pushed by server, and that is used to offer a temporary session
token to clients that can be used in place of a password on
subsequent credential challenges.
This accomplishes the security benefit of preventing caching
of the real password while offering most of the advantages
of password caching, i.e. not forcing the user to re-enter
credentials for every TLS renegotiation or network hiccup.
auth-token does two things:
1. if password caching is enabled, the token replaces the
previous password, and
2. if the management interface is active, the token is output
to it:
>PASSWORD:Auth-Token:<token>
Also made a minor change to HALT/RESTART processing when password
caching is enabled. When client receives a HALT or RESTART message,
and if the message text contains a flags block (i.e. [FFF]:message),
if flag 'P' (preserve auth) is present in flags, don't purge the Auth
password. Otherwise do purge the Auth password.
Version 2.1.3o
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7088
e7ae566f-a301-0410-adde-
c780ea21d3b5
send_control_channel_string (struct context *c, const char *str, int msglevel)
{
#if defined(USE_CRYPTO) && defined(USE_SSL)
-
if (c->c2.tls_multi) {
+ struct gc_arena gc = gc_new ();
bool stat;
/* buffered cleartext write onto TLS control channel */
msg (msglevel, "SENT CONTROL [%s]: '%s' (status=%d)",
tls_common_name (c->c2.tls_multi, false),
- str,
+ sanitize_control_message (str, &gc),
(int) stat);
+ gc_free (&gc);
return stat;
}
#endif
msg (M_FATAL, "Error: private key password verification failed");
break;
case AR_INTERACT:
- ssl_purge_auth ();
+ ssl_purge_auth (false);
case AR_NOINTERACT:
c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Password failure error */
break;
man_forget_passwords (struct management *man)
{
#if defined(USE_CRYPTO) && defined(USE_SSL)
- ssl_purge_auth ();
+ ssl_purge_auth (false);
msg (M_CLIENT, "SUCCESS: Passwords were forgotten");
#endif
}
{
#if defined(USE_CRYPTO) && defined(USE_SSL)
if (man->settings.flags & MF_FORGET_DISCONNECT)
- ssl_purge_auth ();
+ ssl_purge_auth (false);
#endif
if (man->settings.flags & MF_SIGNAL) {
int mysig = man_mod_signal (man, SIGUSR1);
msg (M_CLIENT, ">PASSWORD:Verification Failed: '%s'", type);
}
+void
+management_auth_token (struct management *man, const char *token)
+{
+ msg (M_CLIENT, ">PASSWORD:Auth-Token:%s", token);
+}
+
static inline bool
man_persist_state (unsigned int *persistent, const int n)
{
void management_auth_failure (struct management *man, const char *type, const char *reason);
+/*
+ * Echo an authentication token to management interface
+ */
+void management_auth_token (struct management *man, const char *token);
+
/*
* These functions drive the bytecount in/out counters.
*/
}
}
+void
+set_auth_token (struct user_pass *up, const char *token)
+{
+ if (token && strlen(token) && up && up->defined && !up->nocache)
+ {
+ CLEAR (up->password);
+ strncpynt (up->password, token, USER_PASS_LEN);
+ }
+}
+
/*
* Process string received by untrusted peer before
* printing to console or log file.
}
return NULL;
}
+
+/*
+ * Remove SESS_ID_x strings (i.e. auth tokens) from control message
+ * strings so that they will not be output to log file.
+ */
+const char *
+sanitize_control_message(const char *str, struct gc_arena *gc)
+{
+ char *ret = gc_malloc (strlen(str)+1, false, gc);
+ char *cp = ret;
+ bool redact = false;
+
+ strcpy(ret, str);
+ for (;;)
+ {
+ const char c = *cp;
+ if (c == '\0')
+ break;
+ if (c == 'S' && !strncmp(cp, "SESS_ID_", 8))
+ {
+ cp += 7;
+ redact = true;
+ }
+ else
+ {
+ if (c == ',') /* end of session id? */
+ redact = false;
+ if (redact)
+ *cp = '_';
+ }
+ ++cp;
+ }
+ return ret;
+}
void purge_user_pass (struct user_pass *up, const bool force);
+void set_auth_token (struct user_pass *up, const char *token);
+
/*
* Process string received by untrusted peer before
* printing to console or log file.
void configure_path (void);
+const char *sanitize_control_message(const char *str, struct gc_arena *gc);
+
#if AUTO_USERID
void get_user_pass_auto_userid (struct user_pass *up, const char *tag);
#endif
VERIFY_PERMISSION (OPT_P_GENERAL);
ssl_set_auth_nocache ();
}
+ else if (streq (p[0], "auth-token") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_ECHO);
+ ssl_set_auth_token(p[1]);
+#ifdef ENABLE_MANAGEMENT
+ if (management)
+ management_auth_token (management, p[1]);
+#endif
+ }
else if (streq (p[0], "single-session"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- Auth failure error */
break;
case AR_INTERACT:
- ssl_purge_auth ();
+ ssl_purge_auth (false);
case AR_NOINTERACT:
c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Auth failure error */
break;
const char *m = "";
if (buf_advance (&buf, adv) && buf_read_u8 (&buf) == ',' && BLEN (&buf))
m = BSTR (&buf);
+
+ /* preserve cached passwords? */
+ {
+ bool purge = true;
+
+ if (m[0] == '[')
+ {
+ int i;
+ for (i = 1; m[i] != '\0' && m[i] != ']'; ++i)
+ {
+ if (m[i] == 'P')
+ purge = false;
+ }
+ }
+ if (purge)
+ ssl_purge_auth (true);
+ }
+
if (restart)
{
msg (D_STREAM_ERRORS, "Connection reset command was pushed by server ('%s')", m);
unsigned int option_types_found = 0;
int status;
- msg (D_PUSH, "PUSH: Received control message: '%s'", BSTR (buffer));
+ msg (D_PUSH, "PUSH: Received control message: '%s'", sanitize_control_message(BSTR(buffer), &gc));
status = process_incoming_push_msg (c,
buffer,
&option_types_found);
if (status == PUSH_MSG_ERROR)
- msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", BSTR (buffer));
+ msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", sanitize_control_message(BSTR(buffer), &gc));
else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION)
{
if (status == PUSH_MSG_REPLY)
auth_user_pass.nocache = true;
}
+/*
+ * Set an authentication token
+ */
+void
+ssl_set_auth_token (const char *token)
+{
+ set_auth_token (&auth_user_pass, token);
+}
+
/*
* Forget private key password AND auth-user-pass username/password.
*/
void
-ssl_purge_auth (void)
+ssl_purge_auth (const bool auth_user_pass_only)
{
+ if (!auth_user_pass_only)
+ {
#ifdef USE_PKCS11
- pkcs11_logout ();
+ pkcs11_logout ();
#endif
- purge_user_pass (&passbuf, true);
+ purge_user_pass (&passbuf, true);
+ }
purge_user_pass (&auth_user_pass, true);
#ifdef ENABLE_CLIENT_CR
ssl_purge_auth_challenge();
int pem_password_callback (char *buf, int size, int rwflag, void *u);
void auth_user_pass_setup (const char *auth_file);
void ssl_set_auth_nocache (void);
-void ssl_purge_auth (void);
+void ssl_set_auth_token (const char *token);
+void ssl_purge_auth (const bool auth_user_pass_only);
#ifdef ENABLE_CLIENT_CR
dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1.3n])
+define(PRODUCT_VERSION,[2.1.3o])
dnl define the TAP version
define(PRODUCT_TAP_ID,[tap0901])
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])