MEDIUM: ssl: crt-base and key-base local keywords for crt-store

Add support for crt-base and key-base local keywords for the crt-store.

current_crtbase and current_keybase are filed with a copy of the global
keyword argument when a crt-store is declared, and updated with a new
path when the keywords are in the crt-store section.

The ckch_conf_kws[] array was updated with &current_crtbase and
&current_keybase instead of the global_ssl ones so the parser can use
them.

The keyword must be used before any "load" line in a crt-store section.

Example:

    crt-store web
        crt-base /etc/ssl/certs/
        key-base /etc/ssl/private/
        load crt "site3.crt" alias "site3"
        load crt "site4.crt" key "site4.key"

    frontend in2
        bind *:443 ssl crt "@web/site3" crt "@web/site4.crt"
This commit is contained in:
William Lallemand 2024-04-18 17:24:58 +02:00
parent 0109c0658d
commit 64201ad2c3
2 changed files with 79 additions and 7 deletions

View File

@ -4741,7 +4741,23 @@ every certificate of this store must be referenced using "@<name>/<crt>" 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.
Currently only the "load" keyword is supported in the "crt-store" section:
The following keywords are supported in the "crt-store" section :
- crt-base
- key-base
- load
crt-base <dir>
Assigns a default directory to fetch SSL certificates from when a relative
path is used with "crt" directives. Absolute locations specified prevail and
ignore "crt-base". When used in a crt-store, the crt-base of the global
section is ignored.
key-base <dir>
Assigns a default directory to fetch SSL private keys from when a relative
path is used with "key" directives. Absolute locations specified prevail and
ignore "key-base". When used in a crt-store, the key-base of the global
section is ignored.
load [crt <filename>] [param*]
Load SSL files in the certificate storage.
@ -4788,6 +4804,8 @@ Example:
bind *:443 ssl crt "@/site1" crt "site2.crt"
crt-store web
crt-base /etc/ssl/certs/
key-base /etc/ssl/private/
load crt "site3.crt" alias "site3"
load crt "site4.crt" key "site4.key"

View File

@ -3996,13 +3996,17 @@ static struct cli_kw_list cli_kws = {{ },{
INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
static char *current_crtbase = NULL;
static char *current_keybase = NULL;
static int crtstore_load = 0; /* did we already load in this crt-store */
struct ckch_conf_kws ckch_conf_kws[] = {
{ "alias", -1, PARSE_TYPE_NONE, 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 },
{ "issuer", offsetof(struct ckch_conf, issuer), PARSE_TYPE_STR, ssl_sock_load_issuer_file_into_ckch, &global_ssl.crt_base },
{ "sctl", offsetof(struct ckch_conf, sctl), PARSE_TYPE_STR, ssl_sock_load_sctl_from_file, &global_ssl.crt_base },
{ "crt", offsetof(struct ckch_conf, crt), PARSE_TYPE_STR, ssl_sock_load_pem_into_ckch, &current_crtbase },
{ "key", offsetof(struct ckch_conf, key), PARSE_TYPE_STR, ssl_sock_load_key_into_ckch, &current_keybase },
{ "ocsp", offsetof(struct ckch_conf, ocsp), PARSE_TYPE_STR, ssl_sock_load_ocsp_response_from_file, &current_crtbase },
{ "issuer", offsetof(struct ckch_conf, issuer), PARSE_TYPE_STR, ssl_sock_load_issuer_file_into_ckch, &current_crtbase },
{ "sctl", offsetof(struct ckch_conf, sctl), PARSE_TYPE_STR, ssl_sock_load_sctl_from_file, &current_crtbase },
{ NULL, -1, PARSE_TYPE_STR, NULL, NULL }
};
@ -4065,6 +4069,40 @@ int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, char **err)
return err_code;
}
/* Parse a local crt-base or key-base for a crt-store */
static int crtstore_parse_path_base(char **args, int section_type, struct proxy *curpx, const struct proxy *defpx,
const char *file, int linenum, char **err)
{
int err_code = ERR_NONE;
if (!*args[1]) {
memprintf(err, "parsing [%s:%d] : '%s' requires a <path> argument.",
file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (crtstore_load) {
memprintf(err, "parsing [%s:%d] : '%s' can't be used after a load line, use it at the beginning of the section.",
file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (args[0][1] == 'r') {
/* crt-base */
free(current_crtbase);
current_crtbase = strdup(args[1]);
} else if (args[0][1] == 'e') {
/* key-base */
free(current_keybase);
current_keybase = strdup(args[1]);
}
out:
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,
@ -4159,6 +4197,8 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
goto out;
}
crtstore_load = 1;
if (!final_name) {
final_name = f.crt;
@ -4255,6 +4295,15 @@ static int cfg_parse_crtstore(const char *file, int linenum, char **args, int kw
err_code |= ERR_ALERT | ERR_FATAL | ERR_ABORT;
goto out;
}
/* copy the crt_base and key_base */
ha_free(&current_crtbase);
if (global_ssl.crt_base)
current_crtbase = strdup(global_ssl.crt_base);
ha_free(&current_keybase);
if (global_ssl.key_base)
current_keybase = strdup(global_ssl.key_base);
crtstore_load = 0;
goto out;
}
@ -4304,12 +4353,17 @@ static int cfg_parse_crtstore(const char *file, int linenum, char **args, int kw
static int cfg_post_parse_crtstore()
{
current_crtstore_name[0] = '\0';
ha_free(&current_crtbase);
ha_free(&current_keybase);
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, "crt-base", crtstore_parse_path_base },
{ CFG_CRTSTORE, "key-base", crtstore_parse_path_base },
{ CFG_CRTSTORE, "load", crtstore_parse_load },
{ 0, NULL, NULL },
}};