]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: ssl: can't use crt-store some certificates in ssl-f-use
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 6 May 2025 19:16:20 +0000 (21:16 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Tue, 6 May 2025 19:36:29 +0000 (21:36 +0200)
When declaring a certificate via the crt-store section, this certificate
can then be used 2 ways in a crt-list:
- only by using its name, without any crt-store options
- or by using the exact set of crt-list option that was defined in the
  crt-store

Since ssl-f-use is generating a crt-list, this is suppose to behave the
same. To achieve this, ckch_conf_parse() will parse the keywords related
to the ckch_conf on the ssl-f-use line and use ckch_conf_cmp() to
compare it to the previous declaration from the crt-store. This
comparaison is only done when any ckch_conf keyword are present.

However, ckch_conf_parse() was done for the crt-list, and the crt-list
does not use the "crt" parameter to declare the name of the certificate,
since it's the first element of the line. So when used with ssl-f-use,
ckch_conf_parse() will always see a "crt" keyword which is a ckch_conf
one, and consider that it will always need to have the exact same set of
paremeters when using the same crt in a crt-store and an ssl-f-use line.

So a simple configuration like this:

   crt-store web
     load crt "foo.com.crt" key "foo.com.key" alias "foo"

   frontend mysite
     bind :443 ssl
     ssl-f-use crt "@web/foo" ssl-min-ver TLSv1.2

Would lead to an error like this:

    config : '@web/foo' in crt-list '(null)' line 0, is already defined with incompatible parameters:
    - different parameter 'key' : previously 'foo.com.key' vs '(null)'

In order to fix the issue, this patch parses the "crt" parameter itself
for ssl-f-use instead of using ckch_conf_parse(), so the keyword would
never be considered as a ckch_conf keyword to compare.

This patch also take care of setting the CKCH_CONF_SET_CRTLIST flag only
if a ckch_conf keyword was found. This flag is used by ckch_conf_cmp()
to know if it has to compare or not.

No backport needed.

src/cfgparse-ssl.c

index d5b49956303e7d01a53294b439505f443aafdb9e..1a786f98d47e5218581f1ea69042a125bb488302 100644 (file)
@@ -2207,7 +2207,29 @@ static int proxy_parse_ssl_f_use(char **args, int section_type, struct proxy *cu
        }
 
        while (*args[cur_arg]) {
-               int found = 0;
+               int foundcrtstore = 0; /* found a crt-store keyword */
+               int found = 0;         /* found a crt-list or crt-store keyword */
+
+               if (strcmp("crt", args[cur_arg]) == 0) {
+                       char path[MAXPATHLEN+1];
+                       const char *arg = args[cur_arg+1];
+
+                       if (*arg != '@' && *arg != '/' && global_ssl.crt_base) {
+                               if ((strlen(global_ssl.crt_base) + 1 + strlen(arg)) > sizeof(path) ||
+                                    snprintf(path, sizeof(path), "%s/%s",  global_ssl.crt_base, arg) > sizeof(path)) {
+                                       memprintf(err, "parsing [%s:%d]: '%s' : path too long",
+                                                 file, linenum, arg);
+                                       cfgerr |= ERR_ALERT | ERR_FATAL;
+                                       goto error;
+                               }
+                               arg = path;
+                       }
+                       free(ckch_conf->crt);
+                       ckch_conf->crt = strdup(arg);
+                       cur_arg += 2;
+                       found = 1;
+                       goto next;
+               }
 
                /* first look for crt-list keywords */
                for (i = 0; ssl_crtlist_kws[i].kw != NULL; i++) {
@@ -2230,10 +2252,11 @@ static int proxy_parse_ssl_f_use(char **args, int section_type, struct proxy *cu
                }
 
                /* then look for ckch_conf keywords */
-               cfgerr |= ckch_conf_parse(args, cur_arg, ckch_conf, &found, file, linenum, err);
+               cfgerr |= ckch_conf_parse(args, cur_arg, ckch_conf, &foundcrtstore, file, linenum, err);
                if (cfgerr & ERR_CODE)
                        goto error;
-               if (found) {
+               if (foundcrtstore) {
+                       found = 1;
                        cur_arg += 2;  /* skip 2 words if the keyword was found */
                        ckch_conf->used = CKCH_CONF_SET_CRTLIST; /* if they are options they must be used everywhere */
                        goto next;
@@ -2261,7 +2284,7 @@ error:
 }
 
 /*
- * After parsing the crt keywords in a frontend/listen section, create the corresponding crt-list and initialize the
+ * After parsing the ssl-f-use keywords in a frontend/listen section, create the corresponding crt-list and initialize the
  * certificates
  */