From a6ffd5bf8abf48def4499dd6a1a1658a6f5272a4 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Mon, 9 Mar 2020 13:35:19 +0100 Subject: [PATCH] MINOR: ssl/cli: show/dump ssl crt-list Implement 2 new commands on the CLI: show ssl crt-list []: Without a specified filename, display the list of crt-lists used by the configuration. If a filename is specified, it will displays the content of this crt-list, with a line identifier at the beginning of each line. This output must not be used as a crt-list file. dump ssl crt-list : Dump the content of a crt-list, the output can be used as a crt-list file. Note: It currently displays the default ssl-min-ver and ssl-max-ver which are potentialy not in the original file. --- src/ssl_sock.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 6da15b885d..36a2d70fe3 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -10848,6 +10848,267 @@ static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appc } #endif +/* + * 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) +{ + int space = 0; + + if (conf == NULL) + return; + + chunk_appendf(buf, " ["); +#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; + + size = *ptr; + ptr++; + if (comma) + chunk_memcat(buf, ",", 1); + chunk_memcat(buf, ptr, size); + ptr += size; + len -= size + 1; + comma = 1; + } + chunk_memcat(buf, "", 1); /* finish with a \0 */ + space++; + } +#endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + if (conf->alpn_str) { + int len = conf->alpn_len; + char *ptr = conf->alpn_str; + int comma = 0; + + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "alpn "); + while (len) { + unsigned short size; + + size = *ptr; + ptr++; + if (comma) + chunk_memcat(buf, ",", 1); + chunk_memcat(buf, ptr, size); + ptr += size; + len -= size + 1; + comma = 1; + } + chunk_memcat(buf, "", 1); /* finish with a \0 */ + space++; + } +#endif + /* verify */ + { + if (conf->verify == SSL_SOCK_VERIFY_NONE) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "verify none"); + space++; + } else if (conf->verify == SSL_SOCK_VERIFY_OPTIONAL) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "verify optional"); + space++; + } else if (conf->verify == SSL_SOCK_VERIFY_REQUIRED) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "verify required"); + space++; + } + } + + if (conf->no_ca_names) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "no-ca-names"); + space++; + } + + if (conf->early_data) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "allow-0rtt"); + space++; + } + if (conf->ca_file) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "ca-file %s", conf->ca_file); + space++; + } + if (conf->crl_file) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "crl-file %s", conf->crl_file); + space++; + } + if (conf->ciphers) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "ciphers %s", conf->ciphers); + space++; + } +#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER) + if (conf->ciphersuites) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "ciphersuites %s", conf->ciphersuites); + space++; + } +#endif + if (conf->curves) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "curves %s", conf->curves); + space++; + } + if (conf->ecdhe) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "ecdhe %s", conf->ecdhe); + space++; + } + + /* the crt-lists only support ssl-min-ver and ssl-max-ver */ + /* XXX: this part need to be revamp so we don't dump the default settings */ + if (conf->ssl_methods.min) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "ssl-min-ver %s", methodVersions[conf->ssl_methods.min].name); + space++; + } + + if (conf->ssl_methods.max) { + if (space) chunk_appendf(buf, " "); + chunk_appendf(buf, "ssl-max-ver %s", methodVersions[conf->ssl_methods.max].name); + space++; + } + + chunk_appendf(buf, "] "); + + return; +} + +/* dump a list of filters */ +static void dump_crtlist_filters(struct buffer *buf, struct crtlist_entry *entry) +{ + int space = 0; + int i; + + if (!entry->fcount) + return; + + for (i = 0; i < entry->fcount; i++) { + if (space) + chunk_appendf(buf, " "); + chunk_appendf(buf, "%s", entry->filters[i]); + space = 1; + } + return; +} + +/* CLI IO handler for '(show|dump) ssl crt-list' */ +static int cli_io_handler_dump_crtlist(struct appctx *appctx) +{ + struct buffer *trash = alloc_trash_chunk(); + struct stream_interface *si = appctx->owner; + struct ebmb_node *lnode; + + if (trash == NULL) + return 1; + + /* dump the list of crt-lists */ + lnode = appctx->ctx.cli.p1; + if (lnode == NULL) + lnode = ebmb_first(&crtlists_tree); + while (lnode) { + chunk_appendf(trash, "%s\n", lnode->key); + if (ci_putchk(si_ic(si), trash) == -1) { + si_rx_room_blk(si); + goto yield; + } + lnode = ebmb_next(lnode); + } + return 1; +yield: + appctx->ctx.cli.p1 = lnode; + return 0; +} + +/* CLI IO handler for '(show|dump) ssl crt-list ' */ +static int cli_io_handler_dump_crtlist_entries(struct appctx *appctx) +{ + struct buffer *trash = alloc_trash_chunk(); + struct crtlist *crtlist; + struct stream_interface *si = appctx->owner; + struct crtlist_entry *entry; + + if (trash == NULL) + return 1; + + crtlist = ebmb_entry(appctx->ctx.cli.p0, struct crtlist, node); + + entry = appctx->ctx.cli.p1; + if (entry == NULL) { + entry = LIST_ELEM((crtlist->ord_entries).n, typeof(entry), by_crtlist); + chunk_appendf(trash, "# %s\n", crtlist->node.key); + if (ci_putchk(si_ic(si), trash) == -1) { + si_rx_room_blk(si); + goto yield; + } + } + + list_for_each_entry_from(entry, &crtlist->ord_entries, by_crtlist) { + struct ckch_store *store; + const char *filename; + + store = entry->node.key; + filename = store->path; + if (appctx->ctx.cli.i0 == 's') /* show */ + chunk_appendf(trash, "%p ", entry); + chunk_appendf(trash, "%s", filename); + dump_crtlist_sslconf(trash, entry->ssl_conf); + dump_crtlist_filters(trash, entry); + chunk_appendf(trash, "\n"); + + if (ci_putchk(si_ic(si), trash) == -1) { + si_rx_room_blk(si); + goto yield; + } + } + return 1; +yield: + appctx->ctx.cli.p1 = entry; + return 0; +} + +/* CLI argument parser for '(show|dump) ssl crt-list' */ +static int cli_parse_dump_crtlist(char **args, char *payload, struct appctx *appctx, void *private) +{ + struct ebmb_node *lnode; + int mode; + + if (!cli_has_level(appctx, ACCESS_LVL_ADMIN)) + return 1; + + appctx->ctx.cli.p0 = NULL; + appctx->ctx.cli.p1 = NULL; + mode = (int)args[0][0]; /* 'd' or 's' */ + + if (mode == 'd' && !*args[3]) + return cli_err(appctx, "'dump ssl crt-list' expects a filename or a directory\n"); + + if (*args[3]) { + lnode = ebst_lookup(&crtlists_tree, args[3]); + if (lnode == NULL) + return cli_err(appctx, "didn't find the specified filename\n"); + + appctx->ctx.cli.p0 = lnode; + appctx->io_handler = cli_io_handler_dump_crtlist_entries; + } + appctx->ctx.cli.i0 = mode; + + return 0; +} /* Type of SSL payloads that can be updated over the CLI */ @@ -11897,6 +12158,8 @@ static struct cli_kw_list cli_kws = {{ },{ { { "commit", "ssl", "cert", NULL }, "commit ssl cert : commit a certificate file", cli_parse_commit_cert, cli_io_handler_commit_cert, cli_release_commit_cert }, { { "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 }, + { { "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