From: William Lallemand Date: Tue, 6 May 2025 19:16:20 +0000 (+0200) Subject: BUG/MINOR: ssl: can't use crt-store some certificates in ssl-f-use X-Git-Tag: v3.2-dev15~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fbceabbccf61c3869c71c6d6494c155718076a78;p=thirdparty%2Fhaproxy.git BUG/MINOR: ssl: can't use crt-store some certificates in ssl-f-use 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. --- diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c index d5b499563..1a786f98d 100644 --- a/src/cfgparse-ssl.c +++ b/src/cfgparse-ssl.c @@ -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 */