From dafc068f12a3bd5e81210a5129cb4b8d1023bdcc Mon Sep 17 00:00:00 2001 From: Remi Tricot-Le Breton Date: Mon, 13 Mar 2023 15:56:34 +0100 Subject: [PATCH] MINOR: ssl: Accept certpath as param in "show ssl ocsp-response" CLI command In order to increase usability, the "show ssl ocsp-response" also takes a frontend certificate path as parameter. In such a case, it behaves the same way as "show ssl cert foo.pem.ocsp". --- doc/management.txt | 19 ++++++------ reg-tests/ssl/show_ssl_ocspresponse.vtc | 8 +++++ src/ssl_ocsp.c | 39 +++++++++++++++++++------ 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/doc/management.txt b/doc/management.txt index 008f2b09e..022348e67 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -3432,16 +3432,17 @@ show ssl crt-list [-n] [] ecdsa.pem:3 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] localhost !www.test1.com ecdsa.pem:4 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] -show ssl ocsp-response [[text|base64] ] +show ssl ocsp-response [[text|base64] ] Display the IDs of the OCSP tree entries corresponding to all the OCSP responses used in HAProxy, as well as the issuer's name and key hash and the - serial number of the certificate for which the OCSP response was built. If a - valid is provided, display the contents of the corresponding OCSP - response. When an is provided, it it possible to format in which the - data is dumped. The 'text' option is the default one and it allows to display - detailed information about the OCSP response the same way as in an "openssl - ocsp -respin -text" call. The 'base64' format allows to dump - the contents of an OCSP response in base64. + serial number of the certificate for which the OCSP response was built. + If a valid or the of a valid frontend certificate is provided, + display the contents of the corresponding OCSP response. When an is + provided, it it possible to define the format in which the data is dumped. + The 'text' option is the default one and it allows to display detailed + information about the OCSP response the same way as in an "openssl ocsp + -respin -text" call. The 'base64' format allows to dump the + contents of an OCSP response in base64. Example : @@ -3471,7 +3472,7 @@ show ssl ocsp-response [[text|base64] ] Next Update: Oct 12 15:43:38 2048 GMT [...] - $ echo "show ssl ocsp-response base64 304b300906052b0e03021a0500041448dac[...]" | socat /var/run/haproxy.sock - + $ echo "show ssl ocsp-response base64 /path_to_cert/foo.pem" | socat /var/run/haproxy.sock - MIIB8woBAKCCAewwggHoBgkrBgEFBQcwAQEEggHZMIIB1TCBvqE[...] show ssl ocsp-updates diff --git a/reg-tests/ssl/show_ssl_ocspresponse.vtc b/reg-tests/ssl/show_ssl_ocspresponse.vtc index 3d67fe530..6c1a6b2cf 100644 --- a/reg-tests/ssl/show_ssl_ocspresponse.vtc +++ b/reg-tests/ssl/show_ssl_ocspresponse.vtc @@ -64,6 +64,14 @@ haproxy h1 -cli { expect ~ "Cert Status: good" } +# Test the "show ssl ocsp-response" command with a certificate path as parameter +shell { + ocsp_response=$(echo "show ssl ocsp-response ${testdir}/show_ocsp_server.pem" | socat "${tmpdir}/h1/stats" -) + + echo "$ocsp_response" | grep "Responder Id: C = FR, O = HAProxy Technologies, CN = ocsp.haproxy.com" && + echo "$ocsp_response" | grep "Cert Status: good" +} + # Test the "show ssl cert foo.pem.ocsp" command haproxy h1 -cli { send "show ssl cert" diff --git a/src/ssl_ocsp.c b/src/ssl_ocsp.c index 14fb7e915..17d217e07 100644 --- a/src/ssl_ocsp.c +++ b/src/ssl_ocsp.c @@ -1464,31 +1464,52 @@ static int cli_parse_show_ocspresponse(char **args, char *payload, struct appctx #if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) && !defined OPENSSL_IS_BORINGSSL) struct show_ocspresp_cli_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx)); - int certid_arg_idx = 3; + int arg_idx = 3; if (*args[3]) { struct certificate_ocsp *ocsp = NULL; char key[OCSP_MAX_CERTID_ASN1_LENGTH] = {}; int key_length = OCSP_MAX_CERTID_ASN1_LENGTH; char *key_ptr = key; + unsigned char *p; + struct ckch_store *ckch_store = NULL; if (strcmp(args[3], "text") == 0) { ctx->format = SHOW_OCSPRESP_FMT_TEXT; - ++certid_arg_idx; + ++arg_idx; } else if (strcmp(args[3], "base64") == 0) { ctx->format = SHOW_OCSPRESP_FMT_B64; - ++certid_arg_idx; + ++arg_idx; } - if (ctx->format != SHOW_OCSPRESP_FMT_DFLT && !*args[certid_arg_idx]) + if (ctx->format != SHOW_OCSPRESP_FMT_DFLT && !*args[arg_idx]) return cli_err(appctx, "'show ssl ocsp-response [text|base64]' expects a valid certid.\n"); - if (strlen(args[certid_arg_idx]) > OCSP_MAX_CERTID_ASN1_LENGTH*2) { - return cli_err(appctx, "'show ssl ocsp-response' received a too big key.\n"); + /* Try to convert parameter into an OCSP certid first, and consider it + * as a filename if it fails. */ + if (strlen(args[arg_idx]) > OCSP_MAX_CERTID_ASN1_LENGTH*2 || + !parse_binary(args[arg_idx], &key_ptr, &key_length, NULL)) { + + key_ptr = key; + key_length = 0; + + /* The operations on the CKCH architecture are locked so we can + * manipulate ckch_store and ckch_inst */ + if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock)) { + return cli_err(appctx, "Operations on certificates are currently locked!\n"); + } + + ckch_store = ckchs_lookup(args[arg_idx]); + + if (ckch_store) { + p = (unsigned char*)key; + key_length = i2d_OCSP_CERTID(ckch_store->data->ocsp_cid, &p); + } + HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock); } - if (!parse_binary(args[certid_arg_idx], &key_ptr, &key_length, NULL)) { - return cli_err(appctx, "'show ssl ocsp-response' received an invalid key.\n"); + if (key_length == 0) { + return cli_err(appctx, "'show ssl ocsp-response' expects a valid certid or certificate path.\n"); } HA_SPIN_LOCK(OCSP_LOCK, &ocsp_tree_lock); @@ -1496,7 +1517,7 @@ static int cli_parse_show_ocspresponse(char **args, char *payload, struct appctx if (!ocsp) { HA_SPIN_UNLOCK(OCSP_LOCK, &ocsp_tree_lock); - return cli_err(appctx, "Certificate ID does not match any certificate.\n"); + return cli_err(appctx, "Certificate ID or path does not match any certificate.\n"); } ++ocsp->refcount; HA_SPIN_UNLOCK(OCSP_LOCK, &ocsp_tree_lock);