summaryrefslogtreecommitdiff
path: root/lib/priority.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2018-11-20 11:30:22 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-11-27 12:52:23 +0100
commit8979d4072d2017c2a58d95d8d4ccb9a1790baa8b (patch)
tree364fa646f8530c83ec8a9d82b8b772c4e6de759a /lib/priority.c
parentf7143c4eb99ddbd5bf1b972244f24a0ff7ce22e3 (diff)
downloadgnutls-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.c21
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);