]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Display cross-certificate and OCSP status messages
authorMichael Brown <mcb30@ipxe.org>
Thu, 7 Mar 2019 15:23:19 +0000 (15:23 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 7 Mar 2019 15:23:19 +0000 (15:23 +0000)
TLS connections will almost always create background connections to
perform cross-signed certificate downloads and OCSP checks.  There is
currently no direct visibility into which checks are taking place,
which makes troubleshooting difficult in the absence of either a
packet capture or a debug build.

Use the job progress message buffer to report the current cross-signed
certificate download or OCSP status check, where applicable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/net/tls.c
src/net/validator.c

index 1cd37e776533fed154e15052a3539282552e78bb..510bef8c4031068ed7c887d6a70480f273113a2d 100644 (file)
@@ -47,6 +47,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/certstore.h>
 #include <ipxe/rbg.h>
 #include <ipxe/validator.h>
+#include <ipxe/job.h>
 #include <ipxe/tls.h>
 
 /* Disambiguate the various error causes */
@@ -2570,12 +2571,31 @@ static int tls_plainstream_deliver ( struct tls_connection *tls,
        return rc;
 }
 
+/**
+ * Report job progress
+ *
+ * @v tls              TLS connection
+ * @v progress         Progress report to fill in
+ * @ret ongoing_rc     Ongoing job status code (if known)
+ */
+static int tls_progress ( struct tls_connection *tls,
+                         struct job_progress *progress ) {
+
+       /* Return cipherstream or validator progress as applicable */
+       if ( tls_ready ( tls ) ) {
+               return job_progress ( &tls->cipherstream, progress );
+       } else {
+               return job_progress ( &tls->validator, progress );
+       }
+}
+
 /** TLS plaintext stream interface operations */
 static struct interface_operation tls_plainstream_ops[] = {
        INTF_OP ( xfer_deliver, struct tls_connection *,
                  tls_plainstream_deliver ),
        INTF_OP ( xfer_window, struct tls_connection *,
                  tls_plainstream_window ),
+       INTF_OP ( job_progress, struct tls_connection *, tls_progress ),
        INTF_OP ( intf_close, struct tls_connection *, tls_close ),
 };
 
index 25d81bd24642b5e406419a3e637a3d5e8c828df6..f6b03ff41949078bb62306fec9a425ca2b7990ed 100644 (file)
@@ -40,6 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/base64.h>
 #include <ipxe/crc32.h>
 #include <ipxe/ocsp.h>
+#include <ipxe/job.h>
 #include <ipxe/validator.h>
 #include <config/crypto.h>
 
@@ -49,6 +50,17 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  *
  */
 
+struct validator;
+
+/** A certificate validator action */
+struct validator_action {
+       /** Name */
+       const char *name;
+       /** Action to take upon completed transfer */
+       int ( * done ) ( struct validator *validator, const void *data,
+                        size_t len );
+};
+
 /** A certificate validator */
 struct validator {
        /** Reference count */
@@ -67,9 +79,16 @@ struct validator {
        struct ocsp_check *ocsp;
        /** Data buffer */
        struct xfer_buffer buffer;
-       /** Action to take upon completed transfer */
-       int ( * done ) ( struct validator *validator, const void *data,
-                        size_t len );
+
+       /** Current action */
+       const struct validator_action *action;
+       /** Current certificate
+        *
+        * This will always be present within the certificate chain
+        * and so this pointer does not hold a reference to the
+        * certificate.
+        */
+       struct x509_certificate *cert;
 };
 
 /**
@@ -123,8 +142,29 @@ static void validator_finished ( struct validator *validator, int rc ) {
  *
  */
 
+/**
+ * Report job progress
+ *
+ * @v validator                Certificate validator
+ * @v progress         Progress report to fill in
+ * @ret ongoing_rc     Ongoing job status code (if known)
+ */
+static int validator_progress ( struct validator *validator,
+                               struct job_progress *progress ) {
+
+       /* Report current action, if applicable */
+       if ( validator->action ) {
+               snprintf ( progress->message, sizeof ( progress->message ),
+                          "%s %s", validator->action->name,
+                          x509_name ( validator->cert ) );
+       }
+
+       return 0;
+}
+
 /** Certificate validator job control interface operations */
 static struct interface_operation validator_job_operations[] = {
+       INTF_OP ( job_progress, struct validator *, validator_progress ),
        INTF_OP ( intf_close, struct validator *, validator_finished ),
 };
 
@@ -236,6 +276,12 @@ static int validator_append ( struct validator *validator,
        return rc;
 }
 
+/** Cross-signing certificate download validator action */
+static const struct validator_action validator_crosscert = {
+       .name = "XCRT",
+       .done = validator_append,
+};
+
 /**
  * Start download of cross-signing certificate
  *
@@ -285,7 +331,8 @@ static int validator_start_download ( struct validator *validator,
               x509_name ( cert ), uri_string );
 
        /* Set completion handler */
-       validator->done = validator_append;
+       validator->action = &validator_crosscert;
+       validator->cert = cert;
 
        /* Open URI */
        if ( ( rc = xfer_open_uri_string ( &validator->xfer,
@@ -350,6 +397,12 @@ static int validator_ocsp_validate ( struct validator *validator,
        return 0;
 }
 
+/** OCSP validator action */
+static const struct validator_action validator_ocsp = {
+       .name = "OCSP",
+       .done = validator_ocsp_validate,
+};
+
 /**
  * Start OCSP check
  *
@@ -374,7 +427,8 @@ static int validator_start_ocsp ( struct validator *validator,
        }
 
        /* Set completion handler */
-       validator->done = validator_ocsp_validate;
+       validator->action = &validator_ocsp;
+       validator->cert = cert;
 
        /* Open URI */
        uri_string = validator->ocsp->uri_string;
@@ -421,9 +475,9 @@ static void validator_xfer_close ( struct validator *validator, int rc ) {
                validator, validator_name ( validator ) );
 
        /* Process completed download */
-       assert ( validator->done != NULL );
-       if ( ( rc = validator->done ( validator, validator->buffer.data,
-                                      validator->buffer.len ) ) != 0 )
+       assert ( validator->action != NULL );
+       if ( ( rc = validator->action->done ( validator, validator->buffer.data,
+                                             validator->buffer.len ) ) != 0 )
                goto err_append;
 
        /* Free downloaded data */