From 0a9b9414f05ac55268edf0afaa054dfe2c2377d8 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Mon, 6 Apr 2020 17:43:05 +0200 Subject: [PATCH] MINOR: ssl/cli: 'del ssl crt-list' delete an entry Delete an entry in a crt-list, this is done by iterating over the ckch_inst in the crtlist_entry. For each ckch_inst the bind_conf lock is held during the deletion of the sni_ctx in the SNI trees. Everything is free'd. If there is several entries with the same certificate, a line number must be provided to chose with entry delete. --- doc/management.txt | 6 +++ src/ssl_sock.c | 122 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/doc/management.txt b/doc/management.txt index 23b63af8b1..2aea4e0233 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1524,6 +1524,12 @@ del map [|#] listing the content of the map. Note that if the reference is a file and is shared with a acl, the entry will be also deleted in the map. +del ssl crt-list + Delete an entry in a crt-list. This will delete every SNIs used for this + entry in the frontends. If a certificate is used several time in a crt-list, + you will need to provide which line you want to delete. To display the line + numbers, use "show ssl crt-list -n ". + disable agent / Mark the auxiliary agent check as temporarily stopped. diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 37a45214cc..b1fdb09c53 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -11474,6 +11474,127 @@ error: return cli_dynerr(appctx, err); } +/* Parse a "del ssl crt-list " line. */ +static int cli_parse_del_crtlist(char **args, char *payload, struct appctx *appctx, void *private) +{ + struct ckch_store *store; + char *err = NULL; + char *crtlist_path, *cert_path; + struct ebmb_node *ebmb; + struct ebpt_node *ebpt; + struct crtlist *crtlist; + struct crtlist_entry *entry = NULL; + struct ckch_inst *inst, *inst_s; + int linenum = 0; + char *colons; + + if (!cli_has_level(appctx, ACCESS_LVL_ADMIN)) + return 1; + + if (!*args[3] || !*args[4]) + return cli_err(appctx, "'del ssl crtlist' expects a filename and a certificate name\n"); + + crtlist_path = args[3]; + cert_path = args[4]; + + colons = strchr(cert_path, ':'); + if (colons) { + char *endptr; + + linenum = strtol(colons + 1, &endptr, 10); + if (colons + 1 == endptr || *endptr != '\0') { + memprintf(&err, "wrong line number after colons in '%s'!", cert_path); + goto error; + } + *colons = '\0'; + } + /* look for crtlist */ + ebmb = ebst_lookup(&crtlists_tree, crtlist_path); + if (!ebmb) { + memprintf(&err, "crt-list '%s' does not exist!", crtlist_path); + goto error; + } + crtlist = ebmb_entry(ebmb, struct crtlist, node); + + /* look for store */ + store = ckchs_lookup(cert_path); + if (store == NULL) { + memprintf(&err, "certificate '%s' does not exist!", cert_path); + goto error; + } + if (store->ckch == NULL || store->ckch->cert == NULL) { + memprintf(&err, "certificate '%s' is empty!", cert_path); + goto error; + } + + ebpt = ebpt_lookup(&crtlist->entries, store); + if (!ebpt) { + memprintf(&err, "certificate '%s' can't be found in crt-list '%s'!", cert_path, crtlist_path); + goto error; + } + + /* list the line number of entries for errors in err, and select the right ebpt */ + for (; ebpt; ebpt = ebpt_next_dup(ebpt)) { + struct crtlist_entry *tmp; + + tmp = ebpt_entry(ebpt, struct crtlist_entry, node); + memprintf(&err, "%s%s%d", err ? err : "", err ? ", " : "", tmp->linenum); + + /* select the entry we wanted */ + if (linenum == 0 || tmp->linenum == linenum) { + if (!entry) + entry = tmp; + } + } + + /* we didn't found the specified entry */ + if (!entry) { + memprintf(&err, "found a certificate '%s' but the line number is incorrect, please specify a correct line number preceded by colons (%s)!", cert_path, err ? err : NULL); + goto error; + } + + /* we didn't specified a line number but there were several entries */ + if (linenum == 0 && ebpt_next_dup(&entry->node)) { + memprintf(&err, "found the certificate '%s' in several entries, please specify a line number preceded by colons (%s)!", cert_path, err ? err : NULL); + goto error; + } + + /* upon error free the ckch_inst and everything inside */ + + ebpt_delete(&entry->node); + LIST_DEL(&entry->by_crtlist); + LIST_DEL(&entry->by_ckch_store); + + list_for_each_entry_safe(inst, inst_s, &entry->ckch_inst, by_crtlist_entry) { + struct sni_ctx *sni, *sni_s; + + HA_RWLOCK_WRLOCK(SNI_LOCK, &inst->bind_conf->sni_lock); + list_for_each_entry_safe(sni, sni_s, &inst->sni_ctx, by_ckch_inst) { + ebmb_delete(&sni->name); + LIST_DEL(&sni->by_ckch_inst); + if (sni->order == 0) /* we only free if it's the first inserted */ + SSL_CTX_free(sni->ctx); + free(sni); + } + HA_RWLOCK_WRUNLOCK(SNI_LOCK, &inst->bind_conf->sni_lock); + LIST_DEL(&inst->by_ckchs); + free(inst); + } + + crtlist_free_filters(entry->filters); + ssl_sock_free_ssl_conf(entry->ssl_conf); + free(entry->ssl_conf); + free(entry); + + HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock); + err = memprintf(&err, "Entry '%s' deleted in crtlist '%s'!\n", cert_path, crtlist_path); + return cli_dynmsg(appctx, LOG_NOTICE, err); + +error: + HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock); + err = memprintf(&err, "Can't delete the entry: %s\n", err ? err : ""); + return cli_dynerr(appctx, err); +} /* Type of SSL payloads that can be updated over the CLI */ @@ -12600,6 +12721,7 @@ static struct cli_kw_list cli_kws = {{ },{ { { "abort", "ssl", "cert", NULL }, "abort ssl cert : abort a transaction for a certificate file", cli_parse_abort_cert, NULL, NULL }, { { "show", "ssl", "cert", NULL }, "show ssl cert [] : display the SSL certificates used in memory, or the details of a ", cli_parse_show_cert, cli_io_handler_show_cert, cli_release_show_cert }, { { "add", "ssl", "crt-list", NULL }, "add ssl crt-list [options] : add a line to a crt-list ", cli_parse_add_crtlist, cli_io_handler_add_crtlist, cli_release_add_crtlist }, + { { "del", "ssl", "crt-list", NULL }, "del ssl crt-list : delete a line in a crt-list ", cli_parse_del_crtlist, NULL, NULL }, { { "dump", "ssl", "crt-list", NULL }, "dump ssl crt-list : dump the content of a crt-list ", cli_parse_dump_crtlist, cli_io_handler_dump_crtlist, NULL }, { { "show", "ssl", "crt-list", NULL }, "show ssl crt-list [] : show the list of crt-lists or the content of a crt-list ", cli_parse_dump_crtlist, cli_io_handler_dump_crtlist, NULL }, { { NULL }, NULL, NULL, NULL } -- 2.39.5