diff --git a/doc/configuration.txt b/doc/configuration.txt index a5176adb7..afab75099 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -4744,6 +4744,11 @@ load [crt ] [param*] Arguments: + alias 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 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 ] [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 ---------- diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c index 467fbdad9..29e4e08b1 100644 --- a/src/cfgparse-ssl.c +++ b/src/cfgparse-ssl.c @@ -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]); diff --git a/src/ssl_ckch.c b/src/ssl_ckch.c index bd2ffe24f..fea0b9631 100644 --- a/src/ssl_ckch.c +++ b/src/ssl_ckch.c @@ -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; diff --git a/src/ssl_crtlist.c b/src/ssl_crtlist.c index 3b1f53295..7a7721593 100644 --- a/src/ssl_crtlist.c +++ b/src/ssl_crtlist.c @@ -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);