]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Add DTLS_ESTABLISHED state
authorDavid Woodhouse <dwmw2@infradead.org>
Tue, 20 Apr 2021 12:52:44 +0000 (13:52 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Wed, 21 Apr 2021 12:12:31 +0000 (13:12 +0100)
Cisco DTLS is preauthenticated by PSK or the session resume hack, but
with anonymous DTLS there will be authentication over the DTLS channel
once it has been connected. Add a new state DTLS_ESTABLISHED, and let
DTLS_CONNECTED mean merely *connected* at the transport level.

ESP used to use DTLS_CONNECTING state to indicate that the ESP probes
had been received and we were ready to tell the server (over the TCP
channel) to switch over to use ESP. Use DTLS_CONNECTED for that state
now, since it's a better fit. And DTLS_ESTABLISHED when we've actually
told the server to change.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
dtls.c
esp.c
gpst.c
library.c
oncp.c
openconnect-internal.h
pulse.c

diff --git a/dtls.c b/dtls.c
index fa1bb9816553c2d4fdb312c2e98f1913d0bc521e..96754486038b3cce345f01c52b7a5f279a977830 100644 (file)
--- a/dtls.c
+++ b/dtls.c
@@ -245,8 +245,11 @@ int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
 
        if (vpninfo->dtls_state == DTLS_CONNECTING) {
                dtls_try_handshake(vpninfo, timeout);
-               vpninfo->delay_tunnel_reason = "DTLS MTU detection";
-               return 0;
+               if (vpninfo->dtls_state != DTLS_CONNECTED) {
+                       vpninfo->delay_tunnel_reason = "DTLS MTU detection";
+                       return 0;
+               }
+               return 1;
        }
 
        if (vpninfo->dtls_state == DTLS_SLEEPING) {
@@ -262,6 +265,10 @@ int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                return 0;
        }
 
+       /* Nothing to do here for Cisco DTLS as it is preauthenticated */
+       if (vpninfo->dtls_state == DTLS_CONNECTED)
+               vpninfo->dtls_state = DTLS_ESTABLISHED;
+
        while (readable) {
                int len = MAX(16384, vpninfo->ip_info.mtu);
                unsigned char *buf;
diff --git a/esp.c b/esp.c
index 630e8a70eb16aef83e6427ed4d15c0507880d284..30743cdd2f1e8f6eb4d0b870afb185fcd0f414ae 100644 (file)
--- a/esp.c
+++ b/esp.c
@@ -232,7 +232,7 @@ int esp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                                if (vpninfo->dtls_state == DTLS_SLEEPING) {
                                        vpn_progress(vpninfo, PRG_INFO,
                                                     _("ESP session established with server\n"));
-                                       vpninfo->dtls_state = DTLS_CONNECTING;
+                                       vpninfo->dtls_state = DTLS_CONNECTED;
                                }
                                continue;
                        }
@@ -263,7 +263,7 @@ int esp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                }
        }
 
-       if (vpninfo->dtls_state != DTLS_CONNECTED)
+       if (vpninfo->dtls_state != DTLS_ESTABLISHED)
                return 0;
 
        switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
diff --git a/gpst.c b/gpst.c
index 6b61ff76342c8f78c82ab1c1c7686c74bc99ad02..2ae20db1c50e91bc859afb65fcd7317fac0e98a3 100644 (file)
--- a/gpst.c
+++ b/gpst.c
@@ -1044,11 +1044,12 @@ int gpst_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
         * it if the ESP tunnel is connected or connecting.
         */
        switch (vpninfo->dtls_state) {
-       case DTLS_CONNECTING:
+       case DTLS_CONNECTING: /* Can never happen */
+       case DTLS_CONNECTED:
                openconnect_close_https(vpninfo, 0); /* don't keep stale HTTPS socket */
                vpn_progress(vpninfo, PRG_INFO,
                             _("ESP tunnel connected; exiting HTTPS mainloop.\n"));
-               vpninfo->dtls_state = DTLS_CONNECTED;
+               vpninfo->dtls_state = DTLS_ESTABLISHED;
                /* Now that we are connected, let's ensure timeout is less than
                 * or equal to DTLS DPD/keepalive else we might over sleep, eg
                 * if timeout is set to DTLS attempt period from ESP mainloop,
@@ -1057,7 +1058,7 @@ int gpst_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                        if (*timeout > vpninfo->dtls_times.dpd * 1000)
                                *timeout = vpninfo->dtls_times.dpd * 1000;
                /* fall through */
-       case DTLS_CONNECTED:
+       case DTLS_ESTABLISHED:
                /* Rekey or check-and-resubmit HIP if needed */
                if (keepalive_action(&vpninfo->ssl_times, timeout) == KA_REKEY)
                        goto do_rekey;
@@ -1263,7 +1264,7 @@ int gpst_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
        case KA_KEEPALIVE:
                /* No need to send an explicit keepalive
                   if we have real data to send */
-               if (vpninfo->dtls_state != DTLS_CONNECTED &&
+               if (vpninfo->dtls_state != DTLS_ESTABLISHED &&
                    vpninfo->outgoing_queue.head)
                        break;
                /* fall through */
@@ -1276,7 +1277,7 @@ int gpst_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
 
 
        /* Service outgoing packet queue */
-       while (vpninfo->dtls_state != DTLS_CONNECTED &&
+       while (vpninfo->dtls_state != DTLS_ESTABLISHED &&
               (vpninfo->current_ssl_pkt = dequeue_packet(&vpninfo->outgoing_queue))) {
                struct pkt *this = vpninfo->current_ssl_pkt;
 
@@ -1356,7 +1357,7 @@ int gpst_esp_send_probes(struct openconnect_info *vpninfo)
                monitor_except_fd(vpninfo, dtls);
        }
 
-       for (seq=1; seq <= (vpninfo->dtls_state==DTLS_CONNECTED ? 1 : 3); seq++) {
+       for (seq=1; seq <= (vpninfo->dtls_state==DTLS_ESTABLISHED ? 1 : 3); seq++) {
                memset(pkt, 0, sizeof(*pkt) + sizeof(*iph) + ICMP_MINLEN + sizeof(magic_ping_payload));
                pkt->len = sizeof(struct ip) + ICMP_MINLEN + sizeof(magic_ping_payload);
 
index 2d1c58c48c16e81821fad483159909a0317b001e..c3cdec52c29188e321640a65945b4d4ff57dd2c6 100644 (file)
--- a/library.c
+++ b/library.c
@@ -1184,7 +1184,7 @@ const char *openconnect_get_dtls_compression(struct openconnect_info * vpninfo)
 
 const char *openconnect_get_dtls_cipher(struct openconnect_info *vpninfo)
 {
-       if (vpninfo->dtls_state != DTLS_CONNECTED || !vpninfo->dtls_ssl) {
+       if (vpninfo->dtls_state < DTLS_CONNECTED || !vpninfo->dtls_ssl) {
 #if defined(OPENCONNECT_GNUTLS)
                gnutls_free(vpninfo->dtls_cipher_desc);
 #else
diff --git a/oncp.c b/oncp.c
index 75f2be182219755e387a0f9183b5fbb14825b943..9e2610ee077d998225c815a8296f24a949ac9f0e 100644 (file)
--- a/oncp.c
+++ b/oncp.c
@@ -1071,7 +1071,7 @@ int oncp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                           *sent* over the TCP channel. */
                        vpn_progress(vpninfo, PRG_TRACE,
                                     _("Sent ESP enable control packet\n"));
-                       vpninfo->dtls_state = DTLS_CONNECTED;
+                       vpninfo->dtls_state = DTLS_ESTABLISHED;
                        work_done = 1;
                } else {
                        free(vpninfo->current_ssl_pkt);
@@ -1137,7 +1137,7 @@ int oncp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
        case KA_KEEPALIVE:
                /* No need to send an explicit keepalive
                   if we have real data to send */
-               if (vpninfo->dtls_state != DTLS_CONNECTED && vpninfo->outgoing_queue)
+               if (vpninfo->dtls_state != DTLS_ESTABLISHED && vpninfo->outgoing_queue)
                        break;
 
                vpn_progress(vpninfo, PRG_DEBUG, _("Send CSTP Keepalive\n"));
@@ -1153,7 +1153,7 @@ int oncp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
         * via ESP once the enable message has been *sent* over the
         * TCP channel. Assign it directly to current_ssl_pkt so that
         * we can use it in-place and match against it above. */
-       if (vpninfo->dtls_state == DTLS_CONNECTING) {
+       if (vpninfo->dtls_state == DTLS_CONNECTED) {
                vpninfo->current_ssl_pkt = (struct pkt *)&esp_enable_pkt;
                goto handle_outgoing;
        }
@@ -1163,7 +1163,7 @@ int oncp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                goto handle_outgoing;
 
        /* Service outgoing packet queue, if no DTLS */
-       while (vpninfo->dtls_state != DTLS_CONNECTED &&
+       while (vpninfo->dtls_state != DTLS_ESTABLISHED &&
               (vpninfo->current_ssl_pkt = dequeue_packet(&vpninfo->outgoing_queue))) {
                struct pkt *this = vpninfo->current_ssl_pkt;
 
@@ -1214,7 +1214,7 @@ int oncp_bye(struct openconnect_info *vpninfo, const char *reason)
 void oncp_esp_close(struct openconnect_info *vpninfo)
 {
        /* Tell server to stop sending on ESP channel */
-       if (vpninfo->dtls_state >= DTLS_CONNECTING)
+       if (vpninfo->dtls_state >= DTLS_CONNECTED)
                queue_esp_control(vpninfo, 0);
        esp_close(vpninfo);
 }
@@ -1241,7 +1241,7 @@ int oncp_esp_send_probes(struct openconnect_info *vpninfo)
        if (!pkt)
                return -ENOMEM;
 
-       for (seq=1; seq <= (vpninfo->dtls_state==DTLS_CONNECTED ? 1 : 2); seq++) {
+       for (seq=1; seq <= (vpninfo->dtls_state==DTLS_ESTABLISHED ? 1 : 2); seq++) {
                pkt->len = 1;
                pkt->data[0] = 0;
                pktlen = construct_esp_packet(vpninfo, pkt,
index 3f9699b35c4a1b13cbf4054679164f1bcd2591b4..f03d17aef499fea3e691f7744fd83bd8a9e7211f 100644 (file)
@@ -190,8 +190,9 @@ struct pkt {
 #define DTLS_SECRET    1       /* Secret is present, ready to attempt DTLS */
 #define DTLS_DISABLED  2       /* DTLS was disabled on the *client* side */
 #define DTLS_SLEEPING  3       /* For ESP, sometimes sending probes */
-#define DTLS_CONNECTING        4       /* ESP probe received; must tell server */
-#define DTLS_CONNECTED 5       /* Server informed and should be sending ESP */
+#define DTLS_CONNECTING        4       /* DTLS (re)handshaking. Not used for ESP */
+#define DTLS_CONNECTED 5       /* Transport connected but not yet enabled */
+#define DTLS_ESTABLISHED 6     /* Data path fully established */
 
 /* Not to be confused with OC_PROTO_xxx flags which are library-visible */
 #define PROTO_ANYCONNECT       0
diff --git a/pulse.c b/pulse.c
index 82d4fd15a50e0626395d533e53760c3367d2f2f3..86de19581196d1b1d9f7e0c65fbbb85f6d2e9376 100644 (file)
--- a/pulse.c
+++ b/pulse.c
@@ -2826,7 +2826,7 @@ int pulse_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
        case KA_KEEPALIVE:
                /* No need to send an explicit keepalive
                   if we have real data to send */
-               if (vpninfo->dtls_state != DTLS_CONNECTED &&
+               if (vpninfo->dtls_state != DTLS_ESTABLISHED &&
                    vpninfo->outgoing_queue.head)
                        break;
 
@@ -2839,11 +2839,11 @@ int pulse_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                ;
        }
 #endif
-       if (vpninfo->dtls_state == DTLS_CONNECTING) {
+       if (vpninfo->dtls_state == DTLS_CONNECTED) {
                /* We don't currently do anything to make the server start sending
                 * data packets in ESP instead of over IF-T/TLS. Just go straight
                 * to CONNECTED mode. */
-               vpninfo->dtls_state = DTLS_CONNECTED;
+               vpninfo->dtls_state = DTLS_ESTABLISHED;
                work_done = 1;
        }
 
@@ -2856,7 +2856,7 @@ int pulse_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
        }
 
        /* Service outgoing packet queue, if no DTLS */
-       while (vpninfo->dtls_state != DTLS_CONNECTED &&
+       while (vpninfo->dtls_state != DTLS_ESTABLISHED &&
               (vpninfo->current_ssl_pkt = dequeue_packet(&vpninfo->outgoing_queue))) {
                struct pkt *this = vpninfo->current_ssl_pkt;