From 0c34d06494afe217ace7460c66df800d457dd2e8 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 23 Feb 2020 16:06:52 +0000 Subject: Keep the complete certificate chain from a fetch Instead of extracting information from the X509 certificate chain in the fetcher the entire chain is propagated in Distinguished Encoding Rules (DER) format. This allows all the information contained in a certificate chain to be retained which can subsequently be presented to the user --- content/content.h | 7 +- content/fetch.h | 5 +- content/fetchers/curl.c | 177 ++++++++++-------------------- content/hlcache.c | 9 +- content/llcache.c | 285 +++++++++++++++--------------------------------- content/llcache.h | 35 +++--- 6 files changed, 171 insertions(+), 347 deletions(-) (limited to 'content') diff --git a/content/content.h b/content/content.h index 144a698c1..f8f8d32f1 100644 --- a/content/content.h +++ b/content/content.h @@ -44,7 +44,7 @@ struct object_params; struct rect; struct redraw_context; struct llcache_query_msg; -struct ssl_cert_info; +struct cert_chain; /** Status of a content */ typedef enum { @@ -118,10 +118,7 @@ union content_msg_data { * CONTENT_MSG_SSL_CERTS - The certificate chain from the * underlying fetch */ - struct { - const struct ssl_cert_info *certs; /**< The chain */ - size_t num; /**< The number of certs in the chain */ - } certs; + const struct cert_chain *chain; /** * CONTENT_MSG_ERROR - Error from content or underlying fetch diff --git a/content/fetch.h b/content/fetch.h index 9a81ece95..9e80b2685 100644 --- a/content/fetch.h +++ b/content/fetch.h @@ -75,10 +75,7 @@ typedef struct fetch_msg { const char *realm; } auth; - struct { - const struct ssl_cert_info *certs; - size_t num_certs; - } certs; + const struct cert_chain *chain; } data; } fetch_msg; diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c index 0be33ae16..83e92d808 100644 --- a/content/fetchers/curl.c +++ b/content/fetchers/curl.c @@ -149,7 +149,7 @@ struct curl_fetch_info { struct curl_httppost *post_multipart; /**< Multipart post data, or 0. */ uint64_t last_progress_update; /**< Time of last progress update */ int cert_depth; /**< deepest certificate in use */ - struct cert_info cert_data[MAX_SSL_CERTS]; /**< HTTPS certificate data */ + struct cert_info cert_data[MAX_CERT_DEPTH]; /**< HTTPS certificate data */ }; /** curl handle cache entry */ @@ -471,128 +471,37 @@ failed: static void fetch_curl_report_certs_upstream(struct curl_fetch_info *f) { - int depth; + size_t depth; BIO *mem; - BUF_MEM *buf; - const ASN1_INTEGER *asn1_num; - BIGNUM *bignum; - struct ssl_cert_info ssl_certs[MAX_SSL_CERTS]; + BUF_MEM *buf[MAX_CERT_DEPTH]; + struct cert_chain chain; fetch_msg msg; - struct cert_info *certs = f->cert_data; - memset(ssl_certs, 0, sizeof(ssl_certs)); + struct cert_info *certs; + + memset(&chain, 0, sizeof(chain)); + + certs = f->cert_data; + chain.depth = f->cert_depth + 1; /* 0 indexed certificate depth */ - for (depth = 0; depth <= f->cert_depth; depth++) { + for (depth = 0; depth < chain.depth; depth++) { if (certs[depth].cert == NULL) { /* This certificate is missing, skip it */ - ssl_certs[depth].err = SSL_CERT_ERR_CERT_MISSING; + chain.certs[depth].err = SSL_CERT_ERR_CERT_MISSING; continue; } - /* get certificate version */ - ssl_certs[depth].version = X509_get_version(certs[depth].cert); - - /* not before date */ - mem = BIO_new(BIO_s_mem()); - ASN1_TIME_print(mem, X509_get_notBefore(certs[depth].cert)); - BIO_get_mem_ptr(mem, &buf); - (void) BIO_set_close(mem, BIO_NOCLOSE); - BIO_free(mem); - memcpy(ssl_certs[depth].not_before, - buf->data, - min(sizeof(ssl_certs[depth].not_before) - 1, - (unsigned)buf->length)); - ssl_certs[depth].not_before[min(sizeof(ssl_certs[depth].not_before) - 1, - (unsigned)buf->length)] = 0; - BUF_MEM_free(buf); - - /* not after date */ - mem = BIO_new(BIO_s_mem()); - ASN1_TIME_print(mem, - X509_get_notAfter(certs[depth].cert)); - BIO_get_mem_ptr(mem, &buf); - (void) BIO_set_close(mem, BIO_NOCLOSE); - BIO_free(mem); - memcpy(ssl_certs[depth].not_after, - buf->data, - min(sizeof(ssl_certs[depth].not_after) - 1, - (unsigned)buf->length)); - ssl_certs[depth].not_after[min(sizeof(ssl_certs[depth].not_after) - 1, - (unsigned)buf->length)] = 0; - BUF_MEM_free(buf); - - /* signature type */ - ssl_certs[depth].sig_type = - X509_get_signature_type(certs[depth].cert); - - /* serial number */ - asn1_num = X509_get_serialNumber(certs[depth].cert); - if (asn1_num != NULL) { - bignum = ASN1_INTEGER_to_BN(asn1_num, NULL); - if (bignum != NULL) { - char *tmp = BN_bn2hex(bignum); - if (tmp != NULL) { - strncpy(ssl_certs[depth].serialnum, - tmp, - sizeof(ssl_certs[depth].serialnum)); - ssl_certs[depth].serialnum[sizeof(ssl_certs[depth].serialnum)-1] = '\0'; - OPENSSL_free(tmp); - } - BN_free(bignum); - bignum = NULL; - } - } - - /* issuer name */ - mem = BIO_new(BIO_s_mem()); - X509_NAME_print_ex(mem, - X509_get_issuer_name(certs[depth].cert), - 0, XN_FLAG_SEP_CPLUS_SPC | - XN_FLAG_DN_REV | XN_FLAG_FN_NONE); - BIO_get_mem_ptr(mem, &buf); - (void) BIO_set_close(mem, BIO_NOCLOSE); - BIO_free(mem); - memcpy(ssl_certs[depth].issuer, - buf->data, - min(sizeof(ssl_certs[depth].issuer) - 1, - (unsigned) buf->length)); - ssl_certs[depth].issuer[min(sizeof(ssl_certs[depth].issuer) - 1, - (unsigned) buf->length)] = 0; - BUF_MEM_free(buf); - - /* subject */ - mem = BIO_new(BIO_s_mem()); - X509_NAME_print_ex(mem, - X509_get_subject_name(certs[depth].cert), - 0, - XN_FLAG_SEP_CPLUS_SPC | - XN_FLAG_DN_REV | - XN_FLAG_FN_NONE); - BIO_get_mem_ptr(mem, &buf); - (void) BIO_set_close(mem, BIO_NOCLOSE); - BIO_free(mem); - memcpy(ssl_certs[depth].subject, - buf->data, - min(sizeof(ssl_certs[depth].subject) - 1, - (unsigned)buf->length)); - ssl_certs[depth].subject[min(sizeof(ssl_certs[depth].subject) - 1, - (unsigned) buf->length)] = 0; - BUF_MEM_free(buf); - - /* type of certificate */ - ssl_certs[depth].cert_type = - X509_certificate_type(certs[depth].cert, - X509_get_pubkey(certs[depth].cert)); - /* error code (if any) */ switch (certs[depth].err) { case X509_V_OK: - ssl_certs[depth].err = SSL_CERT_ERR_OK; + chain.certs[depth].err = SSL_CERT_ERR_OK; break; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: /* fallthrough */ case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - ssl_certs[depth].err = SSL_CERT_ERR_BAD_ISSUER; + chain.certs[depth].err = SSL_CERT_ERR_BAD_ISSUER; break; + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: /* fallthrough */ case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: @@ -600,41 +509,66 @@ fetch_curl_report_certs_upstream(struct curl_fetch_info *f) case X509_V_ERR_CERT_SIGNATURE_FAILURE: /* fallthrough */ case X509_V_ERR_CRL_SIGNATURE_FAILURE: - ssl_certs[depth].err = SSL_CERT_ERR_BAD_SIG; + chain.certs[depth].err = SSL_CERT_ERR_BAD_SIG; break; + case X509_V_ERR_CERT_NOT_YET_VALID: /* fallthrough */ case X509_V_ERR_CRL_NOT_YET_VALID: - ssl_certs[depth].err = SSL_CERT_ERR_TOO_YOUNG; + chain.certs[depth].err = SSL_CERT_ERR_TOO_YOUNG; break; + case X509_V_ERR_CERT_HAS_EXPIRED: /* fallthrough */ case X509_V_ERR_CRL_HAS_EXPIRED: - ssl_certs[depth].err = SSL_CERT_ERR_TOO_OLD; + chain.certs[depth].err = SSL_CERT_ERR_TOO_OLD; break; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - ssl_certs[depth].err = SSL_CERT_ERR_SELF_SIGNED; + chain.certs[depth].err = SSL_CERT_ERR_SELF_SIGNED; break; + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - ssl_certs[depth].err = SSL_CERT_ERR_CHAIN_SELF_SIGNED; + chain.certs[depth].err = SSL_CERT_ERR_CHAIN_SELF_SIGNED; break; + case X509_V_ERR_CERT_REVOKED: - ssl_certs[depth].err = SSL_CERT_ERR_REVOKED; + chain.certs[depth].err = SSL_CERT_ERR_REVOKED; break; + case X509_V_ERR_HOSTNAME_MISMATCH: - ssl_certs[depth].err = SSL_CERT_ERR_HOSTNAME_MISMATCH; + chain.certs[depth].err = SSL_CERT_ERR_HOSTNAME_MISMATCH; break; + default: - ssl_certs[depth].err = SSL_CERT_ERR_UNKNOWN; + chain.certs[depth].err = SSL_CERT_ERR_UNKNOWN; break; } + + /* + * get certificate in Distinguished Encoding Rules (DER) format. + */ + mem = BIO_new(BIO_s_mem()); + i2d_X509_bio(mem, certs[depth].cert); + BIO_get_mem_ptr(mem, &buf[depth]); + (void) BIO_set_close(mem, BIO_NOCLOSE); + BIO_free(mem); + + chain.certs[depth].der = (uint8_t *)buf[depth]->data; + chain.certs[depth].der_length = buf[depth]->length; } msg.type = FETCH_CERTS; - msg.data.certs.certs = ssl_certs; - msg.data.certs.num_certs = depth; + msg.data.chain = &chain; fetch_send_callback(&msg, f->fetch_handle); + + /* release the openssl memory buffer */ + for (depth = 0; depth < chain.depth; depth++) { + if (buf[depth] != NULL) { + BUF_MEM_free(buf[depth]); + } + } } @@ -667,7 +601,7 @@ fetch_curl_verify_callback(int verify_ok, X509_STORE_CTX *x509_ctx) fetch = X509_STORE_CTX_get_app_data(x509_ctx); /* certificate chain is excessively deep so fail verification */ - if (depth >= MAX_SSL_CERTS) { + if (depth >= MAX_CERT_DEPTH) { X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_CERT_CHAIN_TOO_LONG); return 0; @@ -1098,8 +1032,11 @@ static void fetch_curl_free(void *vf) curl_formfree(f->post_multipart); } - for (i = 0; i < MAX_SSL_CERTS && f->cert_data[i].cert; i++) { - ns_X509_free(f->cert_data[i].cert); + /* free certificate data */ + for (i = 0; i < MAX_CERT_DEPTH; i++) { + if (f->cert_data[i].cert != NULL) { + ns_X509_free(f->cert_data[i].cert); + } } free(f); diff --git a/content/hlcache.c b/content/hlcache.c index ec011ecdc..23dbc5706 100644 --- a/content/hlcache.c +++ b/content/hlcache.c @@ -423,8 +423,10 @@ static nserror hlcache_migrate_ctx(hlcache_retrieval_ctx *ctx, * \param pw Pointer to client-specific data * \return NSERROR_OK on success, appropriate error otherwise */ -static nserror hlcache_llcache_callback(llcache_handle *handle, - const llcache_event *event, void *pw) +static nserror +hlcache_llcache_callback(llcache_handle *handle, + const llcache_event *event, + void *pw) { hlcache_retrieval_ctx *ctx = pw; lwc_string *effective_type = NULL; @@ -439,8 +441,7 @@ static nserror hlcache_llcache_callback(llcache_handle *handle, hlcache_event hlevent; hlevent.type = CONTENT_MSG_SSL_CERTS; - hlevent.data.certs.certs = event->data.certs.certs; - hlevent.data.certs.num = event->data.certs.num; + hlevent.data.chain = event->data.chain; ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw); } diff --git a/content/llcache.c b/content/llcache.c index 8a71f1874..3a75bf971 100644 --- a/content/llcache.c +++ b/content/llcache.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "netsurf/inttypes.h" #include "utils/config.h" @@ -175,8 +176,7 @@ struct llcache_object { size_t source_len; /**< Byte length of source data */ size_t source_alloc; /**< Allocated size of source buffer */ - size_t ssl_cert_count; /**< The number of SSL certificates stored */ - struct ssl_cert_info *ssl_certs; /**< SSL certificate information if count is non-zero */ + struct cert_chain *chain; /**< Certificate chain from the fetch */ llcache_store_state store_state; /**< where the data for the object is stored */ @@ -969,11 +969,7 @@ static nserror llcache_object_destroy(llcache_object *object) NSLOG(llcache, DEBUG, "Destroying object %p, %s", object, nsurl_access(object->url)); - if (object->ssl_cert_count != 0) { - free(object->ssl_certs); - object->ssl_certs = NULL; - object->ssl_cert_count = 0; - } + cert_chain_free(object->chain); if (object->source_data != NULL) { if (object->store_state == LLCACHE_STATE_DISC) { @@ -1240,6 +1236,13 @@ llcache_serialise_metadata(llcache_object *object, char *op; unsigned int hloop; int use; + size_t cert_chain_depth; + + if (object->chain != NULL) { + cert_chain_depth = object->chain->depth; + } else { + cert_chain_depth = 0; + } allocsize = 10 + 1; /* object length */ @@ -1251,22 +1254,19 @@ llcache_serialise_metadata(llcache_object *object, allocsize += 10 + 1; /* space for number of header entries */ - allocsize += 10 + 1; /* space for number of SSL certificates */ - - allocsize += nsurl_length(object->url) + 1; - for (hloop = 0 ; hloop < object->num_headers ; hloop++) { allocsize += strlen(object->headers[hloop].name) + 1; allocsize += strlen(object->headers[hloop].value) + 1; } - for (hloop = 0; hloop < object->ssl_cert_count; hloop++) { - allocsize += (10 + 1) * 4; /* version, sig_type, cert_type, err */ - allocsize += strlen(object->ssl_certs[hloop].not_before) + 1; - allocsize += strlen(object->ssl_certs[hloop].not_after) + 1; - allocsize += strlen(object->ssl_certs[hloop].serialnum) + 1; - allocsize += strlen(object->ssl_certs[hloop].issuer) + 1; - allocsize += strlen(object->ssl_certs[hloop].subject) + 1; + allocsize += nsurl_length(object->url) + 1; + + /* space for number of DER formatted certificates */ + allocsize += 10 + 1; + + for (hloop = 0; hloop < cert_chain_depth; hloop++) { + allocsize += 10 + 1; /* error status */ + allocsize += 4 * ((object->chain->certs[hloop].der_length + 2) / 3); } data = malloc(allocsize); @@ -1351,8 +1351,8 @@ llcache_serialise_metadata(llcache_object *object, datasize -= use; } - /* number of ssl certificates */ - use = snprintf(op, datasize, "%" PRIsizet, object->ssl_cert_count); + /* number of DER formatted ssl certificates */ + use = snprintf(op, datasize, "%" PRIsizet, cert_chain_depth); if (use < 0) { goto operror; } @@ -1363,80 +1363,13 @@ llcache_serialise_metadata(llcache_object *object, datasize -= use; /* SSL certificates */ - for (hloop = 0; hloop < object->ssl_cert_count; hloop++) { - struct ssl_cert_info *cert = &(object->ssl_certs[hloop]); - /* Certificate version */ - use = snprintf(op, datasize, "%ld", cert->version); - if (use < 0) { - goto operror; - } - use++; /* does not count the null */ - if (use > datasize) - goto overflow; - op += use; - datasize -= use; - /* not_before */ - use = snprintf(op, datasize, "%s", cert->not_before); - if (use < 0) { - goto operror; - } - use++; /* does not count the null */ - if (use > datasize) - goto overflow; - op += use; - datasize -= use; - /* not_after */ - use = snprintf(op, datasize, "%s", cert->not_after); - if (use < 0) { - goto operror; - } - use++; /* does not count the null */ - if (use > datasize) - goto overflow; - op += use; - datasize -= use; - /* Signature type */ - use = snprintf(op, datasize, "%d", cert->sig_type); - if (use < 0) { - goto operror; - } - use++; /* does not count the null */ - if (use > datasize) - goto overflow; - op += use; - datasize -= use; - /* serialnum */ - use = snprintf(op, datasize, "%s", cert->serialnum); - if (use < 0) { - goto operror; - } - use++; /* does not count the null */ - if (use > datasize) - goto overflow; - op += use; - datasize -= use; - /* issuer */ - use = snprintf(op, datasize, "%s", cert->issuer); - if (use < 0) { - goto operror; - } - use++; /* does not count the null */ - if (use > datasize) - goto overflow; - op += use; - datasize -= use; - /* subject */ - use = snprintf(op, datasize, "%s", cert->subject); - if (use < 0) { - goto operror; - } - use++; /* does not count the null */ - if (use > datasize) - goto overflow; - op += use; - datasize -= use; - /* Certificate type */ - use = snprintf(op, datasize, "%d", cert->cert_type); + for (hloop = 0; hloop < cert_chain_depth; hloop++) { + size_t output_length; + nsuerror res; + + /* Certificate error code */ + use = snprintf(op, datasize, "%d", + (int)(object->chain->certs[hloop].err)); if (use < 0) { goto operror; } @@ -1445,14 +1378,26 @@ llcache_serialise_metadata(llcache_object *object, goto overflow; op += use; datasize -= use; - /* Certificate error code */ - use = snprintf(op, datasize, "%d", (int)(cert->err)); - if (use < 0) { - goto operror; + + /* DER certificate data in base64 encoding */ + if (object->chain->certs[hloop].der != NULL) { + output_length = datasize; + res = nsu_base64_encode( + object->chain->certs[hloop].der, + object->chain->certs[hloop].der_length, + (uint8_t *)op, + &output_length); + if (res != NSUERROR_OK) { + goto operror; + } + use = output_length; + } else { + use = 0; } - use++; /* does not count the null */ + use++; /* allow for null */ if (use > datasize) goto overflow; + *(op + output_length) = 0; op += use; datasize -= use; } @@ -1510,7 +1455,7 @@ llcache_process_metadata(llcache_object *object) size_t num_headers; size_t hloop; size_t ssl_cert_count = 0; - struct ssl_cert_info *ssl_certs = NULL; + struct cert_chain *chain = NULL; NSLOG(llcache, INFO, "Retrieving metadata"); @@ -1642,7 +1587,7 @@ llcache_process_metadata(llcache_object *object) goto skip_ssl_certificates; } - /* Next line is the number of SSL certificates*/ + /* Next line is the number of DER base64 encoded certificates */ line++; ln += lnsize + 1; lnsize = strlen(ln); @@ -1657,72 +1602,20 @@ llcache_process_metadata(llcache_object *object) goto skip_ssl_certificates; } - ssl_certs = calloc(sizeof(struct ssl_cert_info), ssl_cert_count); - if (ssl_certs == NULL) { - res = NSERROR_NOMEM; + if (ssl_cert_count > MAX_CERT_DEPTH) { + res = NSERROR_INVALID; + goto format_error; + } + + res = cert_chain_alloc(ssl_cert_count, &chain); + if (res != NSERROR_OK) { goto format_error; } for (hloop = 0; hloop < ssl_cert_count; hloop++) { - struct ssl_cert_info *cert = &ssl_certs[hloop]; int errcode; - /* Certificate version */ - line++; - ln += lnsize + 1; - lnsize = strlen(ln); - remaining -= lnsize + 1; - if ((lnsize < 1) || (sscanf(ln, "%ld", &cert->version) != 1)) { - res = NSERROR_INVALID; - goto format_error; - } - /* Not before */ - line++; - ln += lnsize + 1; - lnsize = strlen(ln); - remaining -= lnsize + 1; - memcpy(&cert->not_before, ln, lnsize); - /* Not after */ - line++; - ln += lnsize + 1; - lnsize = strlen(ln); - remaining -= lnsize + 1; - memcpy(&cert->not_after, ln, lnsize); - /* Signature type */ - line++; - ln += lnsize + 1; - lnsize = strlen(ln); - remaining -= lnsize + 1; - if ((lnsize < 1) || (sscanf(ln, "%d", &cert->sig_type) != 1)) { - res = NSERROR_INVALID; - goto format_error; - } - /* Serial Number */ - line++; - ln += lnsize + 1; - lnsize = strlen(ln); - remaining -= lnsize + 1; - memcpy(&cert->serialnum, ln, lnsize); - /* issuer */ - line++; - ln += lnsize + 1; - lnsize = strlen(ln); - remaining -= lnsize + 1; - memcpy(&cert->issuer, ln, lnsize); - /* subject */ - line++; - ln += lnsize + 1; - lnsize = strlen(ln); - remaining -= lnsize + 1; - memcpy(&cert->subject, ln, lnsize); - /* Certificate type */ - line++; - ln += lnsize + 1; - lnsize = strlen(ln); - remaining -= lnsize + 1; - if ((lnsize < 1) || (sscanf(ln, "%d", &cert->cert_type) != 1)) { - res = NSERROR_INVALID; - goto format_error; - } + nsuerror nsures; + /* Certificate error code */ line++; ln += lnsize + 1; @@ -1735,9 +1628,25 @@ llcache_process_metadata(llcache_object *object) if (errcode < SSL_CERT_ERR_OK || errcode > SSL_CERT_ERR_MAX_KNOWN) { /* Error with the cert code, assume UNKNOWN */ - cert->err = SSL_CERT_ERR_UNKNOWN; + chain->certs[hloop].err = SSL_CERT_ERR_UNKNOWN; } else { - cert->err = (ssl_cert_err)errcode; + chain->certs[hloop].err = (ssl_cert_err)errcode; + } + + /* base64 encoded DER certificate data */ + line++; + ln += lnsize + 1; + lnsize = strlen(ln); + remaining -= lnsize + 1; + if (lnsize > 0) { + nsures = nsu_base64_decode_alloc((const uint8_t *)ln, + lnsize, + &chain->certs[hloop].der, + &chain->certs[hloop].der_length); + if (nsures != NSUERROR_OK) { + res = NSERROR_NOMEM; + goto format_error; + } } } @@ -1754,8 +1663,7 @@ skip_ssl_certificates: object->cache.res_time = response_time; object->cache.fin_time = completion_time; - object->ssl_cert_count = ssl_cert_count; - object->ssl_certs = ssl_certs; + object->chain = chain; /* object stored in backing store */ object->store_state = LLCACHE_STATE_DISC; @@ -1768,9 +1676,7 @@ format_error: line, res); guit->llcache->release(object->url, BACKING_STORE_META); - if (ssl_certs != NULL) { - free(ssl_certs); - } + cert_chain_free(chain); return res; } @@ -3173,21 +3079,15 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p) case FETCH_CERTS: /* Certificate information from the fetch */ - /* Persist the data onto our object */ - object->ssl_certs = calloc(sizeof(struct ssl_cert_info), - msg->data.certs.num_certs); - if (object->ssl_certs != NULL) { - object->ssl_cert_count = msg->data.certs.num_certs; - memcpy(object->ssl_certs, msg->data.certs.certs, - sizeof(struct ssl_cert_info) * object->ssl_cert_count); - } - - /* Now pass on the event */ - event.type = LLCACHE_EVENT_GOT_CERTS; - event.data.certs.certs = msg->data.certs.certs; - event.data.certs.num = msg->data.certs.num_certs; + /* Persist the chain onto our object */ + error = cert_chain_dup(msg->data.chain, &object->chain); + if (error != NSERROR_OK) { + /* Now pass on the event */ + event.type = LLCACHE_EVENT_GOT_CERTS; + event.data.chain = msg->data.chain; - error = llcache_send_event_to_users(object, &event); + error = llcache_send_event_to_users(object, &event); + } break; /* Events requiring action */ @@ -3388,10 +3288,9 @@ static nserror llcache_object_notify_users(llcache_object *object) handle->state = LLCACHE_FETCH_HEADERS; /* Emit any certificate data we hold */ - if (object->ssl_cert_count > 0) { + if (object->chain != NULL) { event.type = LLCACHE_EVENT_GOT_CERTS; - event.data.certs.certs = object->ssl_certs; - event.data.certs.num = object->ssl_cert_count; + event.data.chain = object->chain; error = handle->cb(handle, &event, handle->pw); } else { error = NSERROR_OK; @@ -3613,16 +3512,12 @@ llcache_object_snapshot(llcache_object *object, llcache_object **snapshot) } } - if (object->ssl_cert_count != 0) { - newobj->ssl_certs = calloc(sizeof(struct ssl_cert_info), - object->ssl_cert_count); - if (newobj->ssl_certs == NULL) { + if (object->chain != NULL) { + error = cert_chain_dup(object->chain, &newobj->chain); + if (error != NSERROR_OK) { llcache_object_destroy(newobj); - return NSERROR_NOMEM; + return error; } - memcpy(newobj->ssl_certs, object->ssl_certs, - sizeof(struct ssl_cert_info) * object->ssl_cert_count); - newobj->ssl_cert_count = object->ssl_cert_count; } newobj->fetch.state = LLCACHE_FETCH_COMPLETE; @@ -3662,7 +3557,7 @@ total_object_size(llcache_object *object) } } - tot += object->ssl_cert_count * sizeof(struct ssl_cert_info); + tot += cert_chain_size(object->chain); return tot; } diff --git a/content/llcache.h b/content/llcache.h index 8d2411e0a..514272f29 100644 --- a/content/llcache.h +++ b/content/llcache.h @@ -30,7 +30,7 @@ #include "utils/errors.h" #include "utils/nsurl.h" -struct ssl_cert_info; +struct cert_chain; struct fetch_multipart_data; /** Handle for low-level cache object */ @@ -83,26 +83,23 @@ typedef enum { * and must be copied if it is desirable to retain. */ typedef struct { - llcache_event_type type; /**< Type of event */ + llcache_event_type type; /**< Type of event */ union { struct { - const uint8_t *buf; /**< Buffer of data */ - size_t len; /**< Length of buffer, in bytes */ - } data; /**< Received data */ + const uint8_t *buf; /**< Buffer of data */ + size_t len; /**< Byte length of buffer */ + } data; /**< Received data */ struct { - nserror code; /**< The error code */ - const char *msg; /**< Error message */ + nserror code; /**< The error code */ + const char *msg; /**< Error message */ } error; - const char *progress_msg; /**< Progress message */ + const char *progress_msg; /**< Progress message */ struct { - nsurl *from; /**< Redirect origin */ - nsurl *to; /**< Redirect target */ - } redirect; /**< Fetch URL redirect occured */ - struct { - const struct ssl_cert_info *certs; /**< The chain */ - size_t num; /**< Number of certs in chain */ - } certs; - } data; /**< Event data */ + nsurl *from; /**< Redirect origin */ + nsurl *to; /**< Redirect target */ + } redirect; /**< Fetch URL redirect occured */ + const struct cert_chain *chain; /**< Certificate chain */ + } data; /**< Event data */ } llcache_event; /** @@ -171,17 +168,17 @@ struct llcache_parameters { size_t hysteresis; /**< The hysteresis around the target size */ /** The minimum lifetime to consider sending objects to backing store.*/ - int minimum_lifetime; + int minimum_lifetime; /** The minimum bandwidth to allow the backing store to * use in bytes/second */ - size_t minimum_bandwidth; + size_t minimum_bandwidth; /** The maximum bandwidth to allow the backing store to use in * bytes/second */ - size_t maximum_bandwidth; + size_t maximum_bandwidth; /** The time quantum over which to calculate the bandwidth values */ -- cgit v1.2.3