Browse code

Make waiting on auth an explicit state in the context state machine

Previously we relied on checking tls_authentication_status to check
wether to determine if the context auth state is actually valid or not.
This patch eliminates that check by introducing waiting on the
authentication as extra state in the context auth, state machine.

The simplification and reorganization of the state machine in this
and the previous patches also eliminates a number of corner cases,
including the specific one that lead to CVE-2020-15078.

Patch v3: Fix ccd config from management being ignored
Patch v4: Fix race condition, we need to accept the config from
management if we are in CAS_WAITING_AUTH or earlier states
and not just in CAS_WAITING_AUTH state

CVE: 2020-15078

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <20210604143938.779193-1-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg22491.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Arne Schwabe authored on 2021/06/04 23:39:38
Showing 3 changed files
... ...
@@ -2596,11 +2596,6 @@ static const multi_client_connect_handler client_connect_handlers[] = {
2596 2596
 static void
2597 2597
 multi_connection_established(struct multi_context *m, struct multi_instance *mi)
2598 2598
 {
2599
-    if (tls_authentication_status(mi->context.c2.tls_multi) != TLS_AUTHENTICATION_SUCCEEDED)
2600
-    {
2601
-        return;
2602
-    }
2603
-
2604 2599
     /* We are only called for the CAS_PENDING_x states, so we
2605 2600
      * can ignore other states here */
2606 2601
     bool from_deferred = (mi->context.c2.tls_multi->multi_state != CAS_PENDING);
... ...
@@ -3970,7 +3965,7 @@ management_client_auth(void *arg,
3970 3970
         {
3971 3971
             if (auth)
3972 3972
             {
3973
-                if (is_cas_pending(mi->context.c2.tls_multi->multi_state))
3973
+                if (mi->context.c2.tls_multi->multi_state <= CAS_WAITING_AUTH)
3974 3974
                 {
3975 3975
                     set_cc_config(mi, cc_config);
3976 3976
                     cc_config_owned = false;
... ...
@@ -2810,7 +2810,7 @@ tls_process(struct tls_multi *multi,
2810 2810
                     if (session->opt->mode == MODE_SERVER)
2811 2811
                     {
2812 2812
                         /* On a server we continue with running connect scripts next */
2813
-                        multi->multi_state = CAS_PENDING;
2813
+                        multi->multi_state = CAS_WAITING_AUTH;
2814 2814
                     }
2815 2815
                     else
2816 2816
                     {
... ...
@@ -3136,6 +3136,13 @@ tls_multi_process(struct tls_multi *multi,
3136 3136
 
3137 3137
     enum tls_auth_status tas = tls_authentication_status(multi);
3138 3138
 
3139
+    /* If we have successfully authenticated and are still waiting for the authentication to finish
3140
+     * move the state machine for the multi context forward */
3141
+    if (multi->multi_state == CAS_WAITING_AUTH && tas == TLS_AUTHENTICATION_SUCCEEDED)
3142
+    {
3143
+        multi->multi_state = CAS_PENDING;
3144
+    }
3145
+
3139 3146
     /*
3140 3147
      * If lame duck session expires, kill it.
3141 3148
      */
... ...
@@ -511,6 +511,7 @@ struct tls_session
511 511
  * connect scripts/plugins */
512 512
 enum multi_status {
513 513
     CAS_NOT_CONNECTED,
514
+    CAS_WAITING_AUTH,               /**< TLS connection established but deferred auth not finished */
514 515
     CAS_PENDING,
515 516
     CAS_PENDING_DEFERRED,
516 517
     CAS_PENDING_DEFERRED_PARTIAL,   /**< at least handler succeeded, no result yet*/