summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/browser_private.h15
-rw-r--r--desktop/browser_window.c46
-rw-r--r--desktop/gui_factory.c3
-rw-r--r--desktop/sslcert_viewer.c184
-rw-r--r--desktop/sslcert_viewer.h14
5 files changed, 208 insertions, 54 deletions
diff --git a/desktop/browser_private.h b/desktop/browser_private.h
index 6e45052d7..41b8fefd4 100644
--- a/desktop/browser_private.h
+++ b/desktop/browser_private.h
@@ -89,13 +89,6 @@ struct browser_fetch_parameters {
bool parent_quirks; /**< Optional parent quirks */
};
-/**
- * The SSL context for a fetch, as provided by the fetchers
- */
-struct browser_ssl_info {
- struct ssl_cert_info certs[MAX_SSL_CERTS]; /**< The certificate chain */
- size_t num; /**< The number of certificates in the chain */
-};
/**
* Browser window data.
@@ -113,9 +106,9 @@ struct browser_window {
struct browser_fetch_parameters current_parameters;
/**
- * The SSL information for the current content
+ * The certificate chain for the current content
*/
- struct browser_ssl_info current_ssl_info;
+ struct cert_chain *current_cert_chain;
/**
* Content handle of page in process of being loaded or NULL
@@ -129,9 +122,9 @@ struct browser_window {
struct browser_fetch_parameters loading_parameters;
/**
- * The SSL information for the loading content
+ * The certificate chain for the loading content
*/
- struct browser_ssl_info loading_ssl_info;
+ struct cert_chain *loading_cert_chain;
/**
* Favicon
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index 06f41ddf3..6defe0182 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -743,9 +743,10 @@ static nserror browser_window_content_ready(struct browser_window *bw)
browser_window__free_fetch_parameters(&bw->current_parameters);
bw->current_parameters = bw->loading_parameters;
memset(&bw->loading_parameters, 0, sizeof(bw->loading_parameters));
- /* Transfer the SSL info */
- bw->current_ssl_info = bw->loading_ssl_info;
- bw->loading_ssl_info.num = 0;
+ /* Transfer the certificate chain */
+ cert_chain_free(bw->current_cert_chain);
+ bw->current_cert_chain = bw->loading_cert_chain;
+ bw->loading_cert_chain = NULL;
}
/* Format the new content to the correct dimensions */
@@ -1136,7 +1137,7 @@ browser_window__handle_bad_certs(struct browser_window *bw,
nserror err;
/* Initially we don't know WHY the SSL cert was bad */
const char *reason = messages_get_sslcode(SSL_CERT_ERR_UNKNOWN);
- size_t n;
+ size_t depth;
memset(&params, 0, sizeof(params));
@@ -1151,12 +1152,14 @@ browser_window__handle_bad_certs(struct browser_window *bw,
goto out;
}
- for (n = 0; n < bw->loading_ssl_info.num; ++n) {
- size_t idx = bw->loading_ssl_info.num - (n + 1);
- ssl_cert_err err = bw->loading_ssl_info.certs[idx].err;
- if (err != SSL_CERT_ERR_OK) {
- reason = messages_get_sslcode(err);
- break;
+ if (bw->loading_cert_chain != NULL) {
+ for (depth = 0; depth < bw->loading_cert_chain->depth; ++depth) {
+ size_t idx = bw->loading_cert_chain->depth - (depth + 1);
+ ssl_cert_err err = bw->loading_cert_chain->certs[idx].err;
+ if (err != SSL_CERT_ERR_OK) {
+ reason = messages_get_sslcode(err);
+ break;
+ }
}
}
@@ -1175,8 +1178,7 @@ browser_window__handle_bad_certs(struct browser_window *bw,
}
err = guit->misc->cert_verify(url,
- bw->loading_ssl_info.certs,
- bw->loading_ssl_info.num,
+ bw->loading_cert_chain,
browser_window__handle_ssl_query_response,
bw);
@@ -1352,11 +1354,8 @@ browser_window_callback(hlcache_handle *c, const hlcache_event *event, void *pw)
switch (event->type) {
case CONTENT_MSG_SSL_CERTS:
/* SSL certificate information has arrived, store it */
- assert(event->data.certs.num < MAX_SSL_CERTS);
- memcpy(&bw->loading_ssl_info.certs[0],
- event->data.certs.certs,
- sizeof(struct ssl_cert_info) * event->data.certs.num);
- bw->loading_ssl_info.num = event->data.certs.num;
+ cert_chain_free(bw->loading_cert_chain);
+ cert_chain_dup(event->data.chain, &bw->loading_cert_chain);
break;
case CONTENT_MSG_LOG:
@@ -3431,7 +3430,8 @@ navigate_internal_real(struct browser_window *bw,
fetch_is_post = (params->post_urlenc != NULL || params->post_multipart != NULL);
/* Clear SSL info for load */
- bw->loading_ssl_info.num = 0;
+ cert_chain_free(bw->loading_cert_chain);
+ bw->loading_cert_chain = NULL;
/* Set up retrieval parameters */
if (!(params->flags & BW_NAVIGATE_UNVERIFIABLE)) {
@@ -4707,17 +4707,17 @@ browser_window_page_info_state browser_window_get_page_info_state(
}
/* Exported interface, documented in browser_window.h */
-nserror browser_window_get_ssl_chain(struct browser_window *bw, size_t *num,
- struct ssl_cert_info **chain)
+nserror
+browser_window_get_ssl_chain(struct browser_window *bw,
+ struct cert_chain **chain)
{
assert(bw != NULL);
- if (bw->current_ssl_info.num == 0) {
+ if (bw->current_cert_chain == NULL) {
return NSERROR_NOT_FOUND;
}
- *num = bw->current_ssl_info.num;
- *chain = &(bw->current_ssl_info.certs[0]);
+ *chain = bw->current_cert_chain;
return NSERROR_OK;
}
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index 8b52e5469..7ef457a7a 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -639,8 +639,7 @@ static nserror gui_default_launch_url(struct nsurl *url)
static nserror gui_default_cert_verify(nsurl *url,
- const struct ssl_cert_info *certs,
- unsigned long num,
+ const struct cert_chain *chain,
nserror (*cb)(bool proceed, void *pw),
void *cbpw)
{
diff --git a/desktop/sslcert_viewer.c b/desktop/sslcert_viewer.c
index 4d8725757..ec0fd3431 100644
--- a/desktop/sslcert_viewer.c
+++ b/desktop/sslcert_viewer.c
@@ -52,6 +52,21 @@ enum sslcert_viewer_field {
typedef nserror (*response_cb)(bool proceed, void *pw);
/**
+ * ssl certificate information for certificate error message
+ */
+struct ssl_cert_info {
+ long version; /**< Certificate version */
+ char not_before[32]; /**< Valid from date */
+ char not_after[32]; /**< Valid to date */
+ int sig_type; /**< Signature type */
+ char serialnum[64]; /**< Serial number */
+ char issuer[256]; /**< Issuer details */
+ char subject[256]; /**< Subject details */
+ int cert_type; /**< Certificate type */
+ ssl_cert_err err; /**< Whatever is wrong with this certificate */
+};
+
+/**
* ssl certificate verification context.
*/
struct sslcert_session_data {
@@ -473,38 +488,183 @@ nserror sslcert_viewer_fini(struct sslcert_session_data *ssl_d)
return err;
}
+#ifdef WITH_OPENSSL
+
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+
+static nserror
+der_to_certinfo(const uint8_t *der,
+ size_t der_length,
+ struct ssl_cert_info *info)
+{
+ BIO *mem;
+ BUF_MEM *buf;
+ const ASN1_INTEGER *asn1_num;
+ BIGNUM *bignum;
+ X509 *cert; /**< Pointer to certificate */
+
+ if (der == NULL) {
+ return NSERROR_OK;
+ }
+
+ cert = d2i_X509(NULL, &der, der_length);
+ if (cert == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ /* get certificate version */
+ info->version = X509_get_version(cert);
+
+ /* not before date */
+ mem = BIO_new(BIO_s_mem());
+ ASN1_TIME_print(mem, X509_get_notBefore(cert));
+ BIO_get_mem_ptr(mem, &buf);
+ (void) BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+ memcpy(info->not_before,
+ buf->data,
+ min(sizeof(info->not_before) - 1, (unsigned)buf->length));
+ info->not_before[min(sizeof(info->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(cert));
+ BIO_get_mem_ptr(mem, &buf);
+ (void) BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+ memcpy(info->not_after,
+ buf->data,
+ min(sizeof(info->not_after) - 1, (unsigned)buf->length));
+ info->not_after[min(sizeof(info->not_after) - 1, (unsigned)buf->length)] = 0;
+ BUF_MEM_free(buf);
+
+ /* signature type */
+ info->sig_type = X509_get_signature_type(cert);
+
+ /* serial number */
+ asn1_num = X509_get_serialNumber(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(info->serialnum,
+ tmp,
+ sizeof(info->serialnum));
+ info->serialnum[sizeof(info->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(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(info->issuer,
+ buf->data,
+ min(sizeof(info->issuer) - 1, (unsigned) buf->length));
+ info->issuer[min(sizeof(info->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(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(info->subject,
+ buf->data,
+ min(sizeof(info->subject) - 1, (unsigned)buf->length));
+ info->subject[min(sizeof(info->subject) - 1, (unsigned) buf->length)] = 0;
+ BUF_MEM_free(buf);
+
+ /* type of certificate */
+ info->cert_type = X509_certificate_type(cert, X509_get_pubkey(cert));
+
+ X509_free(cert);
+
+ return NSERROR_OK;
+}
+#else
+static nserror
+der_to_certinfo(uint8_t *der, size_t der_length, struct ssl_cert_info *info)
+{
+ return NSERROR_NOT_IMPLEMENTED;
+}
+#endif
+
+/* copy certificate data */
+static nserror
+convert_chain_to_cert_info(const struct cert_chain *chain,
+ struct ssl_cert_info **cert_info_out)
+{
+ struct ssl_cert_info *certs;
+ size_t depth;
+ nserror res;
+
+ certs = calloc(chain->depth, sizeof(struct ssl_cert_info));
+ if (certs == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ for (depth = 0; depth < chain->depth;depth++) {
+ res = der_to_certinfo(chain->certs[depth].der,
+ chain->certs[depth].der_length,
+ certs + depth);
+ if (res != NSERROR_OK) {
+ free(certs);
+ return res;
+ }
+ certs[depth].err = chain->certs[depth].err;
+ }
+
+ *cert_info_out = certs;
+ return NSERROR_OK;
+}
/* Exported interface, documented in sslcert_viewer.h */
nserror
-sslcert_viewer_create_session_data(unsigned long num,
- struct nsurl *url,
+sslcert_viewer_create_session_data(struct nsurl *url,
nserror (*cb)(bool proceed, void *pw),
void *cbpw,
- const struct ssl_cert_info *certs,
+ const struct cert_chain *chain,
struct sslcert_session_data **ssl_d)
{
struct sslcert_session_data *data;
-
+ nserror res;
assert(url != NULL);
- assert(certs != NULL);
+ assert(chain != NULL);
data = malloc(sizeof(struct sslcert_session_data));
if (data == NULL) {
*ssl_d = NULL;
return NSERROR_NOMEM;
}
-
- /* copy certificate data */
- data->certs = malloc(num * sizeof(struct ssl_cert_info));
- if (data->certs == NULL) {
+ res = convert_chain_to_cert_info(chain, &data->certs);
+ if (res != NSERROR_OK) {
free(data);
*ssl_d = NULL;
- return NSERROR_NOMEM;
+ return res;
}
- memcpy(data->certs, certs, num * sizeof(struct ssl_cert_info));
data->url = nsurl_ref(url);
- data->num = num;
+ data->num = chain->depth;
data->cb = cb;
data->cbpw = cbpw;
diff --git a/desktop/sslcert_viewer.h b/desktop/sslcert_viewer.h
index 6955e0167..854284083 100644
--- a/desktop/sslcert_viewer.h
+++ b/desktop/sslcert_viewer.h
@@ -32,16 +32,15 @@ struct redraw_context;
struct core_window_callback_table;
struct rect;
struct nsurl;
-struct ssl_cert_info;
+struct cert_chain;
/**
* Create ssl certificate viewer session data.
*
- * \param num The number of certificates in the chain
* \param url Address of the page we're inspecting certificates of
* \param cb Low level cache callback
* \param cbpw Low level cache private data
- * \param certs The SSL certificates
+ * \param chain The SSL certificate chain
* \param ssl_d Updated to SSL certificate session data
* \return NSERROR_OK on success, appropriate error otherwise
*
@@ -49,8 +48,10 @@ struct ssl_cert_info;
* sslcert_viewer_fini destroys the session data.
*/
nserror sslcert_viewer_create_session_data(
- unsigned long num, struct nsurl *url, nserror (*cb)(bool proceed, void *pw),
- void *cbpw, const struct ssl_cert_info *certs,
+ struct nsurl *url,
+ nserror (*cb)(bool proceed, void *pw),
+ void *cbpw,
+ const struct cert_chain *chain,
struct sslcert_session_data **ssl_d);
@@ -65,7 +66,8 @@ nserror sslcert_viewer_create_session_data(
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
- void *core_window_handle, struct sslcert_session_data *ssl_d);
+ void *core_window_handle,
+ struct sslcert_session_data *ssl_d);
/**