[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 <mcb30@ipxe.org>
pull/108/head
Michael Brown 2019-03-07 15:23:19 +00:00
parent 447e5cd447
commit b28ccfc725
2 changed files with 82 additions and 8 deletions

View 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 ),
};

View 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 */