Browse code

Added "auth-token" client directive, which is intended to be 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

James Yonan authored on 2011/03/27 06:16:40
Showing 11 changed files
... ...
@@ -232,8 +232,8 @@ bool
232 232
 send_control_channel_string (struct context *c, const char *str, int msglevel)
233 233
 {
234 234
 #if defined(USE_CRYPTO) && defined(USE_SSL)
235
-
236 235
   if (c->c2.tls_multi) {
236
+    struct gc_arena gc = gc_new ();
237 237
     bool stat;
238 238
 
239 239
     /* buffered cleartext write onto TLS control channel */
... ...
@@ -250,9 +250,10 @@ send_control_channel_string (struct context *c, const char *str, int msglevel)
250 250
 
251 251
     msg (msglevel, "SENT CONTROL [%s]: '%s' (status=%d)",
252 252
 	 tls_common_name (c->c2.tls_multi, false),
253
-	 str,
253
+	 sanitize_control_message (str, &gc),
254 254
 	 (int) stat);
255 255
 
256
+    gc_free (&gc);
256 257
     return stat;
257 258
   }
258 259
 #endif
... ...
@@ -1929,7 +1929,7 @@ do_init_crypto_tls_c1 (struct context *c)
1929 1929
 	      msg (M_FATAL, "Error: private key password verification failed");
1930 1930
 	      break;
1931 1931
 	    case AR_INTERACT:
1932
-	      ssl_purge_auth ();
1932
+	      ssl_purge_auth (false);
1933 1933
 	    case AR_NOINTERACT:
1934 1934
 	      c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Password failure error */
1935 1935
 	      break;
... ...
@@ -698,7 +698,7 @@ static void
698 698
 man_forget_passwords (struct management *man)
699 699
 {
700 700
 #if defined(USE_CRYPTO) && defined(USE_SSL)
701
-  ssl_purge_auth ();
701
+  ssl_purge_auth (false);
702 702
   msg (M_CLIENT, "SUCCESS: Passwords were forgotten");
703 703
 #endif
704 704
 }
... ...
@@ -1682,7 +1682,7 @@ man_reset_client_socket (struct management *man, const bool exiting)
1682 1682
     {
1683 1683
 #if defined(USE_CRYPTO) && defined(USE_SSL)
1684 1684
       if (man->settings.flags & MF_FORGET_DISCONNECT)
1685
-	ssl_purge_auth ();
1685
+	ssl_purge_auth (false);
1686 1686
 #endif
1687 1687
       if (man->settings.flags & MF_SIGNAL) {
1688 1688
       	  int mysig = man_mod_signal (man, SIGUSR1);
... ...
@@ -2515,6 +2515,12 @@ management_auth_failure (struct management *man, const char *type, const char *r
2515 2515
     msg (M_CLIENT, ">PASSWORD:Verification Failed: '%s'", type);
2516 2516
 }
2517 2517
 
2518
+void
2519
+management_auth_token (struct management *man, const char *token)
2520
+{
2521
+  msg (M_CLIENT, ">PASSWORD:Auth-Token:%s", token);  
2522
+}
2523
+
2518 2524
 static inline bool
2519 2525
 man_persist_state (unsigned int *persistent, const int n)
2520 2526
 {
... ...
@@ -472,6 +472,11 @@ void management_echo (struct management *man, const char *string, const bool pul
472 472
 void management_auth_failure (struct management *man, const char *type, const char *reason);
473 473
 
474 474
 /*
475
+ * Echo an authentication token to management interface
476
+ */
477
+void management_auth_token (struct management *man, const char *token);
478
+
479
+/*
475 480
  * These functions drive the bytecount in/out counters.
476 481
  */
477 482
 
... ...
@@ -1695,6 +1695,16 @@ purge_user_pass (struct user_pass *up, const bool force)
1695 1695
     }
1696 1696
 }
1697 1697
 
1698
+void
1699
+set_auth_token (struct user_pass *up, const char *token)
1700
+{
1701
+  if (token && strlen(token) && up && up->defined && !up->nocache)
1702
+    {
1703
+      CLEAR (up->password);
1704
+      strncpynt (up->password, token, USER_PASS_LEN);
1705
+    }
1706
+}
1707
+
1698 1708
 /*
1699 1709
  * Process string received by untrusted peer before
1700 1710
  * printing to console or log file.
... ...
@@ -2363,3 +2373,37 @@ openvpn_basename (const char *path)
2363 2363
     }
2364 2364
   return NULL;
2365 2365
 }
2366
+
2367
+/*
2368
+ * Remove SESS_ID_x strings (i.e. auth tokens) from control message
2369
+ * strings so that they will not be output to log file.
2370
+ */
2371
+const char *
2372
+sanitize_control_message(const char *str, struct gc_arena *gc)
2373
+{
2374
+  char *ret = gc_malloc (strlen(str)+1, false, gc);
2375
+  char *cp = ret;
2376
+  bool redact = false;
2377
+
2378
+  strcpy(ret, str);
2379
+  for (;;)
2380
+    {
2381
+      const char c = *cp;
2382
+      if (c == '\0')
2383
+	  break;
2384
+      if (c == 'S' && !strncmp(cp, "SESS_ID_", 8))
2385
+	{
2386
+	  cp += 7;
2387
+	  redact = true;
2388
+	}
2389
+      else
2390
+	{
2391
+	  if (c == ',') /* end of session id? */
2392
+	    redact = false;
2393
+	  if (redact)
2394
+	    *cp = '_';
2395
+	}
2396
+      ++cp;
2397
+    }
2398
+  return ret;
2399
+}
... ...
@@ -306,6 +306,8 @@ void fail_user_pass (const char *prefix,
306 306
 
307 307
 void purge_user_pass (struct user_pass *up, const bool force);
308 308
 
309
+void set_auth_token (struct user_pass *up, const char *token);
310
+
309 311
 /*
310 312
  * Process string received by untrusted peer before
311 313
  * printing to console or log file.
... ...
@@ -327,6 +329,8 @@ void openvpn_sleep (const int n);
327 327
 
328 328
 void configure_path (void);
329 329
 
330
+const char *sanitize_control_message(const char *str, struct gc_arena *gc);
331
+
330 332
 #if AUTO_USERID
331 333
 void get_user_pass_auto_userid (struct user_pass *up, const char *tag);
332 334
 #endif
... ...
@@ -5802,6 +5802,15 @@ add_option (struct options *options,
5802 5802
       VERIFY_PERMISSION (OPT_P_GENERAL);
5803 5803
       ssl_set_auth_nocache ();
5804 5804
     }
5805
+  else if (streq (p[0], "auth-token") && p[1])
5806
+    {
5807
+      VERIFY_PERMISSION (OPT_P_ECHO);
5808
+      ssl_set_auth_token(p[1]);
5809
+#ifdef ENABLE_MANAGEMENT
5810
+      if (management)
5811
+	management_auth_token (management, p[1]);
5812
+#endif
5813
+    }
5805 5814
   else if (streq (p[0], "single-session"))
5806 5815
     {
5807 5816
       VERIFY_PERMISSION (OPT_P_GENERAL);
... ...
@@ -52,7 +52,7 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
52 52
 	  c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- Auth failure error */
53 53
 	  break;
54 54
 	case AR_INTERACT:
55
-	  ssl_purge_auth ();
55
+	  ssl_purge_auth (false);
56 56
 	case AR_NOINTERACT:
57 57
 	  c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Auth failure error */
58 58
 	  break;
... ...
@@ -95,6 +95,24 @@ server_pushed_signal (struct context *c, const struct buffer *buffer, const bool
95 95
       const char *m = "";
96 96
       if (buf_advance (&buf, adv) && buf_read_u8 (&buf) == ',' && BLEN (&buf))
97 97
 	m = BSTR (&buf);
98
+
99
+      /* preserve cached passwords? */
100
+      {
101
+	bool purge = true;
102
+
103
+	if (m[0] == '[')
104
+	  {
105
+	    int i;
106
+	    for (i = 1; m[i] != '\0' && m[i] != ']'; ++i)
107
+	      {
108
+		if (m[i] == 'P')
109
+		  purge = false;
110
+	      }
111
+	  }
112
+	if (purge)
113
+	  ssl_purge_auth (true);
114
+      }
115
+
98 116
       if (restart)
99 117
 	{
100 118
 	  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)
166 166
   unsigned int option_types_found = 0;
167 167
   int status;
168 168
 
169
-  msg (D_PUSH, "PUSH: Received control message: '%s'", BSTR (buffer));
169
+  msg (D_PUSH, "PUSH: Received control message: '%s'", sanitize_control_message(BSTR(buffer), &gc));
170 170
 
171 171
   status = process_incoming_push_msg (c,
172 172
 				      buffer,
... ...
@@ -175,7 +193,7 @@ incoming_push_message (struct context *c, const struct buffer *buffer)
175 175
 				      &option_types_found);
176 176
 
177 177
   if (status == PUSH_MSG_ERROR)
178
-    msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", BSTR (buffer));
178
+    msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", sanitize_control_message(BSTR(buffer), &gc));
179 179
   else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION)
180 180
     {
181 181
       if (status == PUSH_MSG_REPLY)
... ...
@@ -318,15 +318,27 @@ ssl_set_auth_nocache (void)
318 318
 }
319 319
 
320 320
 /*
321
+ * Set an authentication token
322
+ */
323
+void
324
+ssl_set_auth_token (const char *token)
325
+{
326
+  set_auth_token (&auth_user_pass, token);
327
+}
328
+
329
+/*
321 330
  * Forget private key password AND auth-user-pass username/password.
322 331
  */
323 332
 void
324
-ssl_purge_auth (void)
333
+ssl_purge_auth (const bool auth_user_pass_only)
325 334
 {
335
+  if (!auth_user_pass_only)
336
+    {
326 337
 #ifdef USE_PKCS11
327
-  pkcs11_logout ();
338
+      pkcs11_logout ();
328 339
 #endif
329
-  purge_user_pass (&passbuf, true);
340
+      purge_user_pass (&passbuf, true);
341
+    }
330 342
   purge_user_pass (&auth_user_pass, true);
331 343
 #ifdef ENABLE_CLIENT_CR
332 344
   ssl_purge_auth_challenge();
... ...
@@ -722,7 +722,8 @@ void pem_password_setup (const char *auth_file);
722 722
 int pem_password_callback (char *buf, int size, int rwflag, void *u);
723 723
 void auth_user_pass_setup (const char *auth_file);
724 724
 void ssl_set_auth_nocache (void);
725
-void ssl_purge_auth (void);
725
+void ssl_set_auth_token (const char *token);
726
+void ssl_purge_auth (const bool auth_user_pass_only);
726 727
 
727 728
 
728 729
 #ifdef ENABLE_CLIENT_CR
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1.3n])
2
+define(PRODUCT_VERSION,[2.1.3o])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])