diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-11-20 11:30:22 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-11-27 12:52:23 +0100 |
commit | 8979d4072d2017c2a58d95d8d4ccb9a1790baa8b (patch) | |
tree | 364fa646f8530c83ec8a9d82b8b772c4e6de759a /lib/priority.c | |
parent | f7143c4eb99ddbd5bf1b972244f24a0ff7ce22e3 (diff) | |
download | gnutls-tmp-tls10-tls13-fix.tar.gz |
Prevent applications from combining legacy versions of TLS with TLS1.3tmp-tls10-tls13-fix
It can happen that an application due to a misconfiguration, enables TLS1.3
in combination with TLS1.0 or TLS1.1 only. In that case a server which is
unaware of the TLS1.3 protocol will reply by selecting the TLS1.2 protocol
instead and that answer will be rejected by the client. With this change
we ensure that TLS1.3 is not enabled in these problematic scenarios.
Resolves: #621
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'lib/priority.c')
-rw-r--r-- | lib/priority.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/lib/priority.c b/lib/priority.c index 11ff9ddce5..a8223a5308 100644 --- a/lib/priority.c +++ b/lib/priority.c @@ -1226,6 +1226,7 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) const version_entry_st *tlsmin = NULL; const version_entry_st *dtlsmin = NULL; unsigned have_tls13 = 0, have_srp = 0; + unsigned have_pre_tls12 = 0, have_tls12 = 0; unsigned have_psk = 0, have_null = 0, have_rsa_psk = 0; /* have_psk indicates that a PSK key exchange compatible @@ -1270,14 +1271,20 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) if (vers->tls13_sem) have_tls13 = 1; + if (vers->id == GNUTLS_TLS1_2) + have_tls12 = 1; + else if (vers->id < GNUTLS_TLS1_2) + have_pre_tls12 = 1; + if (tlsmax == NULL || vers->age > tlsmax->age) tlsmax = vers; if (tlsmin == NULL || vers->age < tlsmin->age) tlsmin = vers; } else { /* dtls */ tls_sig_sem |= vers->tls_sig_sem; - if (vers->tls13_sem) - have_tls13 = 1; + + /* we need to introduce similar handling to above + * when DTLS1.3 is supported */ if (dtlsmax == NULL || vers->age > dtlsmax->age) dtlsmax = vers; @@ -1400,11 +1407,15 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) if (unlikely(priority_cache->cs.size == 0)) return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET); - /* when TLS 1.3 is available we must have groups set */ - if (unlikely(!have_psk && tlsmax && tlsmax->id >= GNUTLS_TLS1_3 && priority_cache->groups.size == 0)) { + /* when TLS 1.3 is available we must have groups set; additionally + * we require TLS1.2 to be enabled if TLS1.3 is asked for, and + * a pre-TLS1.2 protocol is there; that is because servers which + * do not support TLS1.3 will negotiate TLS1.2 if seen a TLS1.3 handshake */ + if (unlikely((!have_psk && tlsmax && tlsmax->id >= GNUTLS_TLS1_3 && priority_cache->groups.size == 0)) || + (!have_tls12 && have_pre_tls12 && have_tls13)) { for (i = 0; i < priority_cache->protocol.num_priorities; i++) { vers = version_to_entry(priority_cache->protocol.priorities[i]); - if (!vers) + if (!vers || vers->transport != GNUTLS_STREAM) continue; REMOVE_TLS13_IN_LOOP(vers, i); |