]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl/cli: replace the default_ctx during 'commit ssl cert'
authorWilliam Lallemand <wlallemand@haproxy.com>
Mon, 4 Nov 2019 16:56:13 +0000 (17:56 +0100)
committerWilliam Lallemand <wlallemand@haproxy.org>
Mon, 4 Nov 2019 17:16:53 +0000 (18:16 +0100)
If the SSL_CTX of a previous instance (ckch_inst) was used as a
default_ctx, replace the default_ctx of the bind_conf by the first
SSL_CTX inserted in the SNI tree.

Use the RWLOCK of the sni tree to handle the change of the default_ctx.

include/types/ssl_sock.h
src/ssl_sock.c

index 839ef7a7d06f56aca209e9739c0c92a5909abec8..ccc923508214b0715562515fcd4d520512a98d6e 100644 (file)
@@ -126,6 +126,7 @@ struct ckch_store {
 struct ckch_inst {
        struct bind_conf *bind_conf; /* pointer to the bind_conf that uses this ckch_inst */
        struct ssl_bind_conf *ssl_conf; /* pointer to the ssl_conf which is used by every sni_ctx of this inst */
+       int is_default;      /* This instance is used as the default ctx for this bind_conf */
        struct list sni_ctx; /* list of sni_ctx using this ckch_inst */
        struct list by_ckchs; /* chained in ckch_store's list of ckch_inst */
 };
index 88c0a01efd27ba7ef66a66103062272d3ce9a270..ea4a5e0ba7c7773539608fdfe41d0aafbc12300e 100644 (file)
@@ -2237,7 +2237,9 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
 #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;
@@ -2388,7 +2390,9 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
 #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);
        }
 allow_early:
 #ifdef OPENSSL_IS_BORINGSSL
@@ -2433,7 +2437,9 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
 #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;
        }
 
@@ -2469,10 +2475,12 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
                        return SSL_TLSEXT_ERR_OK;
                }
 #endif
-               HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
-               if (s->strict_sni)
+               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;
        }
 
@@ -2776,6 +2784,7 @@ static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf
 
        struct sni_ctx *sc0, *sc0b, *sc1;
        struct ebmb_node *node;
+       int def = 0;
 
        list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
 
@@ -2809,6 +2818,13 @@ static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf
                        ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
                else
                        ebst_insert(&bind_conf->sni_ctx, &sc0->name);
+
+               /* replace the default_ctx if required with the first ctx */
+               if (ckch_inst->is_default && !def) {
+                       /* we don't need to free the default_ctx because the refcount was not incremented */
+                       bind_conf->default_ctx = sc0->ctx;
+                       def = 1;
+               }
        }
 }
 
@@ -3831,6 +3847,7 @@ static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *c
                        if (key_combos[i].ctx) {
                                bind_conf->default_ctx = key_combos[i].ctx;
                                bind_conf->default_ssl_conf = ssl_conf;
+                               ckch_inst->is_default = 1;
                                break;
                        }
                }
@@ -4024,6 +4041,7 @@ static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs,
        if (!bind_conf->default_ctx) {
                bind_conf->default_ctx = ctx;
                bind_conf->default_ssl_conf = ssl_conf;
+               ckch_inst->is_default = 1;
        }
 
        /* everything succeed, the ckch instance can be used */
@@ -10084,6 +10102,10 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
                                        if (errcode & ERR_CODE)
                                                goto error;
 
+                                       /* if the previous ckchi was used as the default */
+                                       if (ckchi->is_default)
+                                               new_inst->is_default = 1;
+
                                        /* display one dot per new instance */
                                        chunk_appendf(trash, ".");
                                        /* link the new ckch_inst to the duplicate */
@@ -10101,7 +10123,7 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
                                if (!new_ckchs)
                                        continue;
 
-                               /* First, we insert every new SNIs in the trees */
+                               /* First, we insert every new SNIs in the trees, also replace the default_ctx */
                                list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
                                        HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
                                        ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);