]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
openssl-dtls: use DTLS 1.2 for PSK-NEGOTIATE
authorNikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
Wed, 21 Feb 2024 21:24:56 +0000 (22:24 +0100)
committerDaniel Lenski <dlenski@gmail.com>
Thu, 22 Feb 2024 20:53:51 +0000 (12:53 -0800)
Avoid reducing the security level for PSK-NEGOTIATE by
setting DTLS 1.2. This works well because all PSK-NEGOTIATE
ocserv servers are using gnutls that supports DTLS 1.2.

This addresses a previously undetermined issue with DTLS on centos7.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
.gitlab-ci.yml
openssl-dtls.c

index c0fac6139d55f3e410f1deeae658e416fd853da3..ad9c7dbb26c037d27717ef1fe4c6aec44d76ae3e 100644 (file)
@@ -193,9 +193,8 @@ CentOS7/OpenSSL:
 # we don't want pppd to invoke any actual connection scripts
   - mv /etc/ppp /etc/ppp.DISABLED
 # auth-nonascii: UTF-8 support is not available in distro's ocserv package
-# dtls-psk: communication with ocserv fails for undetermined reasons marking as xfail until issue is identified
 # ppp-over-tls-sync: https://gitlab.com/openconnect/openconnect/-/issues/287#note_641198529)
-  - make VERBOSE=1 XFAIL_TESTS="auth-nonascii dtls-psk ppp-over-tls-sync" -j4 check
+  - make VERBOSE=1 XFAIL_TESTS="auth-nonascii ppp-over-tls-sync" -j4 check
   tags:
   - shared
   except:
index 2a061ad8263ccf33259d47b63923464248ecf2fc..00d1fd99d3b241ef00be5c90770a307f97465622 100644 (file)
@@ -329,6 +329,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
        SSL *dtls_ssl;
        BIO *dtls_bio;
        int dtlsver = DTLS1_BAD_VER;
+       int use_psk_neg = 0;
        const char *cipher = vpninfo->dtls_cipher;
 
        if (!cipher) {
@@ -349,7 +350,9 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
                cipher = "AES256-GCM-SHA384";
 #ifndef OPENSSL_NO_PSK
        } else if (!strcmp(cipher, "PSK-NEGOTIATE")) {
-               dtlsver = 0; /* Let it negotiate */
+               use_psk_neg = 1;
+               dtlsver = DTLS1_2_VERSION;
+               cipher = "PSK";
 #endif
 #endif
        }
@@ -406,7 +409,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
                if (vpninfo->proto->proto == PROTO_ANYCONNECT) {
                        /* All the AnyConnect hackery about saved sessions and PSK */
 #if defined (HAVE_DTLS12) && !defined(OPENSSL_NO_PSK)
-                       if (!dtlsver) {
+                       if (use_psk_neg) {
                                SSL_CTX_set_psk_client_callback(vpninfo->dtls_ctx, psk_callback);
                                /* For PSK we override the DTLS master secret with one derived
                                 * from the HTTPS session. */
@@ -422,7 +425,6 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
                                        return -EINVAL;
                                }
                                /* For SSL_CTX_set_cipher_list() */
-                               cipher = "PSK";
                        }
 #endif /* OPENSSL_NO_PSK */
 #ifdef SSL_OP_NO_ENCRYPT_THEN_MAC
@@ -450,7 +452,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
                         * *requires* secure renegotiation support by default. For interop
                         * with Cisco's resumed DTLS sessions, we have to turn that off.
                         */
-                       if (dtlsver)
+                       if (dtlsver && !use_psk_neg)
                                SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
 #endif
 #ifdef SSL_OP_NO_EXTENDED_MASTER_SECRET
@@ -469,7 +471,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
                         * So where OpenSSL provides the choice, tell it not to use extms on
                         * resumed sessions.
                         */
-                       if (dtlsver)
+                       if (dtlsver && !use_psk_neg)
                                SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_NO_EXTENDED_MASTER_SECRET);
 #endif
                        if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, cipher)) {
@@ -511,7 +513,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
                /* Where they only do DTLSv1, they also don't cope with secure renegotiation */
                if (dtlsver == DTLS1_VERSION)
                        SSL_set_options(dtls_ssl, SSL_OP_LEGACY_SERVER_CONNECT);
-       } else if (dtlsver) {
+       } else if (dtlsver && !use_psk_neg) {
                /* This is the actual Cisco AnyConnect method, using session resume */
                STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(dtls_ssl);
                const SSL_CIPHER *ssl_ciph = NULL;
@@ -561,7 +563,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
                /* We don't need our own refcount on it any more */
                SSL_SESSION_free(dtls_session);
 
-       } else if (vpninfo->dtls_app_id_size > 0) {
+       } else if (use_psk_neg) {
                /*
                 * For ocserv PSK-NEGOTIATE we abuse the session resume
                 * protocol just to pass an 'App ID' in our ClientHello
@@ -569,7 +571,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
                 * and isn't actually going to be resumed at all.
                 */
                const uint8_t cs[2] = {0x00, 0x2F}; /* RSA-AES-128 */
-               dtls_session = generate_dtls_session(vpninfo, DTLS1_VERSION,
+               dtls_session = generate_dtls_session(vpninfo, dtlsver,
                                                     SSL_CIPHER_find(dtls_ssl, cs),
                                                     1);
                if (!dtls_session) {