]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
handshake: always accept TLS 1.2 in client hello if we have later protocols enabled
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Tue, 18 Jul 2017 07:23:53 +0000 (09:23 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 19 Feb 2018 14:29:33 +0000 (15:29 +0100)
That is because after TLS 1.3 there is no negotiation of the version using
the Client Hello field, but with an extension.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/handshake.c

index 332349747ad939c5e412e198823c8eccbc057149..36ecc1144014ef54d2826b7230061e7e0b71d186 100644 (file)
@@ -363,10 +363,21 @@ int
 _gnutls_negotiate_legacy_version(gnutls_session_t session,
                          gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
 {
-       int ret;
+       const version_entry_st *vers;
 
-       /* if we do not support that version  */
+       /* if we do not support that version, unless that version is TLS 1.2;
+        * TLS 1.2 is handled separately because it is always advertized under TLS 1.3 or later */
        if (adv_version == GNUTLS_VERSION_UNKNOWN || _gnutls_version_is_supported(session, adv_version) == 0) {
+
+               if (adv_version == GNUTLS_TLS1_2) {
+                       vers = _gnutls_version_max(session);
+                       if (vers->id >= GNUTLS_TLS1_2) {
+                               if (_gnutls_set_current_version(session, adv_version) < 0)
+                                       return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+                               return adv_version;
+                       }
+               }
+
                /* if we get an unknown/unsupported version, then fail if the version we
                 * got is too low to be supported */
                if (!_gnutls_version_is_too_high(session, major, minor))
@@ -375,21 +386,23 @@ _gnutls_negotiate_legacy_version(gnutls_session_t session,
                /* If he requested something we do not support
                 * then we send him the highest we support.
                 */
-               ret = _gnutls_legacy_version_max(session);
-               if (ret == GNUTLS_VERSION_UNKNOWN) {
+               vers = _gnutls_legacy_version_max(session);
+               if (vers == NULL) {
                        /* this check is not really needed.
                         */
                        gnutls_assert();
                        return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
                }
-       } else {
-               ret = adv_version;
-       }
 
-       if (_gnutls_set_current_version(session, ret) < 0)
-               return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+               session->security_parameters.pversion = vers;
 
-       return ret;
+               return vers->id;
+       } else {
+               if (_gnutls_set_current_version(session, adv_version) < 0)
+                       return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+
+               return adv_version;
+       }
 }
 
 /* This function returns:
@@ -873,12 +886,14 @@ _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data,
                /* TLS_FALLBACK_SCSV */
                if (data[i] == GNUTLS_FALLBACK_SCSV_MAJOR &&
                    data[i + 1] == GNUTLS_FALLBACK_SCSV_MINOR) {
-                       unsigned max = _gnutls_legacy_version_max(session);
+                       const version_entry_st *vers = get_version(session);
+                       const version_entry_st *max = _gnutls_version_max(session);
+
                        _gnutls_handshake_log
                            ("HSK[%p]: Received fallback CS\n",
                             session);
 
-                       if (gnutls_protocol_get_version(session) != max)
+                       if (vers != max)
                                return gnutls_assert_val(GNUTLS_E_INAPPROPRIATE_FALLBACK);
                } else if (!scsv_only) {
                        if (peer_clist.size < MAX_CIPHERSUITE_SIZE) {
@@ -1646,9 +1661,7 @@ static int send_client_hello(gnutls_session_t session, int again)
                        if (rehandshake)        /* already negotiated version thus version_max == negotiated version */
                                hver = get_version(session);
                        else    /* new handshake. just get the max */
-                               hver =
-                                   version_to_entry(_gnutls_legacy_version_max
-                                                    (session));
+                               hver = _gnutls_legacy_version_max(session);
                } else {
                        /* we are resuming a session */
                        hver =