From b28ccfc725c9a52401aaa09de0734a44bd44a02d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 7 Mar 2019 15:23:19 +0000 Subject: [tls] Display cross-certificate and OCSP status messages 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 --- src/net/tls.c | 20 +++++++++++++++ src/net/validator.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/net/tls.c b/src/net/tls.c index 1cd37e77..510bef8c 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -47,6 +47,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /* 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 ), }; diff --git a/src/net/validator.c b/src/net/validator.c index 25d81bd2..f6b03ff4 100644 --- a/src/net/validator.c +++ b/src/net/validator.c @@ -40,6 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include #include @@ -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 */ -- cgit v1.2.3-55-g7522