break;
}
}
+ /* if the servername is empty look for the default in the wildcard list */
+ if (!*servername)
+ wildp = servername;
/* Look for an ECDSA, RSA and DSA certificate, first in the single
* name and if not found in the wildcard */
int has_rsa_sig = 0, has_ecdsa_sig = 0;
struct sni_ctx *sni_ctx;
const char *servername;
- size_t servername_len;
+ size_t servername_len = 0;
+ int default_lookup = 0; /* did we lookup for a default yet? */
int allow_early = 0;
int i;
goto allow_early;
}
#endif
- /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
- if (!s->strict_sni) {
- HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
- ssl_sock_switchctx_set(ssl, s->default_ctx);
- HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
- goto allow_early;
- }
- goto abort;
+
+ /* no servername field is not compatible with strict-sni */
+ if (s->strict_sni)
+ goto abort;
+
+ /* without servername extension, look for the defaults which is
+ * defined by an empty servername string */
+ servername = "";
+ servername_len = 0;
+ default_lookup = 1;
}
/* extract/check clientHello information */
}
}
+sni_lookup:
/* we need to transform this a NULL-ended string in lowecase */
for (i = 0; i < trash.size && i < servername_len; i++)
trash.area[i] = tolower(servername[i]);
trash.area[i] = 0;
- servername = trash.area;
HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
- sni_ctx = ssl_sock_chose_sni_ctx(s, servername, has_rsa_sig, has_ecdsa_sig);
+ sni_ctx = ssl_sock_chose_sni_ctx(s, trash.area, has_rsa_sig, has_ecdsa_sig);
if (sni_ctx) {
/* switch ctx */
struct ssl_bind_conf *conf = sni_ctx->conf;
HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
#if (!defined SSL_NO_GENERATE_CERTIFICATES)
- if (s->options & BC_O_GENERATE_CERTS && ssl_sock_generate_certificate(servername, s, ssl)) {
+ if (s->options & BC_O_GENERATE_CERTS && ssl_sock_generate_certificate(trash.area, s, ssl)) {
/* switch ctx done in ssl_sock_generate_certificate */
goto allow_early;
}
#endif
- if (!s->strict_sni) {
- /* no certificate match, is the default_ctx */
- HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
- ssl_sock_switchctx_set(ssl, s->default_ctx);
- HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
- goto allow_early;
+
+ if (!s->strict_sni && !default_lookup) {
+ /* we didn't find a SNI, and we didn't look for a default
+ * look again to find a matching default cert */
+ servername = "";
+ servername_len = 0;
+ default_lookup = 1;
+
+ goto sni_lookup;
}
/* We are about to raise an handshake error so the servername extension
const char *wildp = NULL;
struct ebmb_node *node, *n;
struct bind_conf *s = priv;
+ int default_lookup = 0; /* did we lookup for a default yet? */
#ifdef USE_QUIC
const uint8_t *extension_data;
size_t extension_len;
#endif
if (s->strict_sni)
return SSL_TLSEXT_ERR_ALERT_FATAL;
- HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
- ssl_sock_switchctx_set(ssl, s->default_ctx);
- HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
- return SSL_TLSEXT_ERR_NOACK;
+
+ /* without servername extension, look for the defaults which is
+ * defined by an empty servername string */
+ servername = "";
+ default_lookup = 1;
}
+sni_lookup:
+
for (i = 0; i < trash.size; i++) {
if (!servername[i])
break;
wildp = &trash.area[i];
}
trash.area[i] = 0;
+ if(!*trash.area) /* handle the default which in wildcard tree */
+ wildp = trash.area;
HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
node = NULL;
return SSL_TLSEXT_ERR_OK;
}
#endif
- if (s->strict_sni) {
- HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
- return SSL_TLSEXT_ERR_ALERT_FATAL;
- }
- ssl_sock_switchctx_set(ssl, s->default_ctx);
HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
- return SSL_TLSEXT_ERR_OK;
+
+ if (!s->strict_sni && !default_lookup) {
+ /* we didn't find a SNI, and we didn't look for a default
+ * look again to find a matching default cert */
+ servername = "";
+ default_lookup = 1;
+
+ goto sni_lookup;
+ }
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
}
/* switch ctx */
struct bind_conf *s = arg;
int has_rsa_sig = 0, has_ecdsa_sig = 0;
const char *servername;
+ int default_lookup = 0;
struct sni_ctx *sni_ctx;
int i;
servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
if (!servername) {
- /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
- if (!s->strict_sni) {
- HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
- ssl_sock_switchctx_set(ssl, s->default_ctx);
- HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
- goto allow_early;
- }
- goto abort;
+ if (s->strict_sni)
+ goto abort;
+
+ /* without servername extension, look for the defaults which is
+ * defined by an empty servername string */
+ servername = "";
+ default_lookup = 1;
}
/* extract sigalgs and ciphers */
}
}
+sni_lookup:
+
/* we need to transform this into a NULL-ended string in lowecase */
for (i = 0; i < trash.size && servername[i] != '\0'; i++)
trash.area[i] = tolower(servername[i]);
}
HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
- if (!s->strict_sni) {
- /* no certificate match, is the default_ctx */
- HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
- ssl_sock_switchctx_set(ssl, s->default_ctx);
- HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
- goto allow_early;
+ if (!s->strict_sni && !default_lookup) {
+ /* we didn't find a SNI, and we didn't look for a default
+ * look again to find a matching default cert */
+ servername = "";
+ default_lookup = 1;
+
+ goto sni_lookup;
}
/* We are about to raise an handshake error so the servername extension
struct pkey_info kinfo, char *name, int order)
{
struct sni_ctx *sc;
- int wild = 0, neg = 0;
+ int wild = 0, neg = 0, default_crt = 0;
if (*name == '!') {
neg = 1;
if (*name == '*') {
wild = 1;
name++;
+ /* if this was only a '*' filter, this is a default cert */
+ if (!*name)
+ default_crt = 1;
}
/* !* filter is a nop */
if (neg && wild)
return order;
- if (*name) {
+ if (*name || default_crt) {
int j, len;
len = strlen(name);
for (j = 0; j < len && j < trash.size; j++)
else
ebst_insert(&bind_conf->sni_ctx, &sc0->name);
}
-
- /* replace the default_ctx if required with the instance's ctx. */
- if (ckch_inst->is_default) {
- SSL_CTX_free(bind_conf->default_ctx);
- SSL_CTX_up_ref(ckch_inst->ctx);
- bind_conf->default_ctx = ckch_inst->ctx;
- bind_conf->default_inst = ckch_inst;
- }
}
/*