]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: ssl: introduce the ckch instance structure
authorWilliam Lallemand <wlallemand@haproxy.com>
Thu, 3 Oct 2019 22:29:42 +0000 (00:29 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Fri, 11 Oct 2019 15:32:03 +0000 (17:32 +0200)
struct ckch_inst represents an instance of a certificate (ckch_node)
used in a bind_conf. Every sni_ctx created for 1 ckch_node in a
bind_conf are linked in this structure.

This patch allocate the ckch_inst for each bind_conf and inserts the
sni_ctx in its linked list.

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

index e0b1a80d83e9942cd73ded3d0228f7ea770b3ece..0d6ed638eb0e2cf59465eadd23ba8ebe9bbb1b7a 100644 (file)
@@ -39,6 +39,7 @@ struct sni_ctx {
        uint8_t neg;              /* reject if match */
        struct pkey_info kinfo;   /* pkey info */
        struct ssl_bind_conf *conf; /* ssl "bind" conf for the certificate */
+       struct list by_ckch_inst; /* chained in ckch_inst's list of sni_ctx */
        struct ebmb_node name;    /* node holding the servername value */
 };
 
@@ -105,10 +106,23 @@ struct cert_key_and_chain {
 struct ckch_store {
        struct cert_key_and_chain *ckch;
        int multi; /* is it a multi-cert bundle ? */
+       struct list ckch_inst; /* list of ckch_inst which uses this ckch_node */
        struct ebmb_node node;
        char path[0];
 };
 
+/*
+ * This structure describe a ckch instance. An instance is generated for each
+ * bind_conf.  The instance contains a linked list of the sni ctx which uses
+ * the ckch in this bind_conf.
+ *
+ * XXX: the instance may evolve to handle ssl_bind_conf instead of bind_conf.
+ */
+struct ckch_inst {
+       struct bind_conf *bind_conf; /* pointer to the bind_conf that uses this ckch_inst */
+       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 */
+};
 
 #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
 
index c69cb6c8ccc078505022f75e7e79585f3d2be7d8..0ef56e00720d3a7f8e0078ee37aa4fd4122e2d29 100644 (file)
@@ -2740,8 +2740,23 @@ int ssl_sock_load_global_dh_param_from_file(const char *filename)
 }
 #endif
 
-static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
-                                struct pkey_info kinfo, char *name, int order)
+/* Alloc and init a ckch_inst */
+static struct ckch_inst *ckch_inst_new()
+{
+       struct ckch_inst *ckch_inst;
+
+       ckch_inst = calloc(1, sizeof *ckch_inst);
+       if (ckch_inst)
+               LIST_INIT(&ckch_inst->sni_ctx);
+
+       return ckch_inst;
+}
+
+
+/* This function allocates a sni_ctx and adds it to the ckch_inst */
+static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
+                                 struct bind_conf *s, struct ssl_bind_conf *conf,
+                                 struct pkey_info kinfo, char *name, int order)
 {
        struct sni_ctx *sc;
        int wild = 0, neg = 0;
@@ -2793,6 +2808,9 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_b
                        ebst_insert(&s->sni_w_ctx, &sc->name);
                else
                        ebst_insert(&s->sni_ctx, &sc->name);
+
+               if (ckch_inst != NULL) /* TODO: remove this test later once the code is converted */
+                       LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
        }
        return order;
 }
@@ -3113,6 +3131,8 @@ static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err
                goto end;
        }
 
+       LIST_INIT(&ckchs->ckch_inst);
+
        if (!multi) {
 
                if (ssl_sock_load_crt_file_into_ckch(path, ckchs->ckch, err) == 1)
@@ -3177,7 +3197,7 @@ end:
  * TODO: This function shouldn't access files anymore, sctl and ocsp file access
  * should be migrated to the ssl_sock_load_crt_file_into_ckch() function
  */
-static int ssl_sock_load_multi_ckchs(const char *path, struct ckch_store *ckchs,
+static int ssl_sock_load_multi_ckchs(const char *path, struct ckch_store *ckchs, struct ckch_inst *ckch_inst,
                                      struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
                                      char **sni_filter, int fcount, char **err)
 {
@@ -3355,7 +3375,8 @@ static int ssl_sock_load_multi_ckchs(const char *path, struct ckch_store *ckchs,
                }
 
                /* Update SNI Tree */
-               key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
+
+               key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, ckch_inst, bind_conf, ssl_conf,
                                                              kinfo, str, key_combos[i-1].order);
                if (key_combos[i-1].order < 0) {
                        memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
@@ -3405,8 +3426,10 @@ static int ssl_sock_load_multi_ckchs(const char *path, struct ckch_store *ckchs,
 
 #endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
 
-static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
-                                  char **sni_filter, int fcount, char **err)
+static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
+                               struct ckch_inst *ckch_inst, struct bind_conf
+                               *bind_conf, struct ssl_bind_conf *ssl_conf, char
+                               **sni_filter, int fcount, char **err)
 {
        SSL_CTX *ctx;
        int i;
@@ -3456,7 +3479,7 @@ static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs, struc
 
        if (fcount) {
                while (fcount--) {
-                       order = ssl_sock_add_cert_sni(ctx, bind_conf, ssl_conf, kinfo, sni_filter[fcount], order);
+                       order = ssl_sock_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, sni_filter[fcount], order);
                        if (order < 0) {
                                memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
                                return 1;
@@ -3471,7 +3494,7 @@ static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs, struc
                                GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
                                if (name->type == GEN_DNS) {
                                        if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
-                                               order = ssl_sock_add_cert_sni(ctx, bind_conf, ssl_conf, kinfo, str, order);
+                                               order = ssl_sock_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
                                                OPENSSL_free(str);
                                                if (order < 0) {
                                                        memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
@@ -3491,7 +3514,7 @@ static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs, struc
 
                        value = X509_NAME_ENTRY_get_data(entry);
                        if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
-                               order = ssl_sock_add_cert_sni(ctx, bind_conf, ssl_conf, kinfo, str, order);
+                               order = ssl_sock_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
                                OPENSSL_free(str);
                                if (order < 0) {
                                        memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
@@ -3538,6 +3561,10 @@ static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs, struc
                bind_conf->default_ssl_conf = ssl_conf;
        }
 
+       /* everything succeed, the ckch instance can be used */
+       ckch_inst->bind_conf = bind_conf;
+       LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
+
        return 0;
 }
 
@@ -3555,14 +3582,23 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
        int is_bundle;
        int j;
 #endif
+       struct ckch_inst *ckch_inst;
 
        if ((ckchs = ckchs_lookup(path))) {
+               /* For each certificate (or bundle) used in the configuration, create
+                * a certificate instance */
+               ckch_inst = ckch_inst_new();
+               if (!ckch_inst) {
+                       memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
+                                 err && *err ? *err : "", path);
+                       return 1;
+               }
 
                /* we found the ckchs in the tree, we can use it directly */
                if (ckchs->multi)
-                       return ssl_sock_load_multi_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+                       return ssl_sock_load_multi_ckchs(path, ckchs, ckch_inst, bind_conf, NULL, NULL, 0, err);
                else
-                       return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+                       return ssl_sock_load_ckchs(path, ckchs, ckch_inst, bind_conf, NULL, NULL, 0, err);
 
        }
 
@@ -3572,7 +3608,13 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
                        ckchs =  ckchs_load_cert_file(path, 0,  err);
                        if (!ckchs)
                                return 1;
-                       return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+                       ckch_inst = ckch_inst_new();
+                       if (!ckch_inst) {
+                               memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
+                                         err && *err ? *err : "", path);
+                               return 1;
+                       }
+                       return ssl_sock_load_ckchs(path, ckchs, ckch_inst, bind_conf, NULL, NULL, 0, err);
                }
 
                /* strip trailing slashes, including first one */
@@ -3637,8 +3679,15 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
                                                        ckchs =  ckchs_load_cert_file(fp, 1,  err);
                                                if (!ckchs)
                                                        cfgerr++;
-                                               else
-                                                       cfgerr += ssl_sock_load_multi_ckchs(fp, ckchs, bind_conf, NULL, NULL, 0, err);
+                                               else {
+                                                       ckch_inst = ckch_inst_new();
+                                                       if (!ckch_inst) {
+                                                               memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
+                                                                         err && *err ? *err : "", path);
+                                                               return 1;
+                                                       }
+                                                       cfgerr += ssl_sock_load_multi_ckchs(fp, ckchs, ckch_inst, bind_conf, NULL, NULL, 0, err);
+                                               }
 
                                                /* Successfully processed the bundle */
                                                goto ignore_entry;
@@ -3650,8 +3699,15 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
                                        ckchs =  ckchs_load_cert_file(fp, 0,  err);
                                if (!ckchs)
                                        cfgerr++;
-                               else
-                                       cfgerr += ssl_sock_load_ckchs(fp, ckchs, bind_conf, NULL, NULL, 0, err);
+                               else {
+                                       ckch_inst = ckch_inst_new();
+                                       if (!ckch_inst) {
+                                               memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
+                                                         err && *err ? *err : "", path);
+                                               return 1;
+                                       }
+                                       cfgerr += ssl_sock_load_ckchs(fp, ckchs, ckch_inst, bind_conf, NULL, NULL, 0, err);
+                               }
 
 ignore_entry:
                                free(de);
@@ -3665,7 +3721,13 @@ ignore_entry:
        ckchs =  ckchs_load_cert_file(path, 1,  err);
        if (!ckchs)
                return 1;
-       cfgerr = ssl_sock_load_multi_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+       ckch_inst = ckch_inst_new();
+       if (!ckch_inst) {
+               memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
+                         err && *err ? *err : "", path);
+               return 1;
+       }
+       cfgerr = ssl_sock_load_multi_ckchs(path, ckchs, ckch_inst, bind_conf, NULL, NULL, 0, err);
 
        return cfgerr;
 }