]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: ssl: crt-base and key-base local keywords for crt-store
authorWilliam Lallemand <wlallemand@haproxy.com>
Thu, 18 Apr 2024 15:24:58 +0000 (17:24 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Thu, 18 Apr 2024 15:47:24 +0000 (17:47 +0200)
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"

doc/configuration.txt
src/ssl_ckch.c

index 338863e9d83eacc43e3566987d9f647fca811abd..37bac688c1220795d42bd6d607aeaa54d621ba08 100644 (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"
 
index 8f9c8cacbf9e0f79b6b7ee8520b085403fff4468..3e6917b447d50fed20cf882cc9f0dd2c3f81bc86 100644 (file)
@@ -3996,14 +3996,18 @@ 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 },
-       { NULL,     -1,                                  PARSE_TYPE_STR, NULL,                                  NULL                 }
+       { "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            }
 };
 
 /* crt-store does not try to find files, but use the stored filename */
@@ -4065,6 +4069,40 @@ out:
        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 @@ out:
 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 },
 }};