mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-08 08:07:10 +02:00
MINOR: ssl/cli: show/dump ssl crt-list
Implement 2 new commands on the CLI: show ssl crt-list [<filename>]: 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 <filename>: 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.
This commit is contained in:
parent
a48e7ece48
commit
a6ffd5bf8a
263
src/ssl_sock.c
263
src/ssl_sock.c
@ -10848,6 +10848,267 @@ static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appc
|
|||||||
}
|
}
|
||||||
#endif
|
#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 <filename>' */
|
||||||
|
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 */
|
/* 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 <certfile> : commit a certificate file", cli_parse_commit_cert, cli_io_handler_commit_cert, cli_release_commit_cert },
|
{ { "commit", "ssl", "cert", NULL }, "commit ssl cert <certfile> : commit a certificate file", cli_parse_commit_cert, cli_io_handler_commit_cert, cli_release_commit_cert },
|
||||||
{ { "abort", "ssl", "cert", NULL }, "abort ssl cert <certfile> : abort a transaction for a certificate file", cli_parse_abort_cert, NULL, NULL },
|
{ { "abort", "ssl", "cert", NULL }, "abort ssl cert <certfile> : abort a transaction for a certificate file", cli_parse_abort_cert, NULL, NULL },
|
||||||
{ { "show", "ssl", "cert", NULL }, "show ssl cert [<certfile>] : display the SSL certificates used in memory, or the details of a <certfile>", cli_parse_show_cert, cli_io_handler_show_cert, cli_release_show_cert },
|
{ { "show", "ssl", "cert", NULL }, "show ssl cert [<certfile>] : display the SSL certificates used in memory, or the details of a <certfile>", cli_parse_show_cert, cli_io_handler_show_cert, cli_release_show_cert },
|
||||||
|
{ { "dump", "ssl", "crt-list", NULL }, "dump ssl crt-list <filename> : dump the content of a crt-list <filename>", cli_parse_dump_crtlist, cli_io_handler_dump_crtlist, NULL },
|
||||||
|
{ { "show", "ssl", "crt-list", NULL }, "show ssl crt-list [<filename>] : show the list of crt-lists or the content of a crt-list <filename>", cli_parse_dump_crtlist, cli_io_handler_dump_crtlist, NULL },
|
||||||
{ { NULL }, NULL, NULL, NULL }
|
{ { NULL }, NULL, NULL, NULL }
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user