BUG/MINOR: ssl: certificate choice can be unexpected with openssl >= 1.1.1

It's regression from 9f9b0c6 "BUG/MEDIUM: ECC cert should work with
TLS < v1.2 and openssl >= 1.1.1". Wilcard EC certifcate could be selected
at the expense of specific RSA certificate.
In any case, specific certificate should always selected first, next wildcard.
Reflect this rule in a loop to avoid any bug in certificate selection changes.

Fix issue #394.

It should be backported as far as 1.8.
This commit is contained in:
Emmanuel Hocdet 2019-11-06 16:05:34 +01:00 committed by William Lallemand
parent 4c044e274c
commit 3777e3ad14

View File

@ -2476,32 +2476,16 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
trash.area[i] = 0;
HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
/* lookup in full qualified names */
node = ebst_lookup(&s->sni_ctx, trash.area);
/* lookup a not neg filter */
for (n = node; n; n = ebmb_next_dup(n)) {
if (!container_of(n, struct sni_ctx, name)->neg) {
switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
case TLSEXT_signature_ecdsa:
if (!node_ecdsa)
node_ecdsa = n;
break;
case TLSEXT_signature_rsa:
if (!node_rsa)
node_rsa = n;
break;
default: /* TLSEXT_signature_anonymous|dsa */
if (!node_anonymous)
node_anonymous = n;
break;
}
}
}
if (wildp) {
/* lookup in wildcards names */
node = ebst_lookup(&s->sni_w_ctx, wildp);
for (i = 0; i < 2; i++) {
if (i == 0) /* lookup in full qualified names */
node = ebst_lookup(&s->sni_ctx, trash.area);
else if (i == 1 && wildp) /* lookup in wildcards names */
node = ebst_lookup(&s->sni_w_ctx, wildp);
else
break;
for (n = node; n; n = ebmb_next_dup(n)) {
/* lookup a not neg filter */
if (!container_of(n, struct sni_ctx, name)->neg) {
switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
case TLSEXT_signature_ecdsa:
@ -2519,18 +2503,17 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
}
}
}
}
/* select by key_signature priority order */
node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
: ((has_rsa_sig && node_rsa) ? node_rsa
: (node_anonymous ? node_anonymous
: (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
: node_rsa /* no rsa signature case (far far away) */
)));
if (node) {
/* switch ctx */
struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
/* select by key_signature priority order */
node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
: ((has_rsa_sig && node_rsa) ? node_rsa
: (node_anonymous ? node_anonymous
: (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
: node_rsa /* no rsa signature case (far far away) */
)));
if (node) {
/* switch ctx */
struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
if (conf) {
methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
@ -2539,6 +2522,7 @@ 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);