diff options
-rw-r--r-- | forward.c | 5 | ||||
-rw-r--r-- | init.c | 2 | ||||
-rw-r--r-- | manage.c | 10 | ||||
-rw-r--r-- | manage.h | 5 | ||||
-rw-r--r-- | misc.c | 44 | ||||
-rw-r--r-- | misc.h | 4 | ||||
-rw-r--r-- | options.c | 9 | ||||
-rw-r--r-- | push.c | 24 | ||||
-rw-r--r-- | ssl.c | 18 | ||||
-rw-r--r-- | ssl.h | 3 | ||||
-rw-r--r-- | version.m4 | 2 |
11 files changed, 113 insertions, 13 deletions
@@ -232,8 +232,8 @@ bool 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 */ @@ -250,9 +250,10 @@ send_control_channel_string (struct context *c, const char *str, int msglevel) 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 @@ -1929,7 +1929,7 @@ do_init_crypto_tls_c1 (struct context *c) 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; @@ -698,7 +698,7 @@ static void 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 } @@ -1682,7 +1682,7 @@ man_reset_client_socket (struct management *man, const bool exiting) { #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); @@ -2515,6 +2515,12 @@ management_auth_failure (struct management *man, const char *type, const char *r 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) { @@ -472,6 +472,11 @@ void management_echo (struct management *man, const char *string, const bool pul 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. */ @@ -1695,6 +1695,16 @@ purge_user_pass (struct user_pass *up, const bool force) } } +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. @@ -2363,3 +2373,37 @@ openvpn_basename (const char *path) } 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; +} @@ -306,6 +306,8 @@ void fail_user_pass (const char *prefix, 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. @@ -327,6 +329,8 @@ void openvpn_sleep (const int n); 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 @@ -5802,6 +5802,15 @@ add_option (struct options *options, 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); @@ -52,7 +52,7 @@ receive_auth_failed (struct context *c, const struct buffer *buffer) 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; @@ -95,6 +95,24 @@ server_pushed_signal (struct context *c, const struct buffer *buffer, const bool 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); @@ -166,7 +184,7 @@ incoming_push_message (struct context *c, const struct buffer *buffer) 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, @@ -175,7 +193,7 @@ incoming_push_message (struct context *c, const struct buffer *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) @@ -318,15 +318,27 @@ ssl_set_auth_nocache (void) } /* + * 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(); @@ -722,7 +722,8 @@ void pem_password_setup (const char *auth_file); 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 @@ -1,5 +1,5 @@ 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]) |