]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl: Add the "show ssl cert foo.pem.ocsp" CLI command
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Thu, 10 Jun 2021 11:51:15 +0000 (13:51 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Thu, 10 Jun 2021 14:44:11 +0000 (16:44 +0200)
Add the ability to dump an OCSP response details through a call to "show
ssl cert cert.pem.ocsp". It can also be used on an ongoing transaction
by prefixing the certificate name with a '*'.
Even if the ckch structure holds an ocsp_response buffer, we still need
to look for the actual ocsp response entry in the ocsp response tree
rather than just dumping the ckch's buffer details because when updating
an ocsp response through a "set ssl ocsp-response" call, the
corresponding buffer in the ckch is not updated accordingly. So this
buffer, even if it is not empty, might hold an outdated ocsp response.

doc/management.txt
src/ssl_ckch.c

index 641f253bf575b5d0407e1a9308bae0da956d3c3a..91c0340a2f23031a27a3f9d81408da9eee77e08d 100644 (file)
@@ -2992,6 +2992,11 @@ show ssl cert [<filename>]
   certificate. This command can be useful to check if a certificate was well
   updated. You can also display details on a transaction by prefixing the
   filename by an asterisk.
+  This command can also be used to display the details of a certificate's OCSP
+  response by suffixing the filename with a ".ocsp" extension. It works for
+  committed certificates as well as for ongoing transactions. On a committed
+  certificate, this command is equivalent to calling "show ssl ocsp-response"
+  with the certificate's corresponding OCSP response ID.
 
   Example :
 
index 071f45aa9a8273cd4fb25b753a92484df8873dbc..67eae099b19bd5652377b9c52744afea9e43222f 100644 (file)
@@ -1599,6 +1599,52 @@ yield:
        return 0; /* should come back */
 }
 
+
+/* IO handler of the details "show ssl cert <filename.ocsp>" */
+static int cli_io_handler_show_cert_ocsp_detail(struct appctx *appctx)
+{
+#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
+       struct stream_interface *si = appctx->owner;
+       struct ckch_store *ckchs = appctx->ctx.cli.p0;
+       struct buffer *out = alloc_trash_chunk();
+       int from_transaction = appctx->ctx.cli.i0;
+
+       if (!out)
+               goto end_no_putchk;
+
+       /* If we try to display an ongoing transaction's OCSP response, we
+        * need to dump the ckch's ocsp_response buffer directly.
+        * Otherwise, we must rebuild the certificate's certid in order to
+        * look for the current OCSP response in the tree. */
+       if (from_transaction && ckchs->ckch->ocsp_response) {
+               ssl_ocsp_response_print(ckchs->ckch->ocsp_response, out);
+       }
+       else {
+               unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH] = {};
+               unsigned int key_length = 0;
+
+               if (ckch_store_build_certid(ckchs, (unsigned char*)key, &key_length) < 0)
+                       goto end_no_putchk;
+
+               ssl_get_ocspresponse_detail(key, out);
+       }
+
+       if (ci_putchk(si_ic(si), out) == -1) {
+               si_rx_room_blk(si);
+               goto yield;
+       }
+
+end_no_putchk:
+       free_trash_chunk(out);
+       return 1;
+yield:
+       free_trash_chunk(out);
+       return 0; /* should come back */
+#else
+       return cli_err(appctx, "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n");
+#endif
+}
+
 /* parsing function for 'show ssl cert [certfile]' */
 static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
 {
@@ -1614,7 +1660,20 @@ static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx
 
        /* check if there is a certificate to lookup */
        if (*args[3]) {
+               int show_ocsp_detail = 0;
+               int from_transaction = 0;
+               char *end;
+
+               /* We manage the special case "certname.ocsp" through which we
+                * can show the details of an OCSP response. */
+               end = strrchr(args[3], '.');
+               if (end && strcmp(end+1, "ocsp") == 0) {
+                       *end = '\0';
+                       show_ocsp_detail = 1;
+               }
+
                if (*args[3] == '*') {
+                       from_transaction = 1;
                        if (!ckchs_transaction.new_ckchs)
                                goto error;
 
@@ -1631,7 +1690,12 @@ static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx
 
                appctx->ctx.cli.p0 = ckchs;
                /* use the IO handler that shows details */
-               appctx->io_handler = cli_io_handler_show_cert_detail;
+               if (show_ocsp_detail) {
+                       appctx->ctx.cli.i0 = from_transaction;
+                       appctx->io_handler = cli_io_handler_show_cert_ocsp_detail;
+               }
+               else
+                       appctx->io_handler = cli_io_handler_show_cert_detail;
        }
 
        return 0;