]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: ssl: support aliases in crt-store
authorWilliam Lallemand <wlallemand@haproxy.com>
Wed, 17 Apr 2024 15:03:58 +0000 (17:03 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Wed, 17 Apr 2024 15:24:49 +0000 (17:24 +0200)
The crt-store load line now allows to put an alias. This alias is used
as the key in the ckch_tree instead of the certificate. This way an
alias can be referenced in the configuration with the '@/' prefix.

This can only be define with a crt-store.

doc/configuration.txt
src/cfgparse-ssl.c
src/ssl_ckch.c
src/ssl_crtlist.c

index a5176adb740a9310b1872b6313ea300a5065804d..afab750992ee8c0e429f34539c5f45be3c11b43a 100644 (file)
@@ -4744,6 +4744,11 @@ load [crt <filename>] [param*]
 
   Arguments:
 
+    alias <string>     Optional argument. Allow to name the certificate with an
+                       alias, so it can be referenced with it in the
+                       configuration. An alias must be prefixed with '@/' when
+                       called elsewhere in the configuration.
+
     crt <filename>     This argument is mandatory, it loads a PEM which must
                        contain the public certificate but could also contain
                        the intermediate certificates and the private key.
@@ -4772,11 +4777,11 @@ load [crt <filename>] [param*]
 Example:
 
     crt-store
-        load crt "site1.crt" key "site1.key" ocsp "site1.ocsp"
+        load crt "site1.crt" key "site1.key" ocsp "site1.ocsp" alias "site1"
         load crt "site2.crt" key "site2.key"
 
     frontend in
-        bind *:443 ssl crt "site1.crt" crt "site2.crt"
+        bind *:443 ssl crt "@/site1" crt "site2.crt"
 
 4. Proxies
 ----------
index 467fbdad90dd463ba7f9b345ea8f40c11d0c8406..29e4e08b1770dc005dff07d4ecac33b4d72ccb12 100644 (file)
@@ -784,7 +784,7 @@ static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bin
                return ERR_ALERT | ERR_FATAL;
        }
 
-       if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
+       if ((*args[cur_arg + 1] != '@') && (*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
                if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
                    snprintf(path, sizeof(path), "%s/%s",  global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
                        memprintf(err, "'%s' : path too long", args[cur_arg]);
@@ -1828,7 +1828,7 @@ static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct ser
                return ERR_ALERT | ERR_FATAL;
        }
 
-       if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
+       if ((*args[*cur_arg + 1] != '@') && (*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
                memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
        else
                memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
index bd2ffe24f35cee04d5c4e62c3b1548cfcd457888..fea0b9631b1ccd1b75ba5a67dcce202576be9bd8 100644 (file)
@@ -3997,6 +3997,7 @@ static struct cli_kw_list cli_kws = {{ },{
 INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
 
 struct ckch_conf_kws ckch_conf_kws[] = {
+       { "alias",                               -1,                 0, NULL,                                  NULL },
        { "crt",    offsetof(struct ckch_conf, crt),    PARSE_TYPE_STR, ssl_sock_load_pem_into_ckch,           &global_ssl.crt_base },
        { "key",    offsetof(struct ckch_conf, key),    PARSE_TYPE_STR, ssl_sock_load_key_into_ckch,           &global_ssl.key_base },
        { "ocsp",   offsetof(struct ckch_conf, ocsp),   PARSE_TYPE_STR, ssl_sock_load_ocsp_response_from_file, &global_ssl.crt_base },
@@ -4067,8 +4068,9 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
        int cur_arg = 0;
        struct ckch_conf f = {};
        struct ckch_store *c = NULL;
-       char store_path[PATH_MAX];
-       char *store_name;
+       char store_path[PATH_MAX]; /* complete path with crt_base */
+       char alias_name[PATH_MAX]; /* complete alias name with the store prefix '@/' */
+       char *final_name = NULL; /* name used as a key in the ckch_store */
 
        cur_arg++; /* skip "load" */
 
@@ -4081,7 +4083,25 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
                                found = 1;
                                target = (char **)((intptr_t)&f + (ptrdiff_t)ckch_conf_kws[i].offset);
 
-                               if (ckch_conf_kws[i].type == PARSE_TYPE_STR) {
+                               if (strcmp("alias", args[cur_arg]) == 0) {
+                                       int rv;
+
+                                       if (*args[cur_arg] == '/') {
+                                               memprintf(err, "parsing [%s:%d] : cannot parse '%s' value '%s', '/' is forbidden as the first character.\n",
+                                                         file, linenum, args[cur_arg], args[cur_arg + 1]);
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
+                                       }
+
+                                       rv = snprintf(alias_name, sizeof(alias_name), "@%s/%s", "", args[cur_arg + 1]);
+                                       if (rv >= sizeof(alias_name)) {
+                                               memprintf(err, "parsing [%s:%d] : cannot parse '%s' value '%s', too long, max len is %ld.\n",
+                                                         file, linenum, args[cur_arg], args[cur_arg + 1], sizeof(alias_name));
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
+                                       }
+                                       final_name = alias_name;
+                               } else if (ckch_conf_kws[i].type == PARSE_TYPE_STR) {
                                        char **t = target;
 
                                        *t = strdup(args[cur_arg + 1]);
@@ -4132,21 +4152,23 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
                goto out;
        }
 
-       store_name = f.crt;
+       if (!final_name) {
+               final_name = f.crt;
 
-       /* complete the name in the ckch_tree with 'crt-base' */
-       if (global_ssl.crt_base && *f.crt != '/') {
-               int rv = snprintf(store_path, sizeof(store_path), "%s/%s", global_ssl.crt_base, f.crt);
-               if (rv >= sizeof(store_path)) {
-                       memprintf(err, "'%s/%s' : path too long", global_ssl.crt_base, f.crt);
-                       err_code |= ERR_ALERT | ERR_FATAL;
-                       goto out;
+               /* complete the name in the ckch_tree with 'crt-base' */
+               if (global_ssl.crt_base && *f.crt != '/') {
+                       int rv = snprintf(store_path, sizeof(store_path), "%s/%s", global_ssl.crt_base, f.crt);
+                       if (rv >= sizeof(store_path)) {
+                               memprintf(err, "'%s/%s' : path too long", global_ssl.crt_base, f.crt);
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
+                       }
+                       final_name = store_path;
                }
-               store_name = store_path;
        }
 
        /* process and insert the ckch_store */
-       c = ckch_store_new(store_name);
+       c = ckch_store_new(final_name);
        if (!c)
                goto alloc_error;
 
index 3b1f5329502cf0c824ad3c5c90a5aa86b79ae09b..7a7721593210b4b3140603ad7fcdbc818e5cded5 100644 (file)
@@ -575,7 +575,7 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
                        continue;
                }
 
-               if (*crt_path != '/' && global_ssl.crt_base) {
+               if (*crt_path != '@' && *crt_path != '/' && global_ssl.crt_base) {
                        if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > sizeof(path) ||
                            snprintf(path, sizeof(path), "%s/%s",  global_ssl.crt_base, crt_path) > sizeof(path)) {
                                memprintf(err, "parsing [%s:%d]: '%s' : path too long",
@@ -1338,7 +1338,7 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
                *slash = '/';
        }
 
-       if (*cert_path != '/' && global_ssl.crt_base) {
+       if (*cert_path != '@' && *cert_path != '/' && global_ssl.crt_base) {
                if ((strlen(global_ssl.crt_base) + 1 + strlen(cert_path)) > sizeof(path) ||
                    snprintf(path, sizeof(path), "%s/%s",  global_ssl.crt_base, cert_path) > sizeof(path)) {
                        memprintf(&err, "'%s' : path too long", cert_path);