]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: ssl/cli: handle crt-store keywords in crt-list over the CLI
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 7 May 2024 07:20:06 +0000 (09:20 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Fri, 17 May 2024 15:35:51 +0000 (17:35 +0200)
This patch adds crt-store keywords from the crt-list on the CLI.

- keywords from crt-store can be used over the CLI when inserting
  certificate in a crt-list
- keywords from crt-store are dumped when showing a crt-list content
  over the CLI

The ckch_conf_kws.func function pointer needed a new "cli" parameter, in
order to differenciate loading that come from the CLI or from the
startup, as they don't behave the same. For example it must not try to
load a file on the filesystem when loading a crt-list line from the CLI.

dump_crtlist_sslconf() was renamed in dump_crtlist_conf() and takes a
new ckch_conf parameter in order to dump relevant crt-store keywords.

include/haproxy/ssl_ckch-t.h
include/haproxy/ssl_ckch.h
include/haproxy/ssl_ocsp.h
src/ssl_ckch.c
src/ssl_crtlist.c
src/ssl_ocsp.c

index e01d65c8ba53a5313eddf731850d51703b9e0f21..0f95c485733b3f049620f44381120b3706811f73 100644 (file)
@@ -180,7 +180,7 @@ struct ckch_conf_kws {
        const char *name;
        ssize_t offset;
        enum parse_type_t type;
-       int (*func)(void *value, char *buf, struct ckch_data *d, char **err);
+       int (*func)(void *value, char *buf, struct ckch_data *d, int cli, char **err);
        char **base; /* ptr to the base path */
 };
 
index 3ec2c358627472cb22435243e4c8cfba8167d17b..4ee3541cffca3feb46354e4e963185ac101fb1fa 100644 (file)
@@ -44,7 +44,7 @@ struct ckch_store *ckchs_dup(const struct ckch_store *src);
 struct ckch_store *ckch_store_new(const char *filename);
 void ckch_store_free(struct ckch_store *store);
 void ckch_store_replace(struct ckch_store *old_ckchs, struct ckch_store *new_ckchs);
-int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, char **err);
+int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, int cli, char **err);
 
 /* ckch_conf functions */
 
@@ -80,11 +80,11 @@ extern struct cert_exts cert_exts[];
 extern int (*ssl_commit_crlfile_cb)(const char *path, X509_STORE *ctx, char **err);
 
 /* ckch_conf keyword loading */
-static inline int ckch_conf_load_pem(void *value, char *buf, struct ckch_data *d, char **err) { return ssl_sock_load_pem_into_ckch(value, buf, d, err); }
-static inline int ckch_conf_load_key(void *value, char *buf, struct ckch_data *d, char **err) { return ssl_sock_load_key_into_ckch(value, buf, d, err); }
-static inline int ckch_conf_load_ocsp_response(void *value, char *buf, struct ckch_data *d, char **err) { return ssl_sock_load_ocsp_response_from_file(value, buf, d, err); }
-static inline int ckch_conf_load_ocsp_issuer(void *value, char *buf, struct ckch_data *d, char **err) { return ssl_sock_load_issuer_file_into_ckch(value, buf, d, err); }
-static inline int ckch_conf_load_sctl(void *value, char *buf, struct ckch_data *d, char **err) { return ssl_sock_load_sctl_from_file(value, buf, d, err); }
+static inline int ckch_conf_load_pem(void *value, char *buf, struct ckch_data *d, int cli, char **err) { if (cli) return 0; return ssl_sock_load_pem_into_ckch(value, buf, d, err); }
+static inline int ckch_conf_load_key(void *value, char *buf, struct ckch_data *d, int cli, char **err) { if (cli) return 0; return ssl_sock_load_key_into_ckch(value, buf, d, err); }
+static inline int ckch_conf_load_ocsp_response(void *value, char *buf, struct ckch_data *d, int cli, char **err) { if (cli) return 0; return ssl_sock_load_ocsp_response_from_file(value, buf, d, err); }
+static inline int ckch_conf_load_ocsp_issuer(void *value, char *buf, struct ckch_data *d, int cli, char **err) { if (cli) return 0; return ssl_sock_load_issuer_file_into_ckch(value, buf, d, err); }
+static inline int ckch_conf_load_sctl(void *value, char *buf, struct ckch_data *d, int cli, char **err) { if (cli) return 0; return ssl_sock_load_sctl_from_file(value, buf, d, err); }
 
 #endif /* USE_OPENSSL */
 #endif /* _HAPROXY_SSL_CRTLIST_H */
index 001f85d591f6e23934992a8234c8b5784ec270e1..f6a72b94c01d20ebc4abc10ebe8a8d30642c25df 100644 (file)
@@ -55,7 +55,7 @@ void ssl_destroy_ocsp_update_task(void);
 
 int ssl_ocsp_update_insert(struct certificate_ocsp *ocsp);
 
-int ocsp_update_init(void *value, char *buf, struct ckch_data *d, char **err);
+int ocsp_update_init(void *value, char *buf, struct ckch_data *d, int cli, char **err);
 
 #endif /* (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) */
 
index e91f42d73266c211ded3334fb21177db512585c1..a72da241571ef6d200d3acb60ba88a80e8f73796 100644 (file)
@@ -962,6 +962,9 @@ struct ckch_store *ckchs_dup(const struct ckch_store *src)
        if (!ssl_sock_copy_cert_key_and_chain(src->data, dst->data))
                goto error;
 
+
+       dst->conf.ocsp_update_mode = src->conf.ocsp_update_mode;
+
        return dst;
 
 error:
@@ -1026,7 +1029,7 @@ struct ckch_store *ckch_store_new_load_files_conf(char *name, struct ckch_conf *
                goto end;
        }
 
-       cfgerr = ckch_store_load_files(conf, ckchs, err);
+       cfgerr = ckch_store_load_files(conf, ckchs, 0, err);
        if (cfgerr & ERR_FATAL)
                goto end;
 
@@ -4033,19 +4036,13 @@ struct ckch_conf_kws ckch_conf_kws[] = {
 };
 
 /* crt-store does not try to find files, but use the stored filename */
-int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, char **err)
+int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, int cli, char **err)
 {
        int i;
        int err_code = 0;
        int rc = 1;
        struct ckch_data *d = c->data;
 
-       /* crt */
-       if (!f->crt) {
-               err_code |= ERR_ALERT | ERR_FATAL;
-               goto out;
-       }
-
        for (i = 0; ckch_conf_kws[i].name; i++) {
                void *src = NULL;
 
@@ -4079,7 +4076,7 @@ int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, char **err)
                                        }
                                        path = path_base;
                                }
-                               rc = ckch_conf_kws[i].func(path, NULL, d, err);
+                               rc = ckch_conf_kws[i].func(path, NULL, d, cli, err);
                                if (rc) {
                                        err_code |= ERR_ALERT | ERR_FATAL;
                                        memprintf(err, "%s '%s' cannot be read or parsed.", err && *err ? *err : "", path);
@@ -4092,7 +4089,7 @@ int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, char **err)
                        case PARSE_TYPE_ONOFF:
                        {
                                int v = *(int *)src;
-                               rc = ckch_conf_kws[i].func(&v, NULL, d, err);
+                               rc = ckch_conf_kws[i].func(&v, NULL, d, cli, err);
                                if (rc) {
                                        err_code |= ERR_ALERT | ERR_FATAL;
                                        memprintf(err, "%s '%d' cannot be read or parsed.", err && *err ? *err : "", v);
@@ -4313,7 +4310,7 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
        if (!c)
                goto alloc_error;
 
-       err_code |= ckch_store_load_files(&f, c, err);
+       err_code |= ckch_store_load_files(&f, c,  0, err);
        if (err_code & ERR_FATAL)
                goto out;
 
index 29c969d4c9ff7ab108971b81f2dc9680700635aa..a0dfbcf66f035ccd8de00c66b8728e6a07cdd059 100644 (file)
@@ -825,14 +825,21 @@ end:
  * Take an ssl_bind_conf structure and append the configuration line used to
  * create it in the buffer
  */
-static void dump_crtlist_sslconf(struct buffer *buf, const struct ssl_bind_conf *conf)
+static void dump_crtlist_conf(struct buffer *buf, const struct ssl_bind_conf *conf, const struct ckch_conf *cc)
 {
        int space = 0;
 
-       if (conf == NULL)
+       if (conf == NULL && cc->used == 0)
                return;
 
        chunk_appendf(buf, " [");
+
+
+       if (conf == NULL)
+               goto dump_ckch;
+
+       /* first dump all ssl_conf keywords */
+
 #ifdef OPENSSL_NPN_NEGOTIATED
        if (conf->npn_str) {
                int len = conf->npn_len;
@@ -958,7 +965,22 @@ static void dump_crtlist_sslconf(struct buffer *buf, const struct ssl_bind_conf
                space++;
        }
 
-       /* FIXME: dump crt-store keywords */
+       /* then dump the ckch_conf */
+dump_ckch:
+       if (!cc->used)
+               goto end;
+
+       if (cc->ocsp_update_mode == SSL_SOCK_OCSP_UPDATE_OFF) {
+               if (space) chunk_appendf(buf, " ");
+               chunk_appendf(buf, "ocsp-update off");
+               space++;
+       } else if (cc->ocsp_update_mode == SSL_SOCK_OCSP_UPDATE_ON) {
+               if (space) chunk_appendf(buf, " ");
+               chunk_appendf(buf, "ocsp-update on");
+               space++;
+       }
+
+end:
 
        chunk_appendf(buf, "]");
 
@@ -1042,7 +1064,7 @@ static int cli_io_handler_dump_crtlist_entries(struct appctx *appctx)
                chunk_appendf(trash, "%s", filename);
                if (ctx->mode == 's') /* show */
                        chunk_appendf(trash, ":%d", entry->linenum);
-               dump_crtlist_sslconf(trash, entry->ssl_conf);
+               dump_crtlist_conf(trash, entry->ssl_conf, &store->conf);
                dump_crtlist_filters(trash, entry);
                chunk_appendf(trash, "\n");
 
@@ -1272,6 +1294,7 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
        struct ebpt_node *inserted;
        struct crtlist *crtlist;
        struct crtlist_entry *entry = NULL;
+       struct ckch_conf cc = {};
        char *end;
 
        if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
@@ -1302,6 +1325,7 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
                goto error;
        }
 
+
        if (payload) {
                char *lf;
 
@@ -1311,8 +1335,7 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
                        goto error;
                }
                /* cert_path is filled here */
-               cfgerr |= crtlist_parse_line(payload, &cert_path, entry, NULL, "CLI", 1, 1, &err);
-               /* FIXME: handle the ckch_conf */
+               cfgerr |= crtlist_parse_line(payload, &cert_path, entry, &cc, "CLI", 1, 1, &err);
                if (cfgerr & ERR_CODE)
                        goto error;
        } else {
@@ -1363,6 +1386,24 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
                goto error;
        }
 
+       /* We can use a crt-store keyword when:
+        * - no ckch_inst are linked OR
+        * - ckch_inst are linked but exact same ckch_conf is used.
+        */
+       if (LIST_ISEMPTY(&store->ckch_inst)) {
+
+               store->conf = cc;
+               /* fresh new, run more init (for example init ocsp-update tasks) */
+               cfgerr |= ckch_store_load_files(&cc, store, 1, &err);
+               if (cfgerr & ERR_FATAL)
+                       goto error;
+
+       } else if (ckch_conf_cmp(&store->conf, &cc, &err) != 0) {
+               memprintf(&err, "'%s' is already instantiated with incompatible parameters:\n %s", cert_path, err ? err : "");
+               cfgerr |= ERR_ALERT | ERR_FATAL;
+               goto error;
+       }
+
        /* check if it's possible to insert this new crtlist_entry */
        entry->node.key = store;
        inserted = ebpt_insert(&crtlist->entries, &entry->node);
@@ -1372,8 +1413,8 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
        }
 
        /* this is supposed to be a directory (EB_ROOT_UNIQUE), so no ssl_conf are allowed */
-       if ((entry->ssl_conf || entry->filters) && eb_gettag(crtlist->entries.b[EB_RGHT])) {
-               memprintf(&err, "this is a directory, SSL configuration and filters are not allowed");
+       if ((entry->ssl_conf || entry->filters || cc.used) && eb_gettag(crtlist->entries.b[EB_RGHT])) {
+               memprintf(&err, "this is a directory, SSL configuration, crt-store keywords and filters are not allowed");
                goto error;
        }
 
@@ -1389,6 +1430,7 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
        return 0;
 
 error:
+       ckch_conf_clean(&cc);
        crtlist_entry_free(entry);
        HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
        err = memprintf(&err, "Can't edit the crt-list: %s\n", err ? err : "");
index 92b2f5a74c1b1506a8ef35fe936e0d40e274cf41..7d3a485b8de22b596156a6cbee0891d594089e9c 100644 (file)
@@ -1986,7 +1986,7 @@ static int ocsp_update_parse_global_http_proxy(char **args, int section_type, st
        return 0;
 }
 
-int ocsp_update_init(void *value, char *buf, struct ckch_data *d, char **err)
+int ocsp_update_init(void *value, char *buf, struct ckch_data *d, int cli, char **err)
 {
        int ocsp_update_mode = *(int *)value;
        int ret = 0;