Browse code

Introduce connection state for reconnecting peer in p2p

We introduce this state to make the reconnecting of a client more
obvious and what is called again instead of making it implicit. The
new state CAS_RECONNECT_PENDING is between CAS_WAITING_OPTIONS_IMPORT and
CAS_CONNECT_DONE as we need to redo some of the steps of the connection
setup, so this new state is going a "half step" back in the state machine.

We also do no longer generate data channel keys for untrusted session. This
is done for clarity but also to allow them being generated after the
session has become actually active.

These changes allow a reconnect in p2p mode with DCO to work as the initial
reconnect working.

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

Arne Schwabe authored on 2022/12/01 01:57:05
Showing 5 changed files
... ...
@@ -174,7 +174,14 @@ check_tls(struct context *c)
174 174
         const int tmp_status = tls_multi_process
175 175
                                    (c->c2.tls_multi, &c->c2.to_link, &c->c2.to_link_addr,
176 176
                                    get_link_socket_info(c), &wakeup);
177
-        if (tmp_status == TLSMP_ACTIVE)
177
+
178
+        if (tmp_status == TLSMP_RECONNECT)
179
+        {
180
+            event_timeout_init(&c->c2.wait_for_connect, 1, now);
181
+            reset_coarse_timers(c);
182
+        }
183
+
184
+        if (tmp_status == TLSMP_ACTIVE || tmp_status == TLSMP_RECONNECT)
178 185
         {
179 186
             update_time();
180 187
             interval_action(&c->c2.tmp_int);
... ...
@@ -196,9 +203,15 @@ check_tls(struct context *c)
196 196
 
197 197
     interval_schedule_wakeup(&c->c2.tmp_int, &wakeup);
198 198
 
199
-    /* Our current code has no good hooks in the TLS machinery to update
199
+    /*
200
+     * Our current code has no good hooks in the TLS machinery to update
200 201
      * DCO keys. So we check the key status after the whole TLS machinery
201 202
      * has been completed and potentially update them
203
+     *
204
+     * We have a hidden state transition from secondary to primary key based
205
+     * on ks->auth_deferred_expire that DCO needs to check that the normal
206
+     * TLS state engine does not check. So we call the \c check_dco_key_status
207
+     * function even if tmp_status does not indicate that something has changed.
202 208
      */
203 209
     check_dco_key_status(c);
204 210
 
... ...
@@ -302,7 +315,6 @@ check_push_request(struct context *c)
302 302
 static void
303 303
 check_connection_established(struct context *c)
304 304
 {
305
-
306 305
     if (connection_established(c))
307 306
     {
308 307
         /* if --pull was specified, send a push request to server */
... ...
@@ -337,7 +349,6 @@ check_connection_established(struct context *c)
337 337
 
338 338
         event_timeout_clear(&c->c2.wait_for_connect);
339 339
     }
340
-
341 340
 }
342 341
 
343 342
 bool
... ...
@@ -2219,7 +2219,14 @@ do_up(struct context *c, bool pulled_options, unsigned int option_types_found)
2219 2219
                 }
2220 2220
             }
2221 2221
         }
2222
+    }
2222 2223
 
2224
+    /* This part needs to be run in p2p mode (without pull) when the client
2225
+     * reconnects to setup various things (like DCO and NCP cipher) that
2226
+     * might have changed from the previous connection.
2227
+     */
2228
+    if (!c->c2.do_up_ran || (c->c2.tls_multi && c->c2.tls_multi->multi_state == CAS_RECONNECT_PENDING))
2229
+    {
2223 2230
         if (c->mode == MODE_POINT_TO_POINT)
2224 2231
         {
2225 2232
             /* ovpn-dco requires adding the peer now, before any option can be set,
... ...
@@ -3249,29 +3249,29 @@ tls_multi_process(struct tls_multi *multi,
3249 3249
 
3250 3250
     if (multi->multi_state >= CAS_CONNECT_DONE)
3251 3251
     {
3252
-        for (int i = 0; i < TM_SIZE; ++i)
3253
-        {
3254
-            struct tls_session *session = &multi->session[i];
3255
-            struct key_state *ks = &session->key[KS_PRIMARY];
3252
+        /* Only generate keys for the TM_ACTIVE session. We defer generating
3253
+         * keys for TM_UNTRUSTED until we actually trust it.
3254
+         * For TM_LAME_DUCK it makes no sense to generate new keys. */
3255
+        struct tls_session *session = &multi->session[TM_ACTIVE];
3256
+        struct key_state *ks = &session->key[KS_PRIMARY];
3256 3257
 
3257
-            if (ks->state == S_ACTIVE && ks->authenticated == KS_AUTH_TRUE)
3258
+        if (ks->state == S_ACTIVE && ks->authenticated == KS_AUTH_TRUE)
3259
+        {
3260
+            /* Session is now fully authenticated.
3261
+            * tls_session_generate_data_channel_keys will move ks->state
3262
+            * from S_ACTIVE to S_GENERATED_KEYS */
3263
+            if (!tls_session_generate_data_channel_keys(multi, session))
3258 3264
             {
3259
-                /* Session is now fully authenticated.
3260
-                * tls_session_generate_data_channel_keys will move ks->state
3261
-                * from S_ACTIVE to S_GENERATED_KEYS */
3262
-                if (!tls_session_generate_data_channel_keys(multi, session))
3263
-                {
3264
-                    msg(D_TLS_ERRORS, "TLS Error: generate_key_expansion failed");
3265
-                    ks->authenticated = KS_AUTH_FALSE;
3266
-                    ks->state = S_ERROR;
3267
-                }
3265
+                msg(D_TLS_ERRORS, "TLS Error: generate_key_expansion failed");
3266
+                ks->authenticated = KS_AUTH_FALSE;
3267
+                ks->state = S_ERROR;
3268
+            }
3268 3269
 
3269
-                /* Update auth token on the client if needed on renegotiation
3270
-                 * (key id !=0) */
3271
-                if (session->key[KS_PRIMARY].key_id != 0)
3272
-                {
3273
-                    resend_auth_token_renegotiation(multi, session);
3274
-                }
3270
+            /* Update auth token on the client if needed on renegotiation
3271
+             * (key id !=0) */
3272
+            if (session->key[KS_PRIMARY].key_id != 0)
3273
+            {
3274
+                resend_auth_token_renegotiation(multi, session);
3275 3275
             }
3276 3276
         }
3277 3277
     }
... ...
@@ -3304,6 +3304,12 @@ tls_multi_process(struct tls_multi *multi,
3304 3304
         move_session(multi, TM_ACTIVE, TM_UNTRUSTED, true);
3305 3305
         msg(D_TLS_DEBUG_LOW, "TLS: tls_multi_process: untrusted session promoted to %strusted",
3306 3306
             tas == TLS_AUTHENTICATION_SUCCEEDED ? "" : "semi-");
3307
+
3308
+        if (multi->multi_state == CAS_CONNECT_DONE)
3309
+        {
3310
+            multi->multi_state = CAS_RECONNECT_PENDING;
3311
+            active = TLSMP_RECONNECT;
3312
+        }
3307 3313
     }
3308 3314
 
3309 3315
     /*
... ...
@@ -212,6 +212,7 @@ void tls_multi_free(struct tls_multi *multi, bool clear);
212 212
 #define TLSMP_INACTIVE 0
213 213
 #define TLSMP_ACTIVE   1
214 214
 #define TLSMP_KILL     2
215
+#define TLSMP_RECONNECT 3
215 216
 
216 217
 /*
217 218
  * Called by the top-level event loop.
... ...
@@ -551,6 +551,10 @@ enum multi_status {
551 551
     CAS_PENDING_DEFERRED_PARTIAL,   /**< at least handler succeeded but another is still pending */
552 552
     CAS_FAILED,                     /**< Option import failed or explicitly denied the client */
553 553
     CAS_WAITING_OPTIONS_IMPORT,     /**< client with pull or p2p waiting for first time options import */
554
+    CAS_RECONNECT_PENDING,          /**< session has already successful established (CAS_CONNECT_DONE)
555
+                                     * but has a reconnect and needs to redo some initialisation, this state is
556
+                                     * similar CAS_WAITING_OPTIONS_IMPORT but skips a few things. The normal connection
557
+                                     * skips this step. */
554 558
     CAS_CONNECT_DONE,
555 559
 };
556 560