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.
This commit is contained in:
William Lallemand 2025-05-06 21:16:20 +02:00
parent b3b282d2ee
commit fbceabbccf

View 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
*/