diff --git a/include/haproxy/ssl_ckch-t.h b/include/haproxy/ssl_ckch-t.h index e01d65c8b..0f95c4857 100644 --- a/include/haproxy/ssl_ckch-t.h +++ b/include/haproxy/ssl_ckch-t.h @@ -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 */ }; diff --git a/include/haproxy/ssl_ckch.h b/include/haproxy/ssl_ckch.h index 3ec2c3586..4ee3541cf 100644 --- a/include/haproxy/ssl_ckch.h +++ b/include/haproxy/ssl_ckch.h @@ -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 */ diff --git a/include/haproxy/ssl_ocsp.h b/include/haproxy/ssl_ocsp.h index 001f85d59..f6a72b94c 100644 --- a/include/haproxy/ssl_ocsp.h +++ b/include/haproxy/ssl_ocsp.h @@ -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) */ diff --git a/src/ssl_ckch.c b/src/ssl_ckch.c index e91f42d73..a72da2415 100644 --- a/src/ssl_ckch.c +++ b/src/ssl_ckch.c @@ -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; diff --git a/src/ssl_crtlist.c b/src/ssl_crtlist.c index 29c969d4c..a0dfbcf66 100644 --- a/src/ssl_crtlist.c +++ b/src/ssl_crtlist.c @@ -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 : ""); diff --git a/src/ssl_ocsp.c b/src/ssl_ocsp.c index 92b2f5a74..7d3a485b8 100644 --- a/src/ssl_ocsp.c +++ b/src/ssl_ocsp.c @@ -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;