summaryrefslogtreecommitdiffstats
path: root/src/ssl_crtlist.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 05:11:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 05:11:10 +0000
commitcff6d757e3ba609c08ef2aaa00f07e53551e5bf6 (patch)
tree08c4fc3255483ad397d712edb4214ded49149fd9 /src/ssl_crtlist.c
parentAdding upstream version 2.9.7. (diff)
downloadhaproxy-9a644524ed5176bbb45612a8de194936e4266792.tar.xz
haproxy-9a644524ed5176bbb45612a8de194936e4266792.zip
Adding upstream version 3.0.0.upstream/3.0.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/ssl_crtlist.c')
-rw-r--r--src/ssl_crtlist.c148
1 files changed, 95 insertions, 53 deletions
diff --git a/src/ssl_crtlist.c b/src/ssl_crtlist.c
index d788bec..71fa0a0 100644
--- a/src/ssl_crtlist.c
+++ b/src/ssl_crtlist.c
@@ -356,7 +356,7 @@ struct crtlist *crtlist_new(const char *filename, int unique)
* <crt_path> is a ptr in <line>
* Return an error code
*/
-int crtlist_parse_line(char *line, char **crt_path, struct crtlist_entry *entry, const char *file, int linenum, int from_cli, char **err)
+int crtlist_parse_line(char *line, char **crt_path, struct crtlist_entry *entry, struct ckch_conf *cc, const char *file, int linenum, int from_cli, char **err)
{
int cfgerr = 0;
int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
@@ -438,19 +438,22 @@ int crtlist_parse_line(char *line, char **crt_path, struct crtlist_entry *entry,
cfgerr |= ERR_WARN;
}
- ssl_conf = calloc(1, sizeof *ssl_conf);
- if (!ssl_conf) {
- memprintf(err, "not enough memory!");
- cfgerr |= ERR_ALERT | ERR_FATAL;
- goto error;
- }
}
cur_arg = ssl_b ? ssl_b : 1;
while (cur_arg < ssl_e) {
newarg = 0;
+ /* look for ssl_conf keywords */
for (i = 0; ssl_crtlist_kws[i].kw != NULL; i++) {
if (strcmp(ssl_crtlist_kws[i].kw, args[cur_arg]) == 0) {
+ if (!ssl_conf)
+ ssl_conf = calloc(1, sizeof *ssl_conf);
+ if (!ssl_conf) {
+ memprintf(err, "not enough memory!");
+ cfgerr |= ERR_ALERT | ERR_FATAL;
+ goto error;
+ }
+
newarg = 1;
cfgerr |= ssl_crtlist_kws[i].parse(args, cur_arg, NULL, ssl_conf, from_cli, err);
if (cur_arg + 1 + ssl_crtlist_kws[i].skip > ssl_e) {
@@ -460,9 +463,22 @@ int crtlist_parse_line(char *line, char **crt_path, struct crtlist_entry *entry,
goto error;
}
cur_arg += 1 + ssl_crtlist_kws[i].skip;
- break;
+ goto out;
}
}
+ if (cc) {
+ /* look for ckch_conf keywords */
+ cfgerr |= ckch_conf_parse(args, cur_arg, cc, &newarg, file, linenum, err);
+ if (cfgerr & ERR_FATAL)
+ goto error;
+
+ if (newarg) {
+ cur_arg += 2; /* skip 2 words if the keyword was found */
+ cc->used = CKCH_CONF_SET_CRTLIST; /* if they are options they must be used everywhere */
+ }
+
+ }
+out:
if (!cfgerr && !newarg) {
memprintf(err, "parsing [%s:%d]: unknown ssl keyword %s",
file, linenum, args[cur_arg]);
@@ -521,6 +537,7 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
char *crt_path;
char path[MAXPATHLEN+1];
struct ckch_store *ckchs;
+ struct ckch_conf cc = {};
int found = 0;
if (missing_lf != -1) {
@@ -562,7 +579,7 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
goto error;
}
- cfgerr |= crtlist_parse_line(thisline, &crt_path, entry, file, linenum, 0, err);
+ cfgerr |= crtlist_parse_line(thisline, &crt_path, entry, &cc, file, linenum, 0, err);
if (cfgerr & ERR_CODE)
goto error;
@@ -573,7 +590,7 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
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) ||
snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path) > sizeof(path)) {
memprintf(err, "parsing [%s:%d]: '%s' : path too long",
@@ -589,17 +606,18 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
if (ckchs == NULL) {
if (stat(crt_path, &buf) == 0) {
found++;
-
- ckchs = ckchs_load_cert_file(crt_path, err);
+ free(cc.crt);
+ cc.crt = strdup(crt_path);
+ ckchs = ckch_store_new_load_files_conf(crt_path, &cc, err);
if (ckchs == NULL) {
cfgerr |= ERR_ALERT | ERR_FATAL;
goto error;
}
+ ckchs->conf = cc;
+
entry->node.key = ckchs;
entry->crtlist = newlist;
- if (entry->ssl_conf)
- ckchs->data->ocsp_update_mode = entry->ssl_conf->ocsp_update;
ebpt_insert(&newlist->entries, &entry->node);
LIST_APPEND(&newlist->ord_entries, &entry->by_crtlist);
LIST_APPEND(&ckchs->crtlist_entry, &entry->by_ckch_store);
@@ -614,6 +632,7 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
char fp[MAXPATHLEN+1] = {0};
int n = 0;
struct crtlist_entry *entry_dup = entry; /* use the previous created entry */
+
for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
struct stat buf;
int ret;
@@ -625,7 +644,13 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
ckchs = ckchs_lookup(fp);
if (!ckchs) {
if (stat(fp, &buf) == 0) {
- ckchs = ckchs_load_cert_file(fp, err);
+
+ if (cc.used) {
+ memprintf(err, "%sCan't load '%s'. Using crt-store keyword is not compatible with multi certificates bundle.\n",
+ err && *err ? *err : "", crt_path);
+ cfgerr |= ERR_ALERT | ERR_FATAL;
+ }
+ ckchs = ckch_store_new_load_files_path(fp, err);
if (!ckchs) {
cfgerr |= ERR_ALERT | ERR_FATAL;
goto error;
@@ -649,12 +674,6 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
entry_dup->node.key = ckchs;
entry_dup->crtlist = newlist;
- cfgerr |= ocsp_update_check_cfg_consistency(ckchs, entry, crt_path, err);
- if (cfgerr & ERR_FATAL)
- goto error;
-
- if (entry->ssl_conf)
- ckchs->data->ocsp_update_mode = entry->ssl_conf->ocsp_update;
ebpt_insert(&newlist->entries, &entry_dup->node);
LIST_APPEND(&newlist->ord_entries, &entry_dup->by_crtlist);
LIST_APPEND(&ckchs->crtlist_entry, &entry_dup->by_ckch_store);
@@ -676,15 +695,15 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
}
} else {
+ if (ckch_conf_cmp(&ckchs->conf, &cc, err) != 0) {
+ memprintf(err, "'%s' in crt-list '%s' line %d, is already defined with incompatible parameters:\n %s", crt_path, file, linenum, err ? *err : "");
+ cfgerr |= ERR_ALERT | ERR_FATAL;
+ goto error;
+ }
+
entry->node.key = ckchs;
entry->crtlist = newlist;
- cfgerr |= ocsp_update_check_cfg_consistency(ckchs, entry, crt_path, err);
- if (cfgerr & ERR_FATAL)
- goto error;
-
- if (entry->ssl_conf)
- ckchs->data->ocsp_update_mode = entry->ssl_conf->ocsp_update;
ebpt_insert(&newlist->entries, &entry->node);
LIST_APPEND(&newlist->ord_entries, &entry->by_crtlist);
LIST_APPEND(&ckchs->crtlist_entry, &entry->by_ckch_store);
@@ -711,6 +730,8 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
error:
crtlist_entry_free(entry);
+ /* FIXME: free cc */
+
fclose(f);
crtlist_free(newlist);
return cfgerr;
@@ -774,7 +795,7 @@ int crtlist_load_cert_dir(char *path, struct bind_conf *bind_conf, struct crtlis
ckchs = ckchs_lookup(fp);
if (ckchs == NULL)
- ckchs = ckchs_load_cert_file(fp, err);
+ ckchs = ckch_store_new_load_files_path(fp, err);
if (ckchs == NULL) {
free(de);
free(entry);
@@ -808,21 +829,27 @@ 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;
char *ptr = conf->npn_str;
int comma = 0;
- if (space) chunk_appendf(buf, " ");
chunk_appendf(buf, "npn ");
while (len) {
unsigned short size;
@@ -941,13 +968,23 @@ static void dump_crtlist_sslconf(struct buffer *buf, const struct ssl_bind_conf
space++;
}
- if (conf->ocsp_update != SSL_SOCK_OCSP_UPDATE_DFLT) {
+ /* 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 %s",
- conf->ocsp_update == SSL_SOCK_OCSP_UPDATE_OFF ? "off" : "on");
+ chunk_appendf(buf, "ocsp-update on");
space++;
}
+end:
+
chunk_appendf(buf, "]");
return;
@@ -1030,7 +1067,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");
@@ -1128,7 +1165,6 @@ static int cli_io_handler_add_crtlist(struct appctx *appctx)
{
struct add_crtlist_ctx *ctx = appctx->svcctx;
struct bind_conf_list *bind_conf_node;
- struct stconn *sc = appctx_sc(appctx);
struct crtlist *crtlist = ctx->crtlist;
struct crtlist_entry *entry = ctx->entry;
struct ckch_store *store = entry->node.key;
@@ -1139,10 +1175,6 @@ static int cli_io_handler_add_crtlist(struct appctx *appctx)
/* for each bind_conf which use the crt-list, a new ckch_inst must be
* created.
*/
- /* FIXME: Don't watch the other side !*/
- if (unlikely(sc_opposite(sc)->flags & SC_FL_SHUT_DONE))
- goto end;
-
switch (ctx->state) {
case ADDCRT_ST_INIT:
/* This state just print the update message */
@@ -1173,7 +1205,7 @@ static int cli_io_handler_add_crtlist(struct appctx *appctx)
/* we don't support multi-cert bundles, only simple ones */
ctx->err = NULL;
- errcode |= ckch_inst_new_load_store(store->path, store, bind_conf, entry->ssl_conf, entry->filters, entry->fcount, &new_inst, &ctx->err);
+ errcode |= ckch_inst_new_load_store(store->path, store, bind_conf, entry->ssl_conf, entry->filters, entry->fcount, 0, &new_inst, &ctx->err);
if (errcode & ERR_CODE) {
ctx->state = ADDCRT_ST_ERROR;
goto error;
@@ -1265,6 +1297,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))
@@ -1295,6 +1328,7 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
goto error;
}
+
if (payload) {
char *lf;
@@ -1304,7 +1338,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, "CLI", 1, 1, &err);
+ cfgerr |= crtlist_parse_line(payload, &cert_path, entry, &cc, "CLI", 1, 1, &err);
if (cfgerr & ERR_CODE)
goto error;
} else {
@@ -1335,7 +1369,7 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
*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) ||
snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, cert_path) > sizeof(path)) {
memprintf(&err, "'%s' : path too long", cert_path);
@@ -1355,15 +1389,23 @@ static int cli_parse_add_crtlist(char **args, char *payload, struct appctx *appc
goto error;
}
- /* No need to check 'ocsp-update' inconsistency on a store that is not
- * used yet (it was just added through the CLI for instance).
+ /* 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) &&
- ocsp_update_check_cfg_consistency(store, entry, cert_path, &err))
- goto error;
+ if (LIST_ISEMPTY(&store->ckch_inst)) {
- if (entry->ssl_conf)
- store->data->ocsp_update_mode = entry->ssl_conf->ocsp_update;
+ 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;
@@ -1374,8 +1416,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;
}
@@ -1391,6 +1433,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 : "");
@@ -1567,4 +1610,3 @@ static struct cli_kw_list cli_kws = {{ },{
};
INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
-