summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x!NetSurf/Resources/de/Templates,fecbin14363 -> 15334 bytes
-rw-r--r--!NetSurf/Resources/en/Templates,fecbin14307 -> 15278 bytes
-rw-r--r--!NetSurf/Resources/fr/Templates,fecbin14490 -> 15461 bytes
-rw-r--r--!NetSurf/Resources/nl/Templates,fecbin14393 -> 15364 bytes
-rw-r--r--content/certdb.c154
-rw-r--r--content/certdb.h18
-rw-r--r--content/content.h13
-rw-r--r--content/fetch.c229
-rw-r--r--content/fetch.h22
-rw-r--r--content/fetchcache.c26
-rw-r--r--desktop/401login.h2
-rw-r--r--desktop/browser.c25
-rw-r--r--desktop/gui.h8
-rw-r--r--desktop/options.c3
-rw-r--r--desktop/options.h1
-rw-r--r--makefile32
-rw-r--r--render/html.c16
-rw-r--r--riscos/401login.c10
-rw-r--r--riscos/dialog.c44
-rw-r--r--riscos/gui.h7
-rw-r--r--riscos/plugin.c13
-rw-r--r--riscos/sslcert.c182
-rw-r--r--utils/config.h5
23 files changed, 744 insertions, 66 deletions
diff --git a/!NetSurf/Resources/de/Templates,fec b/!NetSurf/Resources/de/Templates,fec
index 00d2825de..b2eef5366 100755
--- a/!NetSurf/Resources/de/Templates,fec
+++ b/!NetSurf/Resources/de/Templates,fec
Binary files differ
diff --git a/!NetSurf/Resources/en/Templates,fec b/!NetSurf/Resources/en/Templates,fec
index 3efd72aa2..e7c51e864 100644
--- a/!NetSurf/Resources/en/Templates,fec
+++ b/!NetSurf/Resources/en/Templates,fec
Binary files differ
diff --git a/!NetSurf/Resources/fr/Templates,fec b/!NetSurf/Resources/fr/Templates,fec
index 0fdd61f1d..fd82917a2 100644
--- a/!NetSurf/Resources/fr/Templates,fec
+++ b/!NetSurf/Resources/fr/Templates,fec
Binary files differ
diff --git a/!NetSurf/Resources/nl/Templates,fec b/!NetSurf/Resources/nl/Templates,fec
index 4a0b1b76b..c922942a7 100644
--- a/!NetSurf/Resources/nl/Templates,fec
+++ b/!NetSurf/Resources/nl/Templates,fec
Binary files differ
diff --git a/content/certdb.c b/content/certdb.c
new file mode 100644
index 000000000..78c6ec04f
--- /dev/null
+++ b/content/certdb.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 John M Bell <jmb202@ecs.soton.ac.uk>
+ */
+
+/** \file
+ * HTTPS certificate verification database (implementation)
+ *
+ * URLs of servers with invalid SSL certificates are stored hashed by
+ * canonical root URI (absoluteURI with no abs_path part - see RFC 2617)
+ * for fast lookup.
+ */
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netsurf/utils/config.h"
+#include "netsurf/content/certdb.h"
+#define NDEBUG
+#include "netsurf/utils/log.h"
+#include "netsurf/utils/url.h"
+
+#define HASH_SIZE 77
+
+#ifdef WITH_SSL
+
+struct cert_entry {
+ char *root_url; /**< Canonical root URL */
+ struct cert_entry *next;
+};
+
+static struct cert_entry *cert_table[HASH_SIZE];
+
+static unsigned int certdb_hash(const char *s);
+static void certdb_dump(void);
+
+/**
+ * Insert an entry into the database
+ *
+ * \param url Absolute URL to resource
+ * \return true on success, false on error.
+ */
+bool certdb_insert(const char *url)
+{
+ char *canon;
+ unsigned int hash;
+ struct cert_entry *entry;
+ url_func_result ret;
+
+ assert(url);
+
+ LOG(("Adding '%s'", url));
+
+ ret = url_canonical_root(url, &canon);
+ if (ret != URL_FUNC_OK)
+ return false;
+
+ LOG(("'%s'", canon));
+
+ hash = certdb_hash(canon);
+
+ /* Look for existing entry */
+ for (entry = cert_table[hash]; entry; entry = entry->next) {
+ if (strcmp(entry->root_url, canon) == 0) {
+ free(canon);
+ return true;
+ }
+ }
+
+ /* not found => create new */
+ entry = malloc(sizeof(struct cert_entry));
+ if (!entry) {
+ free(canon);
+ return false;
+ }
+
+ entry->root_url = canon;
+ entry->next = cert_table[hash];
+ cert_table[hash] = entry;
+
+ return true;
+}
+
+/**
+ * Retrieve certificate details for an URL from the database
+ *
+ * \param url Absolute URL to consider
+ * \return certificate details, or NULL if none found.
+ */
+const char *certdb_get(const char *url)
+{
+ char *canon;
+ struct cert_entry *entry;
+ url_func_result ret;
+
+ assert(url);
+
+ LOG(("Searching for '%s'", url));
+
+ certdb_dump();
+
+ ret = url_canonical_root(url, &canon);
+ if (ret != URL_FUNC_OK)
+ return NULL;
+
+ /* Find cert entry */
+ for (entry = cert_table[certdb_hash(canon)]; entry;
+ entry = entry->next) {
+ if (strcmp(entry->root_url, canon) == 0) {
+ free(canon);
+ return entry->root_url;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Hash function for keys.
+ */
+unsigned int certdb_hash(const char *s)
+{
+ unsigned int i, z = 0, m;
+ if (!s)
+ return 0;
+
+ m = strlen(s);
+
+ for (i = 0; i != m && s[i]; i++)
+ z += s[i] & 0x1f; /* lower 5 bits, case insensitive */
+ return z % HASH_SIZE;
+}
+
+/**
+ * Dump contents of auth db to stderr
+ */
+void certdb_dump(void)
+{
+#ifndef NDEBUG
+ int i;
+ struct cert_entry *e;
+
+ for (i = 0; i != HASH_SIZE; i++) {
+ LOG(("%d:", i));
+ for (e = cert_table[i]; e; e = e->next) {
+ LOG(("\t%s", e->root_url));
+ }
+ }
+#endif
+}
+
+#endif
diff --git a/content/certdb.h b/content/certdb.h
new file mode 100644
index 000000000..28aa88664
--- /dev/null
+++ b/content/certdb.h
@@ -0,0 +1,18 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 John M Bell <jmb202@ecs.soton.ac.uk>
+ */
+
+/** \file
+ * HTTPS certificate verification database (interface)
+ */
+
+#ifndef _NETSURF_CONTENT_CERTDB_H_
+#define _NETSURF_CONTENT_CERTDB_H_
+
+bool certdb_insert(const char *url);
+const char *certdb_get(const char *url);
+
+#endif
diff --git a/content/content.h b/content/content.h
index f40888009..21c4f399c 100644
--- a/content/content.h
+++ b/content/content.h
@@ -139,6 +139,7 @@ struct cache_data;
struct content;
struct fetch;
struct object_params;
+struct ssl_cert_info;
/** Used in callbacks to indicate what has occurred. */
@@ -154,7 +155,10 @@ typedef enum {
CONTENT_MSG_NEWPTR, /**< address of structure has changed */
CONTENT_MSG_REFRESH, /**< wants refresh */
#ifdef WITH_AUTH
- CONTENT_MSG_AUTH /**< authentication required */
+ CONTENT_MSG_AUTH, /**< authentication required */
+#endif
+#ifdef WITH_SSL
+ CONTENT_MSG_SSL /**< SSL cert verify failed */
#endif
} content_msg;
@@ -175,8 +179,13 @@ union content_msg_data {
/** Dimensions to plot object with. */
float object_width, object_height;
} redraw;
- char *auth_realm; /**< Realm, for CONTENT_MSG_AUTH. */
+ const char *auth_realm; /**< Realm, for CONTENT_MSG_AUTH. */
int delay; /**< Minimum delay, for CONTENT_MSG_REFRESH */
+ struct {
+ /** Certificate chain (certs[0] == server) */
+ const struct ssl_cert_info *certs;
+ unsigned long num; /**< Number of certs in chain */
+ } ssl;
};
/** Linked list of users of a content. */
diff --git a/content/fetch.c b/content/fetch.c
index 0d9ccd583..25202340b 100644
--- a/content/fetch.c
+++ b/content/fetch.c
@@ -31,9 +31,15 @@
#endif
#include "curl/curl.h"
#include "netsurf/utils/config.h"
+#ifdef WITH_SSL
+#include "openssl/ssl.h"
+#endif
#ifdef WITH_AUTH
#include "netsurf/content/authdb.h"
#endif
+#ifdef WITH_SSL
+#include "netsurf/content/certdb.h"
+#endif
#include "netsurf/content/fetch.h"
#include "netsurf/desktop/options.h"
#include "netsurf/render/form.h"
@@ -46,10 +52,18 @@
bool fetch_active; /**< Fetches in progress, please call fetch_poll(). */
+#ifdef WITH_SSL
+/** SSL certificate info */
+struct cert_info {
+ X509 *cert; /**< Pointer to certificate */
+ long err; /**< OpenSSL error code */
+};
+#endif
+
/** Information for a single fetch. */
struct fetch {
CURL * curl_handle; /**< cURL handle if being fetched, or 0. */
- void (*callback)(fetch_msg msg, void *p, const char *data,
+ void (*callback)(fetch_msg msg, void *p, const void *data,
unsigned long size);
/**< Callback function. */
bool had_headers; /**< Headers have been processed. */
@@ -70,6 +84,10 @@ struct fetch {
struct cache_data cachedata; /**< Cache control data */
time_t last_modified; /**< If-Modified-Since time */
time_t file_etag; /**< ETag for local objects */
+#ifdef WITH_SSL
+#define MAX_CERTS 10
+ struct cert_info cert_data[MAX_CERTS]; /**< HTTPS certificate data */
+#endif
struct fetch *queue_prev; /**< Previous fetch for this host. */
struct fetch *queue_next; /**< Next fetch for this host. */
struct fetch *prev; /**< Previous active fetch in ::fetch_list. */
@@ -86,6 +104,9 @@ static char fetch_progress_buffer[256]; /**< Progress buffer for cURL */
static char fetch_proxy_userpwd[100]; /**< Proxy authentication details. */
static CURLcode fetch_set_options(struct fetch *f);
+#ifdef WITH_SSL
+static CURLcode fetch_sslctxfun(CURL *curl_handle, SSL_CTX *sslctx, void *p);
+#endif
static void fetch_free(struct fetch *f);
static void fetch_stop(struct fetch *f);
static void fetch_done(CURL *curl_handle, CURLcode result);
@@ -98,6 +119,10 @@ static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
static bool fetch_process_headers(struct fetch *f);
static struct curl_httppost *fetch_post_convert(
struct form_successful_control *control);
+#ifdef WITH_SSL
+static int fetch_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx);
+static int fetch_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm);
+#endif
/**
@@ -148,14 +173,6 @@ void fetch_init(void)
if (option_ca_bundle)
SETOPT(CURLOPT_CAINFO, option_ca_bundle);
- if (!option_ssl_verify_certificates) {
- /* disable verification of SSL certificates.
- * security? we've heard of it...
- */
- SETOPT(CURLOPT_SSL_VERIFYPEER, 0L);
- SETOPT(CURLOPT_SSL_VERIFYHOST, 0L);
- }
-
return;
curl_easy_setopt_failed:
@@ -207,7 +224,7 @@ void fetch_quit(void)
*/
struct fetch * fetch_start(char *url, char *referer,
- void (*callback)(fetch_msg msg, void *p, const char *data,
+ void (*callback)(fetch_msg msg, void *p, const void *data,
unsigned long size),
void *p, bool only_2xx, char *post_urlenc,
struct form_successful_control *post_multipart, bool cookies,
@@ -288,6 +305,9 @@ struct fetch * fetch_start(char *url, char *referer,
fetch->cachedata.last_modified = 0;
fetch->last_modified = 0;
fetch->file_etag = 0;
+#ifdef WITH_SSL
+ memset(fetch->cert_data, 0, sizeof(fetch->cert_data));
+#endif
fetch->queue_prev = 0;
fetch->queue_next = 0;
fetch->prev = 0;
@@ -473,10 +493,37 @@ CURLcode fetch_set_options(struct fetch *f)
}
}
+#ifdef WITH_SSL
+ if (certdb_get(f->url) != NULL) {
+ /* Disable certificate verification */
+ SETOPT(CURLOPT_SSL_VERIFYPEER, 0L);
+ SETOPT(CURLOPT_SSL_VERIFYHOST, 0L);
+ } else {
+ /* do verification */
+ SETOPT(CURLOPT_SSL_CTX_FUNCTION, fetch_sslctxfun);
+ SETOPT(CURLOPT_SSL_CTX_DATA, f);
+ }
+#endif
+
return CURLE_OK;
}
+#ifdef WITH_SSL
+/**
+ * cURL SSL setup callback
+ */
+
+CURLcode fetch_sslctxfun(CURL *curl_handle, SSL_CTX *sslctx, void *parm)
+{
+ SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_verify_callback);
+ SSL_CTX_set_cert_verify_callback(sslctx, fetch_cert_verify_callback,
+ parm);
+ return CURLE_OK;
+}
+#endif
+
+
/**
* Abort a fetch.
*/
@@ -577,6 +624,10 @@ void fetch_stop(struct fetch *f)
void fetch_free(struct fetch *f)
{
+#ifdef WITH_SSL
+ int i;
+#endif
+
if (f->curl_handle)
curl_easy_cleanup(f->curl_handle);
free(f->url);
@@ -590,6 +641,15 @@ void fetch_free(struct fetch *f)
if (f->post_multipart)
curl_formfree(f->post_multipart);
free(f->cachedata.etag);
+
+#ifdef WITH_SSL
+ for (i = 0; i < MAX_CERTS && f->cert_data[i].cert; i++) {
+ f->cert_data[i].cert->references--;
+ if (f->cert_data[i].cert->references == 0)
+ X509_free(f->cert_data[i].cert);
+ }
+#endif
+
free(f);
}
@@ -641,13 +701,20 @@ void fetch_done(CURL *curl_handle, CURLcode result)
{
bool finished = false;
bool error = false;
+#ifdef WITH_SSL
+ bool cert = false;
+#endif
bool abort;
struct fetch *f;
void *p;
- void (*callback)(fetch_msg msg, void *p, const char *data,
+ void (*callback)(fetch_msg msg, void *p, const void *data,
unsigned long size);
CURLcode code;
struct cache_data cachedata;
+#ifdef WITH_SSL
+ struct cert_info certs[MAX_CERTS];
+ memset(certs, 0, sizeof(certs));
+#endif
/* find the structure associated with this fetch */
code = curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &f);
@@ -669,6 +736,14 @@ void fetch_done(CURL *curl_handle, CURLcode result)
/* CURLE_WRITE_ERROR occurs when fetch_curl_data
* returns 0, which we use to abort intentionally */
;
+#ifdef WITH_SSL
+ else if (result == CURLE_SSL_PEER_CERTIFICATE ||
+ result == CURLE_SSL_CACERT) {
+ memcpy(certs, f->cert_data, sizeof(certs));
+ memset(f->cert_data, 0, sizeof(f->cert_data));
+ cert = true;
+ }
+#endif
else
error = true;
@@ -685,9 +760,91 @@ void fetch_done(CURL *curl_handle, CURLcode result)
if (abort)
; /* fetch was aborted: no callback */
else if (finished) {
- callback(FETCH_FINISHED, p, (const char *)&cachedata, 0);
+ callback(FETCH_FINISHED, p, &cachedata, 0);
free(cachedata.etag);
}
+#ifdef WITH_SSL
+ else if (cert) {
+ int i;
+ BIO *mem;
+ BUF_MEM *buf;
+ struct ssl_cert_info ssl_certs[MAX_CERTS];
+
+ for (i = 0; i < MAX_CERTS && certs[i].cert; i++) {
+ ssl_certs[i].version =
+ X509_get_version(certs[i].cert);
+
+ mem = BIO_new(BIO_s_mem());
+ ASN1_TIME_print(mem,
+ X509_get_notBefore(certs[i].cert));
+ BIO_get_mem_ptr(mem, &buf);
+ BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+ snprintf(ssl_certs[i].not_before,
+ min(sizeof ssl_certs[i].not_before,
+ (unsigned) buf->length + 1),
+ "%s", buf->data);
+ BUF_MEM_free(buf);
+
+ mem = BIO_new(BIO_s_mem());
+ ASN1_TIME_print(mem,
+ X509_get_notAfter(certs[i].cert));
+ BIO_get_mem_ptr(mem, &buf);
+ BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+ snprintf(ssl_certs[i].not_after,
+ min(sizeof ssl_certs[i].not_after,
+ (unsigned) buf->length + 1),
+ "%s", buf->data);
+ BUF_MEM_free(buf);
+
+ ssl_certs[i].sig_type =
+ X509_get_signature_type(certs[i].cert);
+ ssl_certs[i].serial =
+ ASN1_INTEGER_get(
+ X509_get_serialNumber(certs[i].cert));
+ mem = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(mem,
+ X509_get_issuer_name(certs[i].cert),
+ 0, XN_FLAG_SEP_CPLUS_SPC |
+ XN_FLAG_DN_REV | XN_FLAG_FN_NONE);
+ BIO_get_mem_ptr(mem, &buf);
+ BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+ snprintf(ssl_certs[i].issuer,
+ min(sizeof ssl_certs[i].issuer,
+ (unsigned) buf->length + 1),
+ "%s", buf->data);
+ BUF_MEM_free(buf);
+
+ mem = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(mem,
+ X509_get_subject_name(certs[i].cert),
+ 0, XN_FLAG_SEP_CPLUS_SPC |
+ XN_FLAG_DN_REV | XN_FLAG_FN_NONE);
+ BIO_get_mem_ptr(mem, &buf);
+ BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+ snprintf(ssl_certs[i].subject,
+ min(sizeof ssl_certs[i].subject,
+ (unsigned) buf->length + 1),
+ "%s", buf->data);
+ BUF_MEM_free(buf);
+
+ ssl_certs[i].cert_type =
+ X509_certificate_type(certs[i].cert,
+ X509_get_pubkey(certs[i].cert));
+
+ /* and clean up */
+ certs[i].cert->references--;
+ if (certs[i].cert->references == 0)
+ X509_free(certs[i].cert);
+ }
+
+ callback(FETCH_CERT_ERR, p, &ssl_certs, i);
+
+ }
+#endif
else if (error)
callback(FETCH_ERROR, p, fetch_error_buffer, 0);
}
@@ -1096,7 +1253,7 @@ bool fetch_can_fetch(const char *url)
*/
void fetch_change_callback(struct fetch *fetch,
- void (*callback)(fetch_msg msg, void *p, const char *data,
+ void (*callback)(fetch_msg msg, void *p, const void *data,
unsigned long size),
void *p)
{
@@ -1106,6 +1263,52 @@ void fetch_change_callback(struct fetch *fetch,
}
+#ifdef WITH_SSL
+/**
+ * OpenSSL Certificate verification callback
+ * Stores certificate details in fetch struct.
+ */
+
+int fetch_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
+{
+ X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
+ int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
+ int err = X509_STORE_CTX_get_error(x509_ctx);
+ struct fetch *f = X509_STORE_CTX_get_app_data(x509_ctx);
+
+ /* save the certificate by incrementing the reference count and
+ * keeping a pointer */
+ if (depth < MAX_CERTS && !f->cert_data[depth].cert) {
+ f->cert_data[depth].cert = cert;
+ f->cert_data[depth].err = err;
+ cert->references++;
+ }
+
+ return preverify_ok;
+}
+
+
+/**
+ * OpenSSL certificate chain verification callback
+ * Verifies certificate chain, setting up context for fetch_verify_callback
+ */
+
+int fetch_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm)
+{
+ int ok;
+
+ /* Store fetch struct in context for verify callback */
+ ok = X509_STORE_CTX_set_app_data(x509_ctx, parm);
+
+ /* and verify the certificate chain */
+ if (ok)
+ ok = X509_verify_cert(x509_ctx);
+
+ return ok;
+}
+#endif
+
+
/**
* testing framework
*/
diff --git a/content/fetch.h b/content/fetch.h
index 633a87131..5dd2d80cb 100644
--- a/content/fetch.h
+++ b/content/fetch.h
@@ -25,7 +25,10 @@ typedef enum {
FETCH_REDIRECT,
FETCH_NOTMODIFIED,
#ifdef WITH_AUTH
- FETCH_AUTH
+ FETCH_AUTH,
+#endif
+#ifdef WITH_SSL
+ FETCH_CERT_ERR,
#endif
} fetch_msg;
@@ -46,12 +49,25 @@ struct cache_data {
time_t last_modified; /**< Last-Modified: response header */
};
+#ifdef WITH_SSL
+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 */
+ long serial; /**< Serial number */
+ char issuer[256]; /**< Issuer details */
+ char subject[256]; /**< Subject details */
+ int cert_type; /**< Certificate type */
+};
+#endif
+
extern bool fetch_active;
extern CURLM *fetch_curl_multi;
void fetch_init(void);
struct fetch * fetch_start(char *url, char *referer,
- void (*callback)(fetch_msg msg, void *p, const char *data,
+ void (*callback)(fetch_msg msg, void *p, const void *data,
unsigned long size),
void *p, bool only_2xx, char *post_urlenc,
struct form_successful_control *post_multipart,
@@ -63,7 +79,7 @@ const char *fetch_filetype(const char *unix_path);
char *fetch_mimetype(const char *ro_path);
bool fetch_can_fetch(const char *url);
void fetch_change_callback(struct fetch *fetch,
- void (*callback)(fetch_msg msg, void *p, const char *data,
+ void (*callback)(fetch_msg msg, void *p, const void *data,
unsigned long size),
void *p);
diff --git a/content/fetchcache.c b/content/fetchcache.c
index 62fa07e3f..47f24e89c 100644
--- a/content/fetchcache.c
+++ b/content/fetchcache.c
@@ -33,13 +33,13 @@
static char error_page[1000];
static regex_t re_content_type;
-static void fetchcache_callback(fetch_msg msg, void *p, const char *data,
+static void fetchcache_callback(fetch_msg msg, void *p, const void *data,
unsigned long size);
static char *fetchcache_parse_type(const char *s, char **params[]);
static void fetchcache_error_page(struct content *c, const char *error);
static void fetchcache_cache_update(struct content *c,
const struct cache_data *data);
-static void fetchcache_notmodified(struct content *c, const char *data);
+static void fetchcache_notmodified(struct content *c, const void *data);
/**
@@ -307,7 +307,7 @@ void fetchcache_go(struct content *content, char *referer,
* This is called when the status of a fetch changes.
*/
-void fetchcache_callback(fetch_msg msg, void *p, const char *data,
+void fetchcache_callback(fetch_msg msg, void *p, const void *data,
unsigned long size)
{
bool res;
@@ -375,7 +375,7 @@ void fetchcache_callback(fetch_msg msg, void *p, const char *data,
break;
case FETCH_ERROR:
- LOG(("FETCH_ERROR, '%s'", data));
+ LOG(("FETCH_ERROR, '%s'", (const char *)data));
c->fetch = 0;
if (c->no_error_pages) {
c->status = CONTENT_STATUS_ERROR;
@@ -425,7 +425,7 @@ void fetchcache_callback(fetch_msg msg, void *p, const char *data,
#ifdef WITH_AUTH
case FETCH_AUTH:
/* data -> string containing the Realm */
- LOG(("FETCH_AUTH, '%s'", data));
+ LOG(("FETCH_AUTH, '%s'", (const char *)data));
c->fetch = 0;
msg_data.auth_realm = data;
content_broadcast(c, CONTENT_MSG_AUTH, msg_data);
@@ -434,6 +434,20 @@ void fetchcache_callback(fetch_msg msg, void *p, const char *data,
c->status = CONTENT_STATUS_ERROR;
break;
#endif
+
+#ifdef WITH_SSL
+ case FETCH_CERT_ERR:
+ c->fetch = 0;
+ /* set the status to ERROR so that the content is
+ * destroyed in content_clean() */
+ c->status = CONTENT_STATUS_ERROR;
+
+ msg_data.ssl.certs = data;
+ msg_data.ssl.num = size;
+ content_broadcast(c, CONTENT_MSG_SSL, msg_data);
+ break;
+#endif
+
default:
assert(0);
}
@@ -597,7 +611,7 @@ void fetchcache_cache_update(struct content *c,
* Not modified callback handler
*/
-void fetchcache_notmodified(struct content *c, const char *data)
+void fetchcache_notmodified(struct content *c, const void *data)
{
struct content *fb;
union content_msg_data msg_data;
diff --git a/desktop/401login.h b/desktop/401login.h
index fc94d971b..9e6030ab4 100644
--- a/desktop/401login.h
+++ b/desktop/401login.h
@@ -15,7 +15,7 @@
#ifdef WITH_AUTH
void gui_401login_open(struct browser_window *bw, struct content *c,
- char *realm);
+ const char *realm);
#endif
diff --git a/desktop/browser.c b/desktop/browser.c
index 8440bbaba..61d2cc490 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -60,7 +60,7 @@ static void browser_window_stop_throbber(struct browser_window *bw);
static void browser_window_set_status(struct browser_window *bw,
const char *text);
static void browser_window_set_pointer(gui_pointer_shape shape);
-static void download_window_callback(fetch_msg msg, void *p, const char *data,
+static void download_window_callback(fetch_msg msg, void *p, const void *data,
unsigned long size);
static void browser_window_mouse_action_html(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
@@ -429,6 +429,24 @@ void browser_window_callback(content_msg msg, struct content *c,
break;
#endif
+#ifdef WITH_SSL
+ case CONTENT_MSG_SSL:
+ gui_cert_verify(bw, c, data.ssl.certs, data.ssl.num);
+ if (c == bw->loading_content)
+ bw->loading_content = 0;
+ else if (c == bw->current_content) {
+ bw->current_content = 0;
+ bw->caret_callback = NULL;
+ bw->paste_callback = NULL;
+ bw->scrolling_box = NULL;
+ selection_init(bw->sel, NULL);
+ }
+ browser_window_stop_throbber(bw);
+ free(bw->referer);
+ bw->referer = 0;
+ break;
+#endif
+
case CONTENT_MSG_REFRESH:
schedule(data.delay * 100,
browser_window_refresh, bw);
@@ -689,7 +707,7 @@ void browser_window_destroy(struct browser_window *bw)
* Callback for fetch for download window fetches.
*/
-void download_window_callback(fetch_msg msg, void *p, const char *data,
+void download_window_callback(fetch_msg msg, void *p, const void *data,
unsigned long size)
{
struct gui_download_window *download_window = p;
@@ -713,6 +731,9 @@ void download_window_callback(fetch_msg msg, void *p, const char *data,
case FETCH_REDIRECT:
case FETCH_NOTMODIFIED:
case FETCH_AUTH:
+#ifdef WITH_SSL
+ case FETCH_CERT_ERR:
+#endif
default:
/* not possible */
assert(0);
diff --git a/desktop/gui.h b/desktop/gui.h
index dd7486e80..8016fefd7 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -38,6 +38,7 @@ typedef enum { GUI_POINTER_DEFAULT, GUI_POINTER_POINT, GUI_POINTER_CARET,
GUI_POINTER_MOVE } gui_pointer_shape;
#include <stdbool.h>
+#include "netsurf/utils/config.h"
#include "netsurf/content/content.h"
#include "netsurf/desktop/browser.h"
@@ -106,5 +107,12 @@ bool gui_search_term_highlighted(struct gui_window *g,
unsigned start_offset, unsigned end_offset,
unsigned *start_idx, unsigned *end_idx);
+#ifdef WITH_SSL
+struct ssl_cert_info;
+
+void gui_cert_verify(struct browser_window *bw, struct content *c,
+ const struct ssl_cert_info *certs, unsigned long num);
+#endif
+
#endif
diff --git a/desktop/options.c b/desktop/options.c
index 5ae615703..0aa3fc065 100644
--- a/desktop/options.c
+++ b/desktop/options.c
@@ -54,8 +54,6 @@ int option_font_size = 100;
int option_font_min_size = 70;
/** Accept-Language header. */
char *option_accept_language = 0;
-/** Enable verification of SSL certificates. */
-bool option_ssl_verify_certificates = true;
/** Preferred maximum size of memory cache / bytes. */
int option_memory_cache_size = 2 * 1024 * 1024;
/** Preferred expiry age of disc cache / days. */
@@ -96,7 +94,6 @@ struct {
{ "font_size", OPTION_INTEGER, &option_font_size },
{ "font_min_size", OPTION_INTEGER, &option_font_min_size },
{ "accept_language", OPTION_STRING, &option_accept_language },
- { "ssl_verify_certificates", OPTION_BOOL, &option_ssl_verify_certificates },
{ "memory_cache_size", OPTION_INTEGER, &option_memory_cache_size },
{ "disc_cache_age", OPTION_INTEGER, &option_disc_cache_age },
{ "block_advertisements", OPTION_BOOL, &option_block_ads },
diff --git a/desktop/options.h b/desktop/options.h
index f31be7c45..49d956a0d 100644
--- a/desktop/options.h
+++ b/desktop/options.h
@@ -38,7 +38,6 @@ extern char *option_http_proxy_auth_pass;
extern int option_font_size;
extern int option_font_min_size;
extern char *option_accept_language;
-extern bool option_ssl_verify_certificates;
extern int option_memory_cache_size;
extern int option_disc_cache_age;
extern bool option_block_ads;
diff --git a/makefile b/makefile
index dea9e1a24..b7866fa74 100644
--- a/makefile
+++ b/makefile
@@ -17,8 +17,8 @@
# "riscos", "riscos_small", "ncos", and "riscos_debug" can be compiled under
# RISC OS, or cross-compiled using GCCSDK.
-OBJECTS_COMMON = authdb.o content.o fetch.o fetchcache.o \
- url_store.o # content/
+OBJECTS_COMMON = authdb.o certdb.o content.o fetch.o \
+ fetchcache.o url_store.o # content/
OBJECTS_COMMON += css.o css_enum.o parser.o ruleset.o scanner.o # css/
OBJECTS_COMMON += box.o box_construct.o box_normalise.o form.o \
html.o html_redraw.o imagemap.o layout.o list.o \
@@ -38,13 +38,15 @@ OBJECTS_RISCOS += 401login.o artworks.o assert.o awrender.o bitmap.o \
global_history.o gui.o help.o history.o hotlist.o image.o \
menus.o message.o mouseactions.o plotters.o plugin.o print.o \
query.o save.o save_complete.o save_draw.o save_text.o \
- schedule.o search.o sprite.o textselection.o theme.o \
+ schedule.o search.o sprite.o sslcert.o textselection.o theme.o \
theme_install.o thumbnail.o treeview.o ucstables.o uri.o \
url_complete.o url_protocol.o wimp.o wimp_event.o window.o # riscos/
OBJECTS_RISCOS += con_cache.o con_fonts.o con_home.o con_image.o \
con_inter.o con_language.o con_memory.o con_theme.o # riscos/configure/
# OBJECTS_RISCOS += memdebug.o
+OBJECTS_RISCOS_SMALL = $(OBJECTS_RISCOS)
+
OBJECTS_NCOS = $(OBJECTS_RISCOS)
OBJECTS_DEBUG = $(OBJECTS_COMMON) $(OBJECTS_IMAGE)
@@ -69,6 +71,10 @@ OBJDIR_RISCOS = arm-riscos-aof
SOURCES_RISCOS=$(OBJECTS_RISCOS:.o=.c)
OBJS_RISCOS=$(OBJECTS_RISCOS:%.o=$(OBJDIR_RISCOS)/%.o)
+OBJDIR_RISCOS_SMALL = arm-riscos-aof-small
+SOURCES_RISCOS_SMALL=$(OBJECTS_RISCOS_SMALL:.o=.c)
+OBJS_RISCOS_SMALL=$(OBJECTS_RISCOS_SMALL:%.o=$(OBJDIR_RISCOS_SMALL)/%.o)
+
OBJDIR_NCOS = arm-ncos-aof
SOURCES_NCOS=$(OBJECTS_NCOS:.o=.c)
OBJS_NCOS=$(OBJECTS_NCOS:%.o=$(OBJDIR_NCOS)/%.o)
@@ -106,6 +112,7 @@ WARNFLAGS = -W -Wall -Wundef -Wpointer-arith -Wcast-qual \
CFLAGS_RISCOS = -std=c9x -D_BSD_SOURCE -Driscos -DBOOL_DEFINED -O \
$(WARNFLAGS) -I.. $(PLATFORM_CFLAGS_RISCOS) -mpoke-function-name \
# -include netsurf/utils/memdebug.h
+CFLAGS_RISCOS_SMALL = $(CFLAGS_RISCOS) -Dsmall
CFLAGS_NCOS = $(CFLAGS_RISCOS) -Dncos
CFLAGS_DEBUG = -std=c9x -D_BSD_SOURCE -Ddebug $(WARNFLAGS) -I.. \
$(PLATFORM_CFLAGS_DEBUG) -g
@@ -114,6 +121,7 @@ CFLAGS_GTK = -std=c9x -D_BSD_SOURCE -D_POSIX_C_SOURCE -Dgtk \
`pkg-config --cflags gtk+-2.0` `xml2-config --cflags`
AFLAGS_RISCOS = -I..,. $(PLATFORM_AFLAGS_RISCOS)
+AFLAGS_RISCOS_SMALL = $(AFLAGS_RISCOS) -Dsmall
AFLAGS_NCOS = $(AFLAGS_RISCOS) -Dncos
# targets
@@ -121,7 +129,7 @@ riscos: $(RUNIMAGE)
$(RUNIMAGE) : $(OBJS_RISCOS)
$(CC) -o $@ $(LDFLAGS_RISCOS) $^
riscos_small: u!RunImage,ff8
-u!RunImage,ff8 : $(OBJS_RISCOS)
+u!RunImage,ff8 : $(OBJS_RISCOS_SMALL)
$(CC) -o $@ $(LDFLAGS_SMALL) $^
ncos: $(NCRUNIMAGE)
@@ -148,6 +156,9 @@ netsurf.zip: $(RUNIMAGE)
$(OBJDIR_RISCOS)/%.o : %.c
@echo "==> $<"
@$(CC) -o $@ -c $(CFLAGS_RISCOS) $<
+$(OBJDIR_RISCOS_SMALL)/%.o : %.c
+ @echo "==> $<"
+ @$(CC) -o $@ -c $(CFLAGS_RISCOS_SMALL) $<
$(OBJDIR_NCOS)/%.o : %.c
@echo "==> $<"
@$(CC) -o $@ -c $(CFLAGS_NCOS) $<
@@ -160,10 +171,13 @@ $(OBJDIR_GTK)/%.o : %.c
# pattern rules for asm source
$(OBJDIR_RISCOS)/%.o : %.s
- @echo "== $<"
+ @echo "==> $<"
$(ASM) -o $@ -c $(AFLAGS_RISCOS) $<
+$(OBJDIR_RISCOS_SMALL)/%.o : %.s
+ @echo "==> $<"
+ $(ASM) -o $@ -c $(AFLAGS_RISCOS_SMALL) $<
$(OBJDIR_NCOS)/%.o : %.s
- @echo "== $<"
+ @echo "==> $<"
$(ASM) -o $@ -c $(AFLAGS_NCOS) $<
# special cases
@@ -184,14 +198,14 @@ utils/translit.c: transtab
depend: */*.[ch]
@echo "--> modified files $?"
@echo "--> updating dependencies"
- @-mkdir -p $(OBJDIR_RISCOS) $(OBJDIR_NCOS) $(OBJDIR_DEBUG) $(OBJDIR_GTK)
- @perl scandeps netsurf $(OBJDIR_RISCOS) $(OBJDIR_NCOS) $(OBJDIR_DEBUG) $(OBJDIR_GTK) -- $^ > depend
+ @-mkdir -p $(OBJDIR_RISCOS) $(OBJDIR_RISCOS_SMALL) $(OBJDIR_NCOS) $(OBJDIR_DEBUG) $(OBJDIR_GTK)
+ @perl scandeps netsurf $(OBJDIR_RISCOS) $(OBJDIR_RISCOS_SMALL) $(OBJDIR_NCOS) $(OBJDIR_DEBUG) $(OBJDIR_GTK) -- $^ > depend
include depend
# remove generated files
clean:
- -rm $(OBJDIR_RISCOS)/* $(OBJDIR_NCOS)/* \
+ -rm $(OBJDIR_RISCOS)/* $(OBJDIR_RISCOS_SMALL)/* $(OBJDIR_NCOS)/* \
$(OBJDIR_DEBUG)/* $(OBJDIR_GTK)/* \
css/css_enum.c css/css_enum.h \
css/parser.c css/parser.h css/scanner.c css/scanner.h
diff --git a/render/html.c b/render/html.c
index 0290dd2a6..f7369c160 100644
--- a/render/html.c
+++ b/render/html.c
@@ -852,6 +852,14 @@ void html_convert_css_callback(content_msg msg, struct content *css,
break;
#endif
+#ifdef WITH_SSL
+ case CONTENT_MSG_SSL:
+ c->data.html.stylesheet_content[i] = 0;
+ c->active--;
+ content_add_error(c, "?", 0);
+ break;
+#endif
+
default:
assert(0);
}
@@ -1127,6 +1135,14 @@ void html_object_callback(content_msg msg, struct content *object,
break;
#endif
+#ifdef WITH_SSL
+ case CONTENT_MSG_SSL:
+ c->data.html.object[i].content = 0;
+ c->active--;
+ content_add_error(c, "?", 0);
+ break;
+#endif
+
case CONTENT_MSG_REFRESH:
if (object->type == CONTENT_HTML)
/* only for HTML objects */
diff --git a/riscos/401login.c b/riscos/401login.c
index 01479a069..ecc99e4f7 100644
--- a/riscos/401login.c
+++ b/riscos/401login.c
@@ -28,8 +28,8 @@
static void ro_gui_401login_close(wimp_w w);
static bool ro_gui_401login_apply(wimp_w w);
-static void ro_gui_401login_open(struct browser_window *bw, char *host,
- char *realm, char *fetchurl);
+static void ro_gui_401login_open(struct browser_window *bw, const char *host,
+ const char *realm, const char *fetchurl);
static wimp_window *dialog_401_template;
@@ -58,7 +58,7 @@ void ro_gui_401login_init(void)
* Open the login dialog
*/
void gui_401login_open(struct browser_window *bw, struct content *c,
- char *realm)
+ const char *realm)
{
char *murl, *host;
url_func_result res;
@@ -77,8 +77,8 @@ void gui_401login_open(struct browser_window *bw, struct content *c,
* Open a 401 login window.
*/
-void ro_gui_401login_open(struct browser_window *bw, char *host, char *realm,
- char *fetchurl)
+void ro_gui_401login_open(struct browser_window *bw, const char *host,
+ const char *realm, const char *fetchurl)
{
struct session_401 *session;
wimp_w w;
diff --git a/riscos/dialog.c b/riscos/dialog.c
index e41dfb9b5..3a5225e8b 100644
--- a/riscos/dialog.c
+++ b/riscos/dialog.c
@@ -91,6 +91,11 @@ void ro_gui_dialog_init(void)
ro_gui_401login_init();
#endif
+ /* certificate verification window */
+#ifdef WITH_SSL
+ ro_gui_cert_init();
+#endif
+
/* hotlist window */
ro_gui_hotlist_initialise();
@@ -353,6 +358,15 @@ void ro_gui_dialog_close(wimp_w close)
wimp_caret caret;
os_error *error;
+ /* Check if we're a persistent window */
+ for (i = 0; i < MAX_PERSISTENT; i++) {
+ if (persistent_dialog[i].dialog == close) {
+ /* We are => invalidate record */
+ persistent_dialog[i].dialog = NULL;
+ break;
+ }
+ }
+
/* Give the caret back to the parent window. This code relies on
the fact that only tree windows and browser windows open
persistent dialogues, as the caret gets placed to no icon.
@@ -363,24 +377,18 @@ void ro_gui_dialog_close(wimp_w close)
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
} else if (caret.w == close) {
- /* Check if we are a persistent window
- */
- for (i = 0; i < MAX_PERSISTENT; i++) {
- if (persistent_dialog[i].dialog == close) {
- persistent_dialog[i].dialog = NULL;
- error = xwimp_set_caret_position(
- persistent_dialog[i].parent,
- wimp_ICON_WINDOW, -100, -100,
- 32, -1);
- /* parent may have been closed first */
- if ((error) && (error->errnum != 0x287)) {
- LOG(("xwimp_set_caret_position: "
- "0x%x: %s",
- error->errnum,
- error->errmess));
- warn_user("WimpError", error->errmess);
- }
- break;
+ /* Check if we are a persistent window */
+ if (i < MAX_PERSISTENT) {
+ error = xwimp_set_caret_position(
+ persistent_dialog[i].parent,
+ wimp_ICON_WINDOW, -100, -100,
+ 32, -1);
+ /* parent may have been closed first */
+ if ((error) && (error->errnum != 0x287)) {
+ LOG(("xwimp_set_caret_position: 0x%x: %s",
+ error->errnum,
+ error->errmess));
+ warn_user("WimpError", error->errmess);
}
}
}
diff --git a/riscos/gui.h b/riscos/gui.h
index 629316ccb..e4d70bca3 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -124,6 +124,11 @@ void ro_gui_mouse_action(struct gui_window *g);
void ro_gui_401login_init(void);
#endif
+/* in sslcert.c */
+#ifdef WITH_SSL
+void ro_gui_cert_init(void);
+#endif
+
/* in window.c */
void ro_gui_window_quit(void);
void ro_gui_window_click(struct gui_window *g, wimp_pointer *mouse);
@@ -302,7 +307,7 @@ bool ro_gui_theme_install_apply(wimp_w w);
#define ICON_SEARCH_CANCEL 4
#define ICON_SEARCH_STATUS 5
#define ICON_SEARCH_MENU 8
-#define ICON_SEARCH_SHOW_ALL 9
+#define ICON_SEARCH_SHOW_ALL 9
#define ICON_THEME_INSTALL_MESSAGE 0
#define ICON_THEME_INSTALL_INSTALL 1
diff --git a/riscos/plugin.c b/riscos/plugin.c
index b1c26df2c..115045b7c 100644
--- a/riscos/plugin.c
+++ b/riscos/plugin.c
@@ -164,7 +164,7 @@ static void plugin_stream_free(struct plugin_stream *p);
static bool plugin_start_fetch(struct plugin_stream *p, const char *url);
static void plugin_stream_callback(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data);
-static void plugin_fetch_callback(fetch_msg msg, void *p, const char *data,
+static void plugin_fetch_callback(fetch_msg msg, void *p, const void *data,
unsigned long size);
/**
@@ -1707,6 +1707,12 @@ void plugin_stream_callback(content_msg msg, struct content *c,
/* ignore this */
break;
+#ifdef WITH_SSL
+ case CONTENT_MSG_SSL:
+ plugin_destroy_stream(p, plugin_STREAM_DESTROY_ERROR);
+ break;
+#endif
+
case CONTENT_MSG_READY:
case CONTENT_MSG_DONE:
case CONTENT_MSG_REFORMAT:
@@ -1721,7 +1727,7 @@ void plugin_stream_callback(content_msg msg, struct content *c,
/**
* Callback for plugin fetch
*/
-void plugin_fetch_callback(fetch_msg msg, void *p, const char *data,
+void plugin_fetch_callback(fetch_msg msg, void *p, const void *data,
unsigned long size)
{
struct plugin_stream *s = p;
@@ -1754,6 +1760,9 @@ void plugin_fetch_callback(fetch_msg msg, void *p, const char *data,
case FETCH_REDIRECT:
case FETCH_NOTMODIFIED:
case FETCH_AUTH:
+#ifdef WITH_SSL
+ case FETCH_CERT_ERR:
+#endif
default:
/* not possible */
assert(0);
diff --git a/riscos/sslcert.c b/riscos/sslcert.c
new file mode 100644
index 000000000..74a9ffdcd
--- /dev/null
+++ b/riscos/sslcert.c
@@ -0,0 +1,182 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 John M Bell <jmb202@ecs.soton.ac.uk>
+ */
+
+/** \file
+ * SSL Certificate verification UI (implementation)
+ */
+
+#include "netsurf/utils/config.h"
+
+#ifdef WITH_SSL
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include "oslib/wimp.h"
+#include "netsurf/content/certdb.h"
+#include "netsurf/content/content.h"
+#include "netsurf/content/fetch.h"
+#include "netsurf/desktop/browser.h"
+#include "netsurf/desktop/gui.h"
+#include "netsurf/riscos/dialog.h"
+#include "netsurf/riscos/wimp_event.h"
+#include "netsurf/utils/log.h"
+#include "netsurf/utils/utils.h"
+
+#define ICON_CERT_VERSION 1
+#define ICON_CERT_VALID_FROM 2
+#define ICON_CERT_TYPE 3
+#define ICON_CERT_VALID_TO 4
+#define ICON_CERT_SERIAL 5
+#define ICON_CERT_ISSUER 6
+#define ICON_CERT_SUBJECT 7
+#define ICON_CERT_REJECT 8
+#define ICON_CERT_ACCEPT 9
+
+static wimp_window *dialog_cert_template;
+
+struct session_cert {
+ char version[16], valid_from[32], valid_to[32], type[8], serial[32],
+ issuer[256], subject[256];
+ char *url;
+ struct browser_window *bw;
+};
+
+static void ro_gui_cert_open(struct browser_window *bw, const char *url,
+ const struct ssl_cert_info *certdata);
+static void ro_gui_cert_close(wimp_w w);
+static bool ro_gui_cert_apply(wimp_w w);
+
+/**
+ * Load the cert window template
+ */
+
+void ro_gui_cert_init(void)
+{
+ dialog_cert_template = ro_gui_dialog_load_template("sslcert");
+}
+
+/**
+ * Open the certificate verification dialog
+ */
+
+void gui_cert_verify(struct browser_window *bw, struct content *c,
+ const struct ssl_cert_info *certs, unsigned long num)
+{
+ assert(bw && c && certs);
+
+ /** \todo Display entire certificate chain */
+ ro_gui_cert_open(bw, c->url, certs);
+}
+
+void ro_gui_cert_open(struct browser_window *bw, const char *url,
+ const struct ssl_cert_info *certdata)
+{
+ struct session_cert *session;
+ wimp_w w;
+
+ session = malloc(sizeof(struct session_cert));
+ if (!session) {
+ warn_user("NoMemory", 0);
+ return;
+ }
+
+ session->url = strdup(url);
+ if (!session->url) {
+ free(session);
+ warn_user("NoMemory", 0);
+ return;
+ }
+
+ session->bw = bw;
+
+ snprintf(session->version, sizeof session->version, "%ld",
+ certdata->version);
+ snprintf(session->valid_from, sizeof session->valid_from, "%s",
+ certdata->not_before);
+ snprintf(session->type, sizeof session->type, "%d",
+ certdata->cert_type);
+ snprintf(session->valid_to, sizeof session->valid_to, "%s",
+ certdata->not_after);
+ snprintf(session->serial, sizeof session->serial, "%ld",
+ certdata->serial);
+ snprintf(session->issuer, sizeof session->issuer, "%s",
+ certdata->issuer);
+ snprintf(session->subject, sizeof session->subject, "%s",
+ certdata->subject);
+
+ dialog_cert_template->icons[ICON_CERT_VERSION].data.indirected_text.text = session->version;
+ dialog_cert_template->icons[ICON_CERT_VERSION].data.indirected_text.size = strlen(session->version) + 1;
+ dialog_cert_template->icons[ICON_CERT_VALID_FROM].data.indirected_text.text = session->valid_from;
+ dialog_cert_template->icons[ICON_CERT_VALID_FROM].data.indirected_text.size = strlen(session->valid_from) + 1;
+ dialog_cert_template->icons[ICON_CERT_TYPE].data.indirected_text.text = session->type;
+ dialog_cert_template->icons[ICON_CERT_TYPE].data.indirected_text.size = strlen(session->type) + 1;
+ dialog_cert_template->icons[ICON_CERT_VALID_TO].data.indirected_text.text = session->valid_to;
+ dialog_cert_template->icons[ICON_CERT_VALID_TO].data.indirected_text.size = strlen(session->valid_to) + 1;
+ dialog_cert_template->icons[ICON_CERT_SERIAL].data.indirected_text.text = session->serial;
+ dialog_cert_template->icons[ICON_CERT_SERIAL].data.indirected_text.size = strlen(session->serial) + 1;
+ dialog_cert_template->icons[ICON_CERT_ISSUER].data.indirected_text.text = session->issuer;
+ dialog_cert_template->icons[ICON_CERT_ISSUER].data.indirected_text.size = strlen(session->issuer) + 1;
+ dialog_cert_template->icons[ICON_CERT_SUBJECT].data.indirected_text.text = session->subject;
+ dialog_cert_template->icons[ICON_CERT_SUBJECT].data.indirected_text.size = strlen(session->subject) + 1;
+
+ w = wimp_create_window(dialog_cert_template);
+
+ ro_gui_wimp_event_register_cancel(w, ICON_CERT_REJECT);
+ ro_gui_wimp_event_register_ok(w, ICON_CERT_ACCEPT, ro_gui_cert_apply);
+ ro_gui_wimp_event_register_close_window(w, ro_gui_cert_close);
+ ro_gui_wimp_event_set_user_data(w, session);
+
+ ro_gui_dialog_open_persistent(bw->window->window, w, false);
+}
+
+/**
+ * Handle closing of certificate verification dialog
+ */
+void ro_gui_cert_close(wimp_w w)
+{
+ os_error *error;
+ struct session_cert *session;
+
+ session = (struct session_cert *)ro_gui_wimp_event_get_user_data(w);
+
+ assert(session);
+
+ free(session->url);
+ free(session);
+
+ ro_gui_wimp_event_finalise(w);
+
+ error = xwimp_delete_window(w);
+ if (error)
+ LOG(("xwimp_delete_window: 0x%x: %s",
+ error->errnum, error->errmess));
+}
+
+/**
+ * Handle acceptance of certificate
+ */
+bool ro_gui_cert_apply(wimp_w w)
+{
+ struct session_cert *session;
+
+ session = (struct session_cert *)ro_gui_wimp_event_get_user_data(w);
+
+ assert(session);
+
+ if (!certdb_insert(session->url)) {
+ LOG(("certdb_insert failed"));
+ return false;
+ }
+
+ browser_window_go(session->bw, session->url, 0);
+
+ return true;
+}
+
+#endif
diff --git a/utils/config.h b/utils/config.h
index 1ca56cded..9b871ec3c 100644
--- a/utils/config.h
+++ b/utils/config.h
@@ -22,6 +22,11 @@
/* Cookies */
#define WITH_COOKIES
+/* SSL */
+#if !defined(small)
+#define WITH_SSL
+#endif
+
/* Image renderering modules */
#define WITH_JPEG
#define WITH_MNG