MEDIUM: ssl: support aliases in crt-store

The crt-store load line now allows to put an alias. This alias is used
as the key in the ckch_tree instead of the certificate. This way an
alias can be referenced in the configuration with the '@/' prefix.

This can only be define with a crt-store.
This commit is contained in:
William Lallemand 2024-04-17 17:03:58 +02:00
parent e6662bf706
commit bdee8ace81
4 changed files with 46 additions and 19 deletions

View File

@ -4744,6 +4744,11 @@ load [crt <filename>] [param*]
Arguments: Arguments:
alias <string> 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 <filename> This argument is mandatory, it loads a PEM which must crt <filename> This argument is mandatory, it loads a PEM which must
contain the public certificate but could also contain contain the public certificate but could also contain
the intermediate certificates and the private key. the intermediate certificates and the private key.
@ -4772,11 +4777,11 @@ load [crt <filename>] [param*]
Example: Example:
crt-store 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" load crt "site2.crt" key "site2.key"
frontend in frontend in
bind *:443 ssl crt "site1.crt" crt "site2.crt" bind *:443 ssl crt "@/site1" crt "site2.crt"
4. Proxies 4. Proxies
---------- ----------

View File

@ -784,7 +784,7 @@ static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bin
return ERR_ALERT | ERR_FATAL; 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) || 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)) { 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]); 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; 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]); memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
else else
memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]); memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);

View File

@ -3997,6 +3997,7 @@ static struct cli_kw_list cli_kws = {{ },{
INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws); INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
struct ckch_conf_kws ckch_conf_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 }, { "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 }, { "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 }, { "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; int cur_arg = 0;
struct ckch_conf f = {}; struct ckch_conf f = {};
struct ckch_store *c = NULL; struct ckch_store *c = NULL;
char store_path[PATH_MAX]; char store_path[PATH_MAX]; /* complete path with crt_base */
char *store_name; 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" */ cur_arg++; /* skip "load" */
@ -4081,7 +4083,25 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
found = 1; found = 1;
target = (char **)((intptr_t)&f + (ptrdiff_t)ckch_conf_kws[i].offset); 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; char **t = target;
*t = strdup(args[cur_arg + 1]); *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; goto out;
} }
store_name = f.crt; if (!final_name) {
final_name = f.crt;
/* complete the name in the ckch_tree with 'crt-base' */ /* complete the name in the ckch_tree with 'crt-base' */
if (global_ssl.crt_base && *f.crt != '/') { if (global_ssl.crt_base && *f.crt != '/') {
int rv = snprintf(store_path, sizeof(store_path), "%s/%s", 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)) { if (rv >= sizeof(store_path)) {
memprintf(err, "'%s/%s' : path too long", global_ssl.crt_base, f.crt); memprintf(err, "'%s/%s' : path too long", global_ssl.crt_base, f.crt);
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
goto out; goto out;
}
final_name = store_path;
} }
store_name = store_path;
} }
/* process and insert the ckch_store */ /* process and insert the ckch_store */
c = ckch_store_new(store_name); c = ckch_store_new(final_name);
if (!c) if (!c)
goto alloc_error; goto alloc_error;

View File

@ -575,7 +575,7 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
continue; 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) || 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)) { snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path) > sizeof(path)) {
memprintf(err, "parsing [%s:%d]: '%s' : path too long", 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 = '/'; *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) || 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)) { snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, cert_path) > sizeof(path)) {
memprintf(&err, "'%s' : path too long", cert_path); memprintf(&err, "'%s' : path too long", cert_path);