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".
diff --git a/doc/management.txt b/doc/management.txt
index 008f2b0..022348e 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -3432,16 +3432,17 @@
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] <id>]
+show ssl ocsp-response [[text|base64] <id|path>]
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 <id> is provided, display the contents of the corresponding OCSP
- response. When an <id> 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 <ocsp-response> -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 <id> or the <path> of a valid frontend certificate is provided,
+ display the contents of the corresponding OCSP response. When an <id> 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 <ocsp-response> -text" call. The 'base64' format allows to dump the
+ contents of an OCSP response in base64.
Example :
@@ -3471,7 +3472,7 @@
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 3d67fe5..6c1a6b2 100644
--- a/reg-tests/ssl/show_ssl_ocspresponse.vtc
+++ b/reg-tests/ssl/show_ssl_ocspresponse.vtc
@@ -64,6 +64,14 @@
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 14fb7e9..17d217e 100644
--- a/src/ssl_ocsp.c
+++ b/src/ssl_ocsp.c
@@ -1464,31 +1464,52 @@
#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 @@
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);