Browse code

Added the ability for the server to provide a custom reason string when an AUTH_FAILED message is returned to the client. This string can be set by the server-side managment interface and read by the client-side management interface.

For more info, see management/management-notes.txt, and look for
references to "client-reason-text".


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5012 e7ae566f-a301-0410-adde-c780ea21d3b5

james authored on 2009/09/30 08:10:14
Showing 8 changed files
... ...
@@ -94,7 +94,8 @@ man_help ()
94 94
 #ifdef MANAGEMENT_DEF_AUTH
95 95
   msg (M_CLIENT, "client-auth CID KID    : Authenticate client-id/key-id CID/KID (MULTILINE)");
96 96
   msg (M_CLIENT, "client-auth-nt CID KID : Authenticate client-id/key-id CID/KID");
97
-  msg (M_CLIENT, "client-deny CID KID R  : Deny auth client-id/key-id CID/KID with reason text R");
97
+  msg (M_CLIENT, "client-deny CID KID R [CR] : Deny auth client-id/key-id CID/KID with log reason");
98
+  msg (M_CLIENT, "                             text R and optional client reason text CR");
98 99
   msg (M_CLIENT, "client-kill CID        : Kill client instance CID");
99 100
 #ifdef MANAGEMENT_PF
100 101
   msg (M_CLIENT, "client-pf CID          : Define packet filter for client CID (MULTILINE)");
... ...
@@ -801,6 +802,7 @@ in_extra_dispatch (struct management *man)
801 801
 	     man->connection.in_extra_kid,
802 802
 	     true,
803 803
 	     NULL,
804
+	     NULL,
804 805
 	     man->connection.in_extra);
805 806
 	  man->connection.in_extra = NULL;
806 807
 	  if (status)
... ...
@@ -862,7 +864,7 @@ man_client_auth (struct management *man, const char *cid_str, const char *kid_st
862 862
 }
863 863
 
864 864
 static void
865
-man_client_deny (struct management *man, const char *cid_str, const char *kid_str, const char *reason)
865
+man_client_deny (struct management *man, const char *cid_str, const char *kid_str, const char *reason, const char *client_reason)
866 866
 {
867 867
   unsigned long cid = 0;
868 868
   unsigned int kid = 0;
... ...
@@ -876,6 +878,7 @@ man_client_deny (struct management *man, const char *cid_str, const char *kid_st
876 876
 	     kid,
877 877
 	     false,
878 878
 	     reason,
879
+	     client_reason,
879 880
 	     NULL);
880 881
 	  if (status)
881 882
 	    {
... ...
@@ -1160,8 +1163,8 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
1160 1160
     }
1161 1161
   else if (streq (p[0], "client-deny"))
1162 1162
     {
1163
-      if (man_need (man, p, 3, 0))
1164
-	man_client_deny (man, p[1], p[2], p[3]);
1163
+      if (man_need (man, p, 3, MN_AT_LEAST))
1164
+	man_client_deny (man, p[1], p[2], p[3], p[4]);
1165 1165
     }
1166 1166
   else if (streq (p[0], "client-auth-nt"))
1167 1167
     {
... ...
@@ -162,6 +162,7 @@ struct management_callback
162 162
 		       const unsigned int mda_key_id,
163 163
 		       const bool auth,
164 164
 		       const char *reason,
165
+		       const char *client_reason,
165 166
 		       struct buffer_list *cc_config); /* ownership transferred */
166 167
 #endif
167 168
 #ifdef MANAGEMENT_PF
... ...
@@ -308,6 +308,12 @@ COMMAND -- password and username
308 308
 
309 309
     >PASSWORD:Verification Failed: 'Auth'
310 310
 
311
+  Example 5: The --auth-user-pass username/password failed,
312
+  and the server provided a custom client-reason-text string
313
+  using the client-deny server-side management interface command.
314
+
315
+    >PASSWORD:Verification Failed: 'custom server-generated string'
316
+
311 317
 COMMAND -- forget-passwords
312 318
 ---------------------------
313 319
 
... ...
@@ -535,7 +541,7 @@ COMMAND -- client-deny  (OpenVPN 2.1 or higher)
535 535
 
536 536
 Deny a ">CLIENT:CONNECT" or ">CLIENT:REAUTH" request.
537 537
 
538
-  client-deny {CID} {KID} "reason-text"
538
+  client-deny {CID} {KID} "reason-text" ["client-reason-text"]
539 539
 
540 540
 CID,KID -- client ID and Key ID.  See documentation for ">CLIENT:"
541 541
 notification for more info.
... ...
@@ -544,6 +550,9 @@ reason-text: a human-readable message explaining why the authentication
544 544
 request was denied.  This message will be output to the OpenVPN log
545 545
 file or syslog.
546 546
 
547
+client-reason-text: a message that will be sent to the client as
548
+part of the AUTH_FAILED message.
549
+
547 550
 Note that client-deny denies a specific Key ID (pertaining to a
548 551
 TLS renegotiation).  A client-deny command issued in response to
549 552
 an initial TLS key negotiation (notified by ">CLIENT:CONNECT") will
... ...
@@ -2552,6 +2552,7 @@ management_client_auth (void *arg,
2552 2552
 			const unsigned int mda_key_id,
2553 2553
 			const bool auth,
2554 2554
 			const char *reason,
2555
+			const char *client_reason,
2555 2556
 			struct buffer_list *cc_config) /* ownership transferred */
2556 2557
 {
2557 2558
   struct multi_context *m = (struct multi_context *) arg;
... ...
@@ -2561,7 +2562,7 @@ management_client_auth (void *arg,
2561 2561
 
2562 2562
   if (mi)
2563 2563
     {
2564
-      ret = tls_authenticate_key (mi->context.c2.tls_multi, mda_key_id, auth);
2564
+      ret = tls_authenticate_key (mi->context.c2.tls_multi, mda_key_id, auth, client_reason);
2565 2565
       if (ret)
2566 2566
 	{
2567 2567
 	  if (auth && !mi->connection_established_flag)
... ...
@@ -2570,7 +2571,7 @@ management_client_auth (void *arg,
2570 2570
 	      cc_config_owned = false;
2571 2571
 	    }
2572 2572
 	  if (!auth && reason)
2573
-	    msg (D_MULTI_LOW, "MULTI: connection rejected: %s", reason);
2573
+	    msg (D_MULTI_LOW, "MULTI: connection rejected: %s, CLI:%s", reason, np(client_reason));
2574 2574
 	}
2575 2575
     }
2576 2576
   if (cc_config_owned && cc_config)
... ...
@@ -61,7 +61,13 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
61 61
       c->sig->signal_text = "auth-failure";
62 62
 #ifdef ENABLE_MANAGEMENT
63 63
       if (management)
64
-	management_auth_failure (management, UP_TYPE_AUTH);
64
+	{
65
+	  const char *reason = UP_TYPE_AUTH;
66
+	  struct buffer buf = *buffer;
67
+	  if (buf_string_compare_advance (&buf, "AUTH_FAILED,") && BLEN (&buf))
68
+	    reason = BSTR (&buf);
69
+	  management_auth_failure (management, reason);
70
+	}
65 71
 #endif
66 72
     }
67 73
 }
... ...
@@ -71,10 +77,27 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
71 71
  * Send auth failed message from server to client.
72 72
  */
73 73
 void
74
-send_auth_failed (struct context *c)
74
+send_auth_failed (struct context *c, const char *client_reason)
75 75
 {
76
+  struct gc_arena gc = gc_new ();
77
+  static const char auth_failed[] = "AUTH_FAILED";
78
+  size_t len;
79
+
76 80
   schedule_exit (c, c->options.scheduled_exit_interval);
77
-  send_control_channel_string (c, "AUTH_FAILED", D_PUSH);
81
+
82
+  len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed);
83
+  if (len > TLS_CHANNEL_BUF_SIZE)
84
+    len = TLS_CHANNEL_BUF_SIZE;
85
+
86
+  {
87
+    struct buffer buf = alloc_buf_gc (len, &gc);
88
+    buf_printf (&buf, auth_failed);
89
+    if (client_reason)
90
+      buf_printf (&buf, ",%s", client_reason);
91
+    send_control_channel_string (c, BSTR (&buf), D_PUSH);
92
+  }
93
+
94
+  gc_free (&gc);
78 95
 }
79 96
 #endif
80 97
 
... ...
@@ -258,7 +281,8 @@ process_incoming_push_msg (struct context *c,
258 258
     {
259 259
       if (tls_authentication_status (c->c2.tls_multi, 0) == TLS_AUTHENTICATION_FAILED || c->c2.context_auth == CAS_FAILED)
260 260
 	{
261
-	  send_auth_failed (c);
261
+	  const char *client_reason = tls_client_reason (c->c2.tls_multi);
262
+	  send_auth_failed (c, client_reason);
262 263
 	  ret = PUSH_MSG_AUTH_FAILURE;
263 264
 	}
264 265
       else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED)
... ...
@@ -62,7 +62,7 @@ bool send_push_reply (struct context *c);
62 62
 
63 63
 void remove_iroutes_from_push_route_list (struct options *o);
64 64
 
65
-void send_auth_failed (struct context *c);
65
+void send_auth_failed (struct context *c, const char *client_reason);
66 66
 
67 67
 #endif
68 68
 #endif
... ...
@@ -908,6 +908,18 @@ tls_lock_common_name (struct tls_multi *multi)
908 908
 #endif
909 909
 
910 910
 #ifdef MANAGEMENT_DEF_AUTH
911
+static void
912
+man_def_auth_set_client_reason (struct tls_multi *multi, const char *client_reason)
913
+{
914
+  if (multi->client_reason)
915
+    {
916
+      free (multi->client_reason);
917
+      multi->client_reason = NULL;
918
+    }
919
+  if (client_reason && strlen (client_reason))
920
+    multi->client_reason = string_alloc (client_reason, NULL);
921
+}
922
+
911 923
 static inline unsigned int
912 924
 man_def_auth_test (const struct key_state *ks)
913 925
 {
... ...
@@ -1077,12 +1089,13 @@ tls_authentication_status (struct tls_multi *multi, const int latency)
1077 1077
 
1078 1078
 #ifdef MANAGEMENT_DEF_AUTH
1079 1079
 bool
1080
-tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth)
1080
+tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason)
1081 1081
 {
1082 1082
   bool ret = false;
1083 1083
   if (multi)
1084 1084
     {
1085 1085
       int i;
1086
+      man_def_auth_set_client_reason (multi, client_reason);
1086 1087
       for (i = 0; i < KEY_SCAN_SIZE; ++i)
1087 1088
 	{
1088 1089
 	  struct key_state *ks = multi->key_scan[i];
... ...
@@ -2397,6 +2410,10 @@ tls_multi_free (struct tls_multi *multi, bool clear)
2397 2397
 
2398 2398
   ASSERT (multi);
2399 2399
 
2400
+#ifdef MANAGEMENT_DEF_AUTH
2401
+  man_def_auth_set_client_reason(multi, NULL);  
2402
+#endif
2403
+
2400 2404
   if (multi->locked_cn)
2401 2405
     free (multi->locked_cn);
2402 2406
 
... ...
@@ -594,6 +594,11 @@ struct tls_multi
594 594
   char *locked_cn;
595 595
 
596 596
 #ifdef ENABLE_DEF_AUTH
597
+  /*
598
+   * An error message to send to client on AUTH_FAILED
599
+   */
600
+  char *client_reason;
601
+
597 602
   /* Time of last call to tls_authentication_status */
598 603
   time_t tas_last;
599 604
 #endif
... ...
@@ -695,7 +700,7 @@ int tls_authentication_status (struct tls_multi *multi, const int latency);
695 695
 void tls_deauthenticate (struct tls_multi *multi);
696 696
 
697 697
 #ifdef MANAGEMENT_DEF_AUTH
698
-bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth);
698
+bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason);
699 699
 #endif
700 700
 
701 701
 /*
... ...
@@ -738,6 +743,16 @@ tls_set_single_session (struct tls_multi *multi)
738 738
     multi->opt.single_session = true;
739 739
 }
740 740
 
741
+static inline const char *
742
+tls_client_reason (struct tls_multi *multi)
743
+{
744
+#ifdef ENABLE_DEF_AUTH
745
+  return multi->client_reason;
746
+#else
747
+  return NULL;
748
+#endif
749
+}
750
+
741 751
 #ifdef ENABLE_PF
742 752
 
743 753
 static inline bool