]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Added the ability for the server to provide a custom reason string
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Tue, 29 Sep 2009 23:10:14 +0000 (23:10 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Tue, 29 Sep 2009 23:10:14 +0000 (23:10 +0000)
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

manage.c
manage.h
management/management-notes.txt
multi.c
push.c
push.h
ssl.c
ssl.h

index 97d69b45bc3d394a60f085123c5defa5b3f74d65..7c1297968c48669ec63743ba40fc11e1b47b5ffd 100644 (file)
--- a/manage.c
+++ b/manage.c
@@ -94,7 +94,8 @@ man_help ()
 #ifdef MANAGEMENT_DEF_AUTH
   msg (M_CLIENT, "client-auth CID KID    : Authenticate client-id/key-id CID/KID (MULTILINE)");
   msg (M_CLIENT, "client-auth-nt CID KID : Authenticate client-id/key-id CID/KID");
-  msg (M_CLIENT, "client-deny CID KID R  : Deny auth client-id/key-id CID/KID with reason text R");
+  msg (M_CLIENT, "client-deny CID KID R [CR] : Deny auth client-id/key-id CID/KID with log reason");
+  msg (M_CLIENT, "                             text R and optional client reason text CR");
   msg (M_CLIENT, "client-kill CID        : Kill client instance CID");
 #ifdef MANAGEMENT_PF
   msg (M_CLIENT, "client-pf CID          : Define packet filter for client CID (MULTILINE)");
@@ -801,6 +802,7 @@ in_extra_dispatch (struct management *man)
             man->connection.in_extra_kid,
             true,
             NULL,
+            NULL,
             man->connection.in_extra);
          man->connection.in_extra = NULL;
          if (status)
@@ -862,7 +864,7 @@ man_client_auth (struct management *man, const char *cid_str, const char *kid_st
 }
 
 static void
-man_client_deny (struct management *man, const char *cid_str, const char *kid_str, const char *reason)
+man_client_deny (struct management *man, const char *cid_str, const char *kid_str, const char *reason, const char *client_reason)
 {
   unsigned long cid = 0;
   unsigned int kid = 0;
@@ -876,6 +878,7 @@ man_client_deny (struct management *man, const char *cid_str, const char *kid_st
             kid,
             false,
             reason,
+            client_reason,
             NULL);
          if (status)
            {
@@ -1160,8 +1163,8 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
     }
   else if (streq (p[0], "client-deny"))
     {
-      if (man_need (man, p, 3, 0))
-       man_client_deny (man, p[1], p[2], p[3]);
+      if (man_need (man, p, 3, MN_AT_LEAST))
+       man_client_deny (man, p[1], p[2], p[3], p[4]);
     }
   else if (streq (p[0], "client-auth-nt"))
     {
index 23c1fbc7533011934cb5058c4b8e0cd315fd71da..6d6d710cf3ebf0270fd07db866ba14b8f55fe335 100644 (file)
--- a/manage.h
+++ b/manage.h
@@ -162,6 +162,7 @@ struct management_callback
                       const unsigned int mda_key_id,
                       const bool auth,
                       const char *reason,
+                      const char *client_reason,
                       struct buffer_list *cc_config); /* ownership transferred */
 #endif
 #ifdef MANAGEMENT_PF
index 45bfda439bf4f2610e00d5d6dbb85677aa2133f5..1f4cbd0193116ed4bc72a4ceb108080da42399ab 100644 (file)
@@ -308,6 +308,12 @@ COMMAND -- password and username
 
     >PASSWORD:Verification Failed: 'Auth'
 
+  Example 5: The --auth-user-pass username/password failed,
+  and the server provided a custom client-reason-text string
+  using the client-deny server-side management interface command.
+
+    >PASSWORD:Verification Failed: 'custom server-generated string'
+
 COMMAND -- forget-passwords
 ---------------------------
 
@@ -535,7 +541,7 @@ COMMAND -- client-deny  (OpenVPN 2.1 or higher)
 
 Deny a ">CLIENT:CONNECT" or ">CLIENT:REAUTH" request.
 
-  client-deny {CID} {KID} "reason-text"
+  client-deny {CID} {KID} "reason-text" ["client-reason-text"]
 
 CID,KID -- client ID and Key ID.  See documentation for ">CLIENT:"
 notification for more info.
@@ -544,6 +550,9 @@ reason-text: a human-readable message explaining why the authentication
 request was denied.  This message will be output to the OpenVPN log
 file or syslog.
 
+client-reason-text: a message that will be sent to the client as
+part of the AUTH_FAILED message.
+
 Note that client-deny denies a specific Key ID (pertaining to a
 TLS renegotiation).  A client-deny command issued in response to
 an initial TLS key negotiation (notified by ">CLIENT:CONNECT") will
diff --git a/multi.c b/multi.c
index f62563c3da87841bc862a58f4ed614670b0c2db1..ecd1bb3cd311a8a1886064752ec55a1d553e784e 100644 (file)
--- a/multi.c
+++ b/multi.c
@@ -2552,6 +2552,7 @@ management_client_auth (void *arg,
                        const unsigned int mda_key_id,
                        const bool auth,
                        const char *reason,
+                       const char *client_reason,
                        struct buffer_list *cc_config) /* ownership transferred */
 {
   struct multi_context *m = (struct multi_context *) arg;
@@ -2561,7 +2562,7 @@ management_client_auth (void *arg,
 
   if (mi)
     {
-      ret = tls_authenticate_key (mi->context.c2.tls_multi, mda_key_id, auth);
+      ret = tls_authenticate_key (mi->context.c2.tls_multi, mda_key_id, auth, client_reason);
       if (ret)
        {
          if (auth && !mi->connection_established_flag)
@@ -2570,7 +2571,7 @@ management_client_auth (void *arg,
              cc_config_owned = false;
            }
          if (!auth && reason)
-           msg (D_MULTI_LOW, "MULTI: connection rejected: %s", reason);
+           msg (D_MULTI_LOW, "MULTI: connection rejected: %s, CLI:%s", reason, np(client_reason));
        }
     }
   if (cc_config_owned && cc_config)
diff --git a/push.c b/push.c
index 36febe1810b1e9ba25df74253697acbb5226ba4d..142222b0a994fb66cfe5c8ffabac7f53382df6e8 100644 (file)
--- a/push.c
+++ b/push.c
@@ -61,7 +61,13 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
       c->sig->signal_text = "auth-failure";
 #ifdef ENABLE_MANAGEMENT
       if (management)
-       management_auth_failure (management, UP_TYPE_AUTH);
+       {
+         const char *reason = UP_TYPE_AUTH;
+         struct buffer buf = *buffer;
+         if (buf_string_compare_advance (&buf, "AUTH_FAILED,") && BLEN (&buf))
+           reason = BSTR (&buf);
+         management_auth_failure (management, reason);
+       }
 #endif
     }
 }
@@ -71,10 +77,27 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
  * Send auth failed message from server to client.
  */
 void
-send_auth_failed (struct context *c)
+send_auth_failed (struct context *c, const char *client_reason)
 {
+  struct gc_arena gc = gc_new ();
+  static const char auth_failed[] = "AUTH_FAILED";
+  size_t len;
+
   schedule_exit (c, c->options.scheduled_exit_interval);
-  send_control_channel_string (c, "AUTH_FAILED", D_PUSH);
+
+  len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed);
+  if (len > TLS_CHANNEL_BUF_SIZE)
+    len = TLS_CHANNEL_BUF_SIZE;
+
+  {
+    struct buffer buf = alloc_buf_gc (len, &gc);
+    buf_printf (&buf, auth_failed);
+    if (client_reason)
+      buf_printf (&buf, ",%s", client_reason);
+    send_control_channel_string (c, BSTR (&buf), D_PUSH);
+  }
+
+  gc_free (&gc);
 }
 #endif
 
@@ -258,7 +281,8 @@ process_incoming_push_msg (struct context *c,
     {
       if (tls_authentication_status (c->c2.tls_multi, 0) == TLS_AUTHENTICATION_FAILED || c->c2.context_auth == CAS_FAILED)
        {
-         send_auth_failed (c);
+         const char *client_reason = tls_client_reason (c->c2.tls_multi);
+         send_auth_failed (c, client_reason);
          ret = PUSH_MSG_AUTH_FAILURE;
        }
       else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED)
diff --git a/push.h b/push.h
index a48b0777b6de3e31650e169b37c42a092dd3c741..e2813104538f16ed06a6b5ef41b9566970b50aa9 100644 (file)
--- a/push.h
+++ b/push.h
@@ -62,7 +62,7 @@ bool send_push_reply (struct context *c);
 
 void remove_iroutes_from_push_route_list (struct options *o);
 
-void send_auth_failed (struct context *c);
+void send_auth_failed (struct context *c, const char *client_reason);
 
 #endif
 #endif
diff --git a/ssl.c b/ssl.c
index 224721a71e89bc744662e7e74d20750d5fd30bc0..bc8b2daf1f91d95b9ff9b5749951f1b1d97ca835 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -908,6 +908,18 @@ tls_lock_common_name (struct tls_multi *multi)
 #endif
 
 #ifdef MANAGEMENT_DEF_AUTH
+static void
+man_def_auth_set_client_reason (struct tls_multi *multi, const char *client_reason)
+{
+  if (multi->client_reason)
+    {
+      free (multi->client_reason);
+      multi->client_reason = NULL;
+    }
+  if (client_reason && strlen (client_reason))
+    multi->client_reason = string_alloc (client_reason, NULL);
+}
+
 static inline unsigned int
 man_def_auth_test (const struct key_state *ks)
 {
@@ -1077,12 +1089,13 @@ tls_authentication_status (struct tls_multi *multi, const int latency)
 
 #ifdef MANAGEMENT_DEF_AUTH
 bool
-tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth)
+tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason)
 {
   bool ret = false;
   if (multi)
     {
       int i;
+      man_def_auth_set_client_reason (multi, client_reason);
       for (i = 0; i < KEY_SCAN_SIZE; ++i)
        {
          struct key_state *ks = multi->key_scan[i];
@@ -2397,6 +2410,10 @@ tls_multi_free (struct tls_multi *multi, bool clear)
 
   ASSERT (multi);
 
+#ifdef MANAGEMENT_DEF_AUTH
+  man_def_auth_set_client_reason(multi, NULL);  
+#endif
+
   if (multi->locked_cn)
     free (multi->locked_cn);
 
diff --git a/ssl.h b/ssl.h
index e7ccb422ba5ba22d3b8121913a5d237702738a4b..06cd246f3bae0d47689e4ef0097ddb842d54eb6f 100644 (file)
--- a/ssl.h
+++ b/ssl.h
@@ -594,6 +594,11 @@ struct tls_multi
   char *locked_cn;
 
 #ifdef ENABLE_DEF_AUTH
+  /*
+   * An error message to send to client on AUTH_FAILED
+   */
+  char *client_reason;
+
   /* Time of last call to tls_authentication_status */
   time_t tas_last;
 #endif
@@ -695,7 +700,7 @@ int tls_authentication_status (struct tls_multi *multi, const int latency);
 void tls_deauthenticate (struct tls_multi *multi);
 
 #ifdef MANAGEMENT_DEF_AUTH
-bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth);
+bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason);
 #endif
 
 /*
@@ -738,6 +743,16 @@ tls_set_single_session (struct tls_multi *multi)
     multi->opt.single_session = true;
 }
 
+static inline const char *
+tls_client_reason (struct tls_multi *multi)
+{
+#ifdef ENABLE_DEF_AUTH
+  return multi->client_reason;
+#else
+  return NULL;
+#endif
+}
+
 #ifdef ENABLE_PF
 
 static inline bool