BUG/MEDIUM: ssl: does not look for all SNIs before chosing a certificate

In bug #810, the SNI are not matched correctly, indeed when trying to
match a certificate type in ssl_sock_switchctx_cbk() all SNIs were not
looked up correctly.

In the case you have in a crt-list:

wildcard.subdomain.domain.tld.pem.rsa *.subdomain.domain.tld record.subdomain.domain.tld
record.subdomain.domain.tld.pem.ecdsa record.subdomain.domain.tld another-record.subdomain.domain.tld

If the client only supports RSA and requests
"another-record.subdomain.domain.tld", HAProxy will find the single
ECDSA certificate and won't try to look up for a wildcard RSA
certificate.

This patch fixes the code so we look for all single and
wildcard before chosing the certificate type.

This bug was introduced by commit 3777e3a ("BUG/MINOR: ssl: certificate
choice can be unexpected with openssl >= 1.1.1").

It must be backported as far as 1.8 once it is heavily tested.
This commit is contained in:
William Lallemand 2020-08-14 14:43:35 +02:00 committed by William Lallemand
parent 7adf8f35df
commit 94bd319b26

View File

@ -2352,6 +2352,8 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
/* Look for an ECDSA, RSA and DSA certificate, first in the single
* name and if not found in the wildcard */
for (i = 0; i < 2; i++) {
if (i == 0) /* lookup in full qualified names */
node = ebst_lookup(&s->sni_ctx, trash.area);
@ -2378,7 +2380,10 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
}
}
}
/* select by key_signature priority order */
}
/* Once the certificates are found, select them depending on what is
* supported in the client and by key_signature priority order: EDSA >
* RSA > DSA */
node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
: ((has_rsa_sig && node_rsa) ? node_rsa
: (node_anonymous ? node_anonymous
@ -2398,7 +2403,6 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
goto allow_early;
}
}
HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
#if (!defined SSL_NO_GENERATE_CERTIFICATES)