]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Implement forwarding client CR_RESPONSE messages to management
authorArne Schwabe <arne@rfc2549.org>
Tue, 19 May 2020 22:00:04 +0000 (00:00 +0200)
committerGert Doering <gert@greenie.muc.de>
Sat, 20 Jun 2020 10:38:45 +0000 (12:38 +0200)
When signalling the client that it should do Challenge response
without reconnecting (IV_SSO=crtext/INFOPRE=CR_TEXT), the server
needs forward the response via the management console.

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: David Sommerseth <davids@openvpn.net>
Message-Id: <20200519220004.25136-6-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg19910.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
doc/management-notes.txt
src/openvpn/forward.c
src/openvpn/manage.c
src/openvpn/manage.h
src/openvpn/push.c
src/openvpn/push.h

index d639c78d005c4fcc93b50ef004d393e187d03fe2..61daaf0793bc3d7ea5afc9a5a7c7a0b8aa8d1278 100644 (file)
@@ -1094,6 +1094,34 @@ CLIENT notification types:
 
     >CLIENT:ADDRESS,{CID},{ADDR},{PRI}
 
+(5) Text based challenge/Response
+
+   >CLIENT:CR_RESPONSE,{CID},{KID},{response_base64}
+   >CLIENT:ENV,name1=val1
+   >CLIENT:ENV,name2=val2
+   >CLIENT:ENV,...
+   >CLIENT:ENV,END
+
+   Using the cr-response command on the client side will trigger this
+   message on the server side.
+
+   CR_RESPONSE notification. The >CR_RESPONSE fulfils the same purpose as the
+   CRV1 response in the traditional challenge/response. See that section
+   below for more details. Since this still uses the same cid as the original
+   response, we do not use the username and opaque session data in this
+   response but only contains the actual response.
+
+   It is important to note that OpenVPN2 merely passes the authentication
+   information and does not do any further checks. (E.g. if a CR was issued
+   before or if multiple CR responses were sent from the client or if
+   data has a valid base64 encoding)
+
+   This interface should be be sufficient for almost all challenge/response
+   system that can be implemented with a single round and base64 encoding the
+   response. Mechanisms that need multiple rounds or more complex answers
+   should implement a different response type than CR_RESPONSE.
+
+
 Variables:
 
 CID --  Client ID, numerical ID for each connecting client, sequence = 0,1,2,...
index 3b088f87d29f1639dabde5f6282aa2f85d700285..885cf126f9e6dc44d2770fc9b52dad8b5e5c149f 100644 (file)
@@ -403,6 +403,10 @@ check_incoming_control_channel_dowork(struct context *c)
             {
                 server_pushed_info(c, &buf, 4);
             }
+            else if (buf_string_match_head_str(&buf, "CR_RESPONSE"))
+            {
+                receive_cr_response(c, &buf);
+            }
             else
             {
                 msg(D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR(&buf));
index 3ebe72ec6ab30474734d4496515faefc43f05cc0..898cb3b3fd50a78a004fa54e6e2afe163b7ef32f 100644 (file)
@@ -2908,7 +2908,7 @@ management_notify_generic(struct management *man, const char *str)
 #ifdef MANAGEMENT_DEF_AUTH
 
 static void
-man_output_peer_info_env(struct management *man, struct man_def_auth_context *mdac)
+man_output_peer_info_env(struct management *man, const struct man_def_auth_context *mdac)
 {
     char line[256];
     if (man->persist.callback.get_peer_info)
@@ -2958,6 +2958,32 @@ management_notify_client_needing_auth(struct management *management,
     }
 }
 
+void
+management_notify_client_cr_response(unsigned mda_key_id,
+                                     const struct man_def_auth_context *mdac,
+                                     const struct env_set *es,
+                                     const char *response)
+{
+    struct gc_arena gc;
+    if (management)
+    {
+        gc = gc_new();
+
+        struct buffer out = alloc_buf_gc(256, &gc);
+        msg(M_CLIENT, ">CLIENT:CR_RESPONSE,%lu,%u,%s",
+            mdac->cid, mda_key_id, response);
+        man_output_extra_env(management, "CLIENT");
+        if (management->connection.env_filter_level>0)
+        {
+            man_output_peer_info_env(management, mdac);
+        }
+        man_output_env(es, true, management->connection.env_filter_level, "CLIENT");
+        management_notify_generic(management, BSTR(&out));
+
+        gc_free(&gc);
+    }
+}
+
 void
 management_connection_established(struct management *management,
                                   struct man_def_auth_context *mdac,
index e28b11d170789c49822482ca602998c5e95dfe12..8c824ca7d2f18069abdeef51047171635761e13d 100644 (file)
@@ -434,6 +434,11 @@ void management_learn_addr(struct management *management,
                            const struct mroute_addr *addr,
                            const bool primary);
 
+void management_notify_client_cr_response(unsigned mda_key_id,
+                                          const struct man_def_auth_context *mdac,
+                                          const struct env_set *es,
+                                          const char *response);
+
 #endif
 
 char *management_query_pk_sig(struct management *man, const char *b64_data,
index a5fa87d89430e4d760459176814d9cd370e8fca2..264604900355b99e7be55dcbf9a4a8ed8ac5027d 100644 (file)
@@ -209,6 +209,28 @@ server_pushed_info(struct context *c, const struct buffer *buffer,
     msg(D_PUSH, "Info command was pushed by server ('%s')", m);
 }
 
+void
+receive_cr_response(struct context *c, const struct buffer *buffer)
+{
+    struct buffer buf = *buffer;
+    const char *m = "";
+
+    if (buf_advance(&buf, 11) && buf_read_u8(&buf) == ',' && BLEN(&buf))
+    {
+        m = BSTR(&buf);
+    }
+#ifdef MANAGEMENT_DEF_AUTH
+    struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE];
+    struct man_def_auth_context *mda = session->opt->mda_context;
+    struct env_set *es = session->opt->es;
+    int key_id = session->key[KS_PRIMARY].key_id;
+
+
+    management_notify_client_cr_response(key_id, mda, es, m);
+#endif
+    msg(D_PUSH, "CR response was sent by client ('%s')", m);
+}
+
 /**
  * Add an option to the given push list by providing a format string.
  *
index 42ab100dc2d79b719e8e19496cd55ee0b013da64..2faf19a6ee3785b5422002057b465e6aa30989c1 100644 (file)
@@ -53,6 +53,8 @@ void server_pushed_signal(struct context *c, const struct buffer *buffer, const
 void server_pushed_info(struct context *c, const struct buffer *buffer,
                         const int adv);
 
+void receive_cr_response(struct context *c, const struct buffer *buffer);
+
 void incoming_push_message(struct context *c, const struct buffer *buffer);
 
 void clone_push_list(struct options *o);