From ffea2e1a135d7db6c227f46b8906aff89bb38606 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Thu, 18 Apr 2024 15:54:16 +0200 Subject: [PATCH] MEDIUM: ssl: support a named crt-store section This patch introduces named crt-store section. A named crt-store allows to add a scope to the crt name. For example, a crt named "foo.crt" in a crt-store named "web" will result in a certificate called "@web/foo.crt". --- doc/configuration.txt | 13 ++++++++++- src/ssl_ckch.c | 54 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index afab75099..338863e9d 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -4734,6 +4734,10 @@ section. It allows to configure certificate definitions and which files should be loaded in it. A certificate definition must be written before it is used elsewhere in the configuration. +The "crt-store" takes an optional name in argument. If a name is specified, +every certificate of this store must be referenced using "@/" or +"@/". + Files in the certificate storage can also be updated dynamically with the CLI. See "set ssl cert" in the section 9.3 of the management guide. @@ -4780,9 +4784,16 @@ Example: load crt "site1.crt" key "site1.key" ocsp "site1.ocsp" alias "site1" load crt "site2.crt" key "site2.key" - frontend in + frontend in2 bind *:443 ssl crt "@/site1" crt "site2.crt" + crt-store web + load crt "site3.crt" alias "site3" + load crt "site4.crt" key "site4.key" + + frontend in2 + bind *:443 ssl crt "@web/site1" crt "site2.crt" crt "@web/site3" crt "@web/site4.crt" + 4. Proxies ---------- diff --git a/src/ssl_ckch.c b/src/ssl_ckch.c index 40d929d92..8f9c8cacb 100644 --- a/src/ssl_ckch.c +++ b/src/ssl_ckch.c @@ -4065,6 +4065,8 @@ int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, char **err) return err_code; } +static char current_crtstore_name[PATH_MAX] = {}; + static int crtstore_parse_load(char **args, int section_type, struct proxy *curpx, const struct proxy *defpx, const char *file, int linenum, char **err) { @@ -4098,7 +4100,7 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp goto out; } - rv = snprintf(alias_name, sizeof(alias_name), "@%s/%s", "", args[cur_arg + 1]); + rv = snprintf(alias_name, sizeof(alias_name), "@%s/%s", current_crtstore_name, 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)); @@ -4160,9 +4162,28 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp 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 no alias was used: + * - when a crt-store exists, use @store/crt + * - or use the absolute file (crt_base + crt) + * - or the relative file when no crt_base exists + */ + if (current_crtstore_name[0] != '\0') { + int rv; + + /* add the crt-store name, avoid a double / if the crt starts by it */ + rv = snprintf(alias_name, sizeof(alias_name), "@%s%s%s", current_crtstore_name, f.crt[0] != '/' ? "/" : "", f.crt); + 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 (global_ssl.crt_base && *f.crt != '/') { + int rv; + /* When no crt_store name, complete the name in the ckch_tree with 'crt-base' */ + + 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; @@ -4171,7 +4192,6 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp final_name = store_path; } } - /* process and insert the ckch_store */ c = ckch_store_new(final_name); if (!c) @@ -4218,8 +4238,20 @@ static int cfg_parse_crtstore(const char *file, int linenum, char **args, int kw char *errmsg = NULL; if (strcmp(args[0], "crt-store") == 0) { /* new crt-store section */ - if (*args[1]) { - ha_alert("parsing [%s:%d] : 'crt-store' section does not support an argument.\n", file, linenum); + if (!*args[1]) { + current_crtstore_name[0] = '\0'; + } else { + rc = snprintf(current_crtstore_name, sizeof(current_crtstore_name), "%s", args[1]); + if (rc >= sizeof(current_crtstore_name)) { + ha_alert("parsing [%s:%d] : 'crt-store' argument is too long.\n", file, linenum); + current_crtstore_name[0] = '\0'; + err_code |= ERR_ALERT | ERR_FATAL | ERR_ABORT; + goto out; + } + } + + if (*args[2]) { + ha_alert("parsing [%s:%d] : 'crt-store' section only supports a argument.\n", file, linenum); err_code |= ERR_ALERT | ERR_FATAL | ERR_ABORT; goto out; } @@ -4269,7 +4301,13 @@ static int cfg_parse_crtstore(const char *file, int linenum, char **args, int kw return err_code; } -REGISTER_CONFIG_SECTION("crt-store", cfg_parse_crtstore, NULL); +static int cfg_post_parse_crtstore() +{ + current_crtstore_name[0] = '\0'; + return ERR_NONE; +} + +REGISTER_CONFIG_SECTION("crt-store", cfg_parse_crtstore, cfg_post_parse_crtstore); static struct cfg_kw_list cfg_kws = {ILH, { { CFG_CRTSTORE, "load", crtstore_parse_load },