Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/1cf1ec55bc7647e737d7ec41bfe1def721269c02
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/1cf1ec55bc7647e737d7ec41bfe1def721269c02
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/1cf1ec55bc7647e737d7ec41bfe1def721269c02

The branch, master has been updated
       via  1cf1ec55bc7647e737d7ec41bfe1def721269c02 (commit)
      from  75349e79d82c43b9731b9349364f467c81fce94b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=1cf1ec55bc7647e737d7ec41bfe1def721269c02
commit 1cf1ec55bc7647e737d7ec41bfe1def721269c02
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>

    Support SSL verification through new about: handler
    
    In doing this, also propagate why the certificates were bad
    so that the page can display a reason.  We will need FatMessages
    for all these.
    
    Signed-off-by: Daniel Silverstone <[email protected]>

diff --git a/content/fetch.h b/content/fetch.h
index 7c02fb0..66be857 100644
--- a/content/fetch.h
+++ b/content/fetch.h
@@ -28,6 +28,7 @@
 #include "utils/config.h"
 #include "utils/nsurl.h"
 #include "utils/inet.h"
+#include "netsurf/ssl_certs.h"
 
 struct content;
 struct fetch;
@@ -88,23 +89,6 @@ struct fetch_multipart_data {
        bool file; /**< Item is a file */
 };
 
-/**
- * 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 */
-};
-
-/** maximum number of X509 certificates in chain for TLS connection */
-#define MAX_SSL_CERTS 10
-
 typedef void (*fetch_callback)(const fetch_msg *msg, void *p);
 
 /**
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index f5649e0..345f16c 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -555,6 +555,49 @@ fetch_curl_report_certs_upstream(struct curl_fetch_info *f)
                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;
+                       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;
+                       break;
+               case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+                       /* fallthrough */
+               case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+                       /* fallthrough */
+               case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+                       /* fallthrough */
+               case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+                       ssl_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;
+                       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;
+                       break;
+               case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+                       ssl_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;
+                       break;
+               case X509_V_ERR_CERT_REVOKED:
+                       ssl_certs[depth].err = SSL_CERT_ERR_REVOKED;
+                       break;
+               default:
+                       ssl_certs[depth].err = SSL_CERT_ERR_UNKNOWN;
+                       break;
+               }
        }
 
        msg.type = FETCH_CERTS;
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index d74b56a..a6d3ae9 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -844,23 +844,45 @@ browser_window_content_done(struct browser_window *bw)
  * Handle query responses from SSL requests
  */
 static nserror
-browser_window__handle_query_response(bool proceed, void *pw)
+browser_window__handle_ssl_query_response(bool proceed, void *pw)
 {
        struct browser_window *bw = (struct browser_window *)pw;
-       nserror res = NSERROR_OK;
 
-       if (proceed) {
-               /* We want to restart the request, with the loading
-                * context
+       /* If we're in the process of loading, stop the load */
+       if (bw->loading_content != NULL) {
+               /* We had a loading content (maybe auth page?) */
+               browser_window_stop(bw);
+               browser_window_remove_caret(bw, false);
+               browser_window_destroy_children(bw);
+       }
+
+       if (!proceed) {
+               /* We're processing a "back to safety", do a rough-and-ready
+                * nav to the old 'current' parameters, with any post data
+                * stripped away
                 */
-               res = browser_window__navigate_internal(bw, 
&bw->loading_parameters);
+               if (bw->current_parameters.post_urlenc != NULL) {
+                       free(bw->current_parameters.post_urlenc);
+                       bw->current_parameters.post_urlenc = NULL;
+               }
 
-               if (res != NSERROR_OK) {
-                       NSLOG(netsurf, WARNING, "Unable to navigate after query 
proceeds");
+               if (bw->current_parameters.post_multipart != NULL) {
+                       
fetch_multipart_data_destroy(bw->current_parameters.post_multipart);
+                       bw->current_parameters.post_multipart = NULL;
                }
+
+               bw->current_parameters.flags &= ~BW_NAVIGATE_HISTORY;
+               bw->internal_nav = false;
+               return browser_window__navigate_internal(bw, 
&bw->current_parameters);
        }
 
-       return res;
+       /* We're processing a "proceed" attempt from the form */
+       /* First, we permit the SSL */
+       urldb_set_cert_permissions(bw->loading_parameters.url, true);
+
+       /* And then we navigate to the original loading parameters */
+       bw->internal_nav = false;
+       return browser_window__navigate_internal(bw, &bw->loading_parameters);
 }
 
 /**
@@ -1074,6 +1096,70 @@ out:
 }
 
 /**
+ * Handle a certificate verification request (BAD_CERTS) during a fetch
+ */
+static nserror
+browser_window__handle_bad_certs(struct browser_window *bw,
+                                nsurl *url)
+{
+       struct browser_fetch_parameters params;
+       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;
+
+       memset(&params, 0, sizeof(params));
+
+       err = nsurl_create("about:query/ssl", &params.url);
+       if (err != NSERROR_OK) {
+               goto out;
+       }
+
+       err = fetch_multipart_data_new_kv(&params.post_multipart,
+                                         "siteurl",
+                                         nsurl_access(url));
+       if (err != NSERROR_OK) {
+               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;
+               }
+       }
+
+       err = fetch_multipart_data_new_kv(&params.post_multipart,
+                                         "reason",
+                                         reason);
+       if (err != NSERROR_OK) {
+               goto out;
+       }
+
+       /* Now we issue the fetch */
+       bw->internal_nav = true;
+       err = browser_window__navigate_internal(bw, &params);
+       if (err != NSERROR_OK) {
+               goto out;
+       }
+
+       err = guit->misc->cert_verify(url,
+                                     bw->loading_ssl_info.certs,
+                                     bw->loading_ssl_info.num,
+                                     browser_window__handle_ssl_query_response,
+                                     bw);
+
+       if (err == NSERROR_NOT_IMPLEMENTED) {
+               err = NSERROR_OK;
+       }
+out:
+       browser_window__free_fetch_parameters(&params);
+       return err;
+}
+
+/**
  * Handle errors during content fetch
  */
 static nserror
@@ -1129,14 +1215,7 @@ browser_window__handle_error(struct browser_window *bw,
                res = browser_window__handle_login(bw, message, url);
                break;
        case NSERROR_BAD_CERTS:
-               res = guit->misc->cert_verify(url,
-                                             bw->loading_ssl_info.certs,
-                                             bw->loading_ssl_info.num,
-                                             
browser_window__handle_query_response,
-                                             bw);
-               if (res != NSERROR_OK) {
-                       NSLOG(netsurf, DEBUG, "Unable to start GUI callback for 
SSL certs");
-               }
+               res = browser_window__handle_bad_certs(bw, url);
                break;
        default:
                break;
@@ -2986,6 +3065,8 @@ browser_window_navigate(struct browser_window *bw,
        if (scheme == corestring_lwc_about) {
                if (path == corestring_lwc_query_auth) {
                        is_internal = true;
+               } else if (path == corestring_lwc_query_ssl) {
+                       is_internal = true;
                }
        }
        lwc_string_unref(scheme);
@@ -3331,6 +3412,32 @@ browser_window__navigate_internal_query_auth(struct 
browser_window *bw,
 }
 
 
+/**
+ * Internal navigation handler for the SSL/privacy query page.
+ *
+ * If the parameters indicate we're processing a *response* from the handler
+ * then we deal with that, otherwise we pass it on to the about: handler
+ */
+static nserror
+browser_window__navigate_internal_query_ssl(struct browser_window *bw,
+                                           struct browser_fetch_parameters 
*params)
+{
+       bool is_proceed = false, is_back = false;
+
+       assert(params->post_multipart != NULL);
+
+       is_proceed = fetch_multipart_data_find(params->post_multipart, 
"proceed") != NULL;
+       is_back = fetch_multipart_data_find(params->post_multipart, "back") != 
NULL;
+
+       if (!(is_proceed || is_back)) {
+               /* This is a request, so pass it on */
+               return browser_window__navigate_internal_real(bw, params);
+       }
+
+       return browser_window__handle_ssl_query_response(is_proceed, bw);
+}
+
+
 nserror
 browser_window__navigate_internal(struct browser_window *bw,
                                  struct browser_fetch_parameters *params)
@@ -3356,6 +3463,10 @@ browser_window__navigate_internal(struct browser_window 
*bw,
                lwc_string_unref(path);
                return browser_window__navigate_internal_query_auth(bw, params);
        }
+       if (path == corestring_lwc_query_ssl) {
+               lwc_string_unref(path);
+               return browser_window__navigate_internal_query_ssl(bw, params);
+       }
        lwc_string_unref(path);
 
        /* Fall through to a normal about: fetch */
diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c
index af9322e..a81de16 100644
--- a/frontends/amiga/gui.c
+++ b/frontends/amiga/gui.c
@@ -6086,7 +6086,6 @@ static struct gui_misc_table amiga_misc_table = {
 
        .quit = gui_quit,
        .launch_url = gui_launch_url,
-       .cert_verify = ami_cert_verify,
 };
 
 /** Normal entry point from OS */
diff --git a/frontends/atari/gui.c b/frontends/atari/gui.c
index cce4e13..517289d 100644
--- a/frontends/atari/gui.c
+++ b/frontends/atari/gui.c
@@ -1107,7 +1107,6 @@ static struct gui_misc_table atari_misc_table = {
     .warning = atari_warn_user,
 
     .quit = gui_quit,
-    .cert_verify = gui_cert_verify,
 };
 
 /* #define WITH_DBG_LOGFILE 1 */
diff --git a/frontends/gtk/gui.c b/frontends/gtk/gui.c
index 740543b..384f3fc 100644
--- a/frontends/gtk/gui.c
+++ b/frontends/gtk/gui.c
@@ -1072,7 +1072,6 @@ static struct gui_misc_table nsgtk_misc_table = {
 
        .quit = gui_quit,
        .launch_url = gui_launch_url,
-       .cert_verify = gtk_cert_verify,
        .pdf_password = nsgtk_pdf_password,
 };
 
diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c
index ef21548..169b89b 100644
--- a/frontends/riscos/gui.c
+++ b/frontends/riscos/gui.c
@@ -2431,7 +2431,6 @@ static struct gui_misc_table riscos_misc_table = {
 
        .quit = gui_quit,
        .launch_url = gui_launch_url,
-       .cert_verify = gui_cert_verify,
 };
 
 
diff --git a/frontends/windows/main.c b/frontends/windows/main.c
index bae7815..ea9d995 100644
--- a/frontends/windows/main.c
+++ b/frontends/windows/main.c
@@ -312,8 +312,6 @@ static nserror nsw32_messages_init(char **respaths)
 static struct gui_misc_table win32_misc_table = {
        .schedule = win32_schedule,
        .warning = win32_warning,
-
-       .cert_verify = nsw32_cert_verify,
 };
 
 /**
diff --git a/include/netsurf/ssl_certs.h b/include/netsurf/ssl_certs.h
new file mode 100644
index 0000000..a73dc60
--- /dev/null
+++ b/include/netsurf/ssl_certs.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019 Daniel Silverstone <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * SSL related types and values
+ */
+
+#ifndef NETSURF_SSL_CERTS_H_
+#define NETSURF_SSL_CERTS_H_
+
+/**
+ * ssl certificate error status
+ */
+typedef enum {
+       SSL_CERT_ERR_OK,        /**< Nothing wrong with this certificate */
+       SSL_CERT_ERR_UNKNOWN,   /**< Unknown error */
+       SSL_CERT_ERR_BAD_ISSUER, /**< Bad issuer */
+       SSL_CERT_ERR_BAD_SIG,   /**< Bad signature on this certificate */
+       SSL_CERT_ERR_TOO_YOUNG, /**< This certificate is not yet valid */
+       SSL_CERT_ERR_TOO_OLD,   /**< This certificate is no longer valid */
+       SSL_CERT_ERR_SELF_SIGNED, /**< This certificate (or the chain) is self 
signed */
+       SSL_CERT_ERR_CHAIN_SELF_SIGNED, /**< This certificate chain is self 
signed */
+       SSL_CERT_ERR_REVOKED,   /**< This certificate has been revoked */
+} ssl_cert_err;
+
+/**
+ * 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 */
+};
+
+/** maximum number of X509 certificates in chain for TLS connection */
+#define MAX_SSL_CERTS 10
+
+#endif /* NETSURF_SSL_CERTS_H_ */
diff --git a/utils/corestringlist.h b/utils/corestringlist.h
index e6530c5..82fffe2 100644
--- a/utils/corestringlist.h
+++ b/utils/corestringlist.h
@@ -147,6 +147,7 @@ CORESTRING_LWC_VALUE(max_age, "max-age");
 CORESTRING_LWC_VALUE(no_cache, "no-cache");
 CORESTRING_LWC_VALUE(no_store, "no-store");
 CORESTRING_LWC_VALUE(query_auth, "query/auth");
+CORESTRING_LWC_VALUE(query_ssl, "query/ssl");
 
 /* mime types */
 CORESTRING_LWC_VALUE(multipart_form_data, "multipart/form-data");
diff --git a/utils/messages.c b/utils/messages.c
index 5beeba3..29443f9 100644
--- a/utils/messages.c
+++ b/utils/messages.c
@@ -343,6 +343,54 @@ const char *messages_get_errorcode(nserror code)
        return messages_get_ctx("Unknown", messages_hash);
 }
 
+/* exported function documented in utils/messages.h */
+const char *messages_get_sslcode(ssl_cert_err code)
+{
+       switch (code) {
+       case SSL_CERT_ERR_OK:
+               /* Nothing wrong with this certificate */
+               return messages_get_ctx("SSLCertErrOk", messages_hash);
+
+       case SSL_CERT_ERR_UNKNOWN:
+               /* Unknown error */
+               return messages_get_ctx("SSLCertErrUnknown", messages_hash);
+
+       case SSL_CERT_ERR_BAD_ISSUER:
+               /* Bad issuer */
+               return messages_get_ctx("SSLCertErrBadIssuer", messages_hash);
+
+       case SSL_CERT_ERR_BAD_SIG:
+               /* Bad signature on this certificate */
+               return messages_get_ctx("SSLCertErrBadSig", messages_hash);
+
+       case SSL_CERT_ERR_TOO_YOUNG:
+               /* This certificate is not yet valid */
+               return messages_get_ctx("SSLCertErrTooYoung", messages_hash);
+
+       case SSL_CERT_ERR_TOO_OLD:
+               /* This certificate is no longer valid */
+               return messages_get_ctx("SSLCertErrTooOld", messages_hash);
+
+       case SSL_CERT_ERR_SELF_SIGNED:
+               /* This certificate is self signed */
+               return messages_get_ctx("SSLCertErrSelfSigned", messages_hash);
+
+       case SSL_CERT_ERR_CHAIN_SELF_SIGNED:
+               /* This certificate chain is self signed */
+               return messages_get_ctx("SSLCertErrChainSelfSigned", 
messages_hash);
+
+       case SSL_CERT_ERR_REVOKED:
+               /* This certificate has been revoked */
+               return messages_get_ctx("SSLCertErrRevoked", messages_hash);
+       }
+
+       /* The switch has no default, so the compiler should tell us when we
+        * forget to add messages for new error codes.  As such, we should
+        * never get here.
+        */
+       assert(0);
+       return messages_get_ctx("Unknown", messages_hash);
+}
 
 /* exported function documented in utils/messages.h */
 void messages_destroy(void)
diff --git a/utils/messages.h b/utils/messages.h
index 4024f7e..635d6e8 100644
--- a/utils/messages.h
+++ b/utils/messages.h
@@ -36,6 +36,7 @@
 #include <stdint.h>
 
 #include "utils/errors.h"
+#include "netsurf/ssl_certs.h"
 
 /**
  * Read keys and values from messages file into the standard Messages hash.
@@ -79,6 +80,14 @@ const char *messages_get(const char *key);
 const char *messages_get_errorcode(nserror code);
 
 /**
+ * lookup of a message by SSL error code from the standard Messages hash.
+ *
+ * \param code ssl error code
+ * \return message text
+ */
+const char *messages_get_sslcode(ssl_cert_err code);
+
+/**
  * Formatted message from a key in the global message hash.
  *
  * \param  key  key of message


-----------------------------------------------------------------------

Summary of changes:
 content/fetch.h             |   18 +-----
 content/fetchers/curl.c     |   43 +++++++++++++
 desktop/browser_window.c    |  145 ++++++++++++++++++++++++++++++++++++++-----
 frontends/amiga/gui.c       |    1 -
 frontends/atari/gui.c       |    1 -
 frontends/gtk/gui.c         |    1 -
 frontends/riscos/gui.c      |    1 -
 frontends/windows/main.c    |    2 -
 include/netsurf/ssl_certs.h |   61 ++++++++++++++++++
 utils/corestringlist.h      |    1 +
 utils/messages.c            |   48 ++++++++++++++
 utils/messages.h            |    9 +++
 12 files changed, 291 insertions(+), 40 deletions(-)
 create mode 100644 include/netsurf/ssl_certs.h

diff --git a/content/fetch.h b/content/fetch.h
index 7c02fb0..66be857 100644
--- a/content/fetch.h
+++ b/content/fetch.h
@@ -28,6 +28,7 @@
 #include "utils/config.h"
 #include "utils/nsurl.h"
 #include "utils/inet.h"
+#include "netsurf/ssl_certs.h"
 
 struct content;
 struct fetch;
@@ -88,23 +89,6 @@ struct fetch_multipart_data {
        bool file; /**< Item is a file */
 };
 
-/**
- * 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 */
-};
-
-/** maximum number of X509 certificates in chain for TLS connection */
-#define MAX_SSL_CERTS 10
-
 typedef void (*fetch_callback)(const fetch_msg *msg, void *p);
 
 /**
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index f5649e0..345f16c 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -555,6 +555,49 @@ fetch_curl_report_certs_upstream(struct curl_fetch_info *f)
                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;
+                       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;
+                       break;
+               case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+                       /* fallthrough */
+               case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+                       /* fallthrough */
+               case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+                       /* fallthrough */
+               case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+                       ssl_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;
+                       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;
+                       break;
+               case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+                       ssl_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;
+                       break;
+               case X509_V_ERR_CERT_REVOKED:
+                       ssl_certs[depth].err = SSL_CERT_ERR_REVOKED;
+                       break;
+               default:
+                       ssl_certs[depth].err = SSL_CERT_ERR_UNKNOWN;
+                       break;
+               }
        }
 
        msg.type = FETCH_CERTS;
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index d74b56a..a6d3ae9 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -844,23 +844,45 @@ browser_window_content_done(struct browser_window *bw)
  * Handle query responses from SSL requests
  */
 static nserror
-browser_window__handle_query_response(bool proceed, void *pw)
+browser_window__handle_ssl_query_response(bool proceed, void *pw)
 {
        struct browser_window *bw = (struct browser_window *)pw;
-       nserror res = NSERROR_OK;
 
-       if (proceed) {
-               /* We want to restart the request, with the loading
-                * context
+       /* If we're in the process of loading, stop the load */
+       if (bw->loading_content != NULL) {
+               /* We had a loading content (maybe auth page?) */
+               browser_window_stop(bw);
+               browser_window_remove_caret(bw, false);
+               browser_window_destroy_children(bw);
+       }
+
+       if (!proceed) {
+               /* We're processing a "back to safety", do a rough-and-ready
+                * nav to the old 'current' parameters, with any post data
+                * stripped away
                 */
-               res = browser_window__navigate_internal(bw, 
&bw->loading_parameters);
+               if (bw->current_parameters.post_urlenc != NULL) {
+                       free(bw->current_parameters.post_urlenc);
+                       bw->current_parameters.post_urlenc = NULL;
+               }
 
-               if (res != NSERROR_OK) {
-                       NSLOG(netsurf, WARNING, "Unable to navigate after query 
proceeds");
+               if (bw->current_parameters.post_multipart != NULL) {
+                       
fetch_multipart_data_destroy(bw->current_parameters.post_multipart);
+                       bw->current_parameters.post_multipart = NULL;
                }
+
+               bw->current_parameters.flags &= ~BW_NAVIGATE_HISTORY;
+               bw->internal_nav = false;
+               return browser_window__navigate_internal(bw, 
&bw->current_parameters);
        }
 
-       return res;
+       /* We're processing a "proceed" attempt from the form */
+       /* First, we permit the SSL */
+       urldb_set_cert_permissions(bw->loading_parameters.url, true);
+
+       /* And then we navigate to the original loading parameters */
+       bw->internal_nav = false;
+       return browser_window__navigate_internal(bw, &bw->loading_parameters);
 }
 
 /**
@@ -1074,6 +1096,70 @@ out:
 }
 
 /**
+ * Handle a certificate verification request (BAD_CERTS) during a fetch
+ */
+static nserror
+browser_window__handle_bad_certs(struct browser_window *bw,
+                                nsurl *url)
+{
+       struct browser_fetch_parameters params;
+       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;
+
+       memset(&params, 0, sizeof(params));
+
+       err = nsurl_create("about:query/ssl", &params.url);
+       if (err != NSERROR_OK) {
+               goto out;
+       }
+
+       err = fetch_multipart_data_new_kv(&params.post_multipart,
+                                         "siteurl",
+                                         nsurl_access(url));
+       if (err != NSERROR_OK) {
+               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;
+               }
+       }
+
+       err = fetch_multipart_data_new_kv(&params.post_multipart,
+                                         "reason",
+                                         reason);
+       if (err != NSERROR_OK) {
+               goto out;
+       }
+
+       /* Now we issue the fetch */
+       bw->internal_nav = true;
+       err = browser_window__navigate_internal(bw, &params);
+       if (err != NSERROR_OK) {
+               goto out;
+       }
+
+       err = guit->misc->cert_verify(url,
+                                     bw->loading_ssl_info.certs,
+                                     bw->loading_ssl_info.num,
+                                     browser_window__handle_ssl_query_response,
+                                     bw);
+
+       if (err == NSERROR_NOT_IMPLEMENTED) {
+               err = NSERROR_OK;
+       }
+out:
+       browser_window__free_fetch_parameters(&params);
+       return err;
+}
+
+/**
  * Handle errors during content fetch
  */
 static nserror
@@ -1129,14 +1215,7 @@ browser_window__handle_error(struct browser_window *bw,
                res = browser_window__handle_login(bw, message, url);
                break;
        case NSERROR_BAD_CERTS:
-               res = guit->misc->cert_verify(url,
-                                             bw->loading_ssl_info.certs,
-                                             bw->loading_ssl_info.num,
-                                             
browser_window__handle_query_response,
-                                             bw);
-               if (res != NSERROR_OK) {
-                       NSLOG(netsurf, DEBUG, "Unable to start GUI callback for 
SSL certs");
-               }
+               res = browser_window__handle_bad_certs(bw, url);
                break;
        default:
                break;
@@ -2986,6 +3065,8 @@ browser_window_navigate(struct browser_window *bw,
        if (scheme == corestring_lwc_about) {
                if (path == corestring_lwc_query_auth) {
                        is_internal = true;
+               } else if (path == corestring_lwc_query_ssl) {
+                       is_internal = true;
                }
        }
        lwc_string_unref(scheme);
@@ -3331,6 +3412,32 @@ browser_window__navigate_internal_query_auth(struct 
browser_window *bw,
 }
 
 
+/**
+ * Internal navigation handler for the SSL/privacy query page.
+ *
+ * If the parameters indicate we're processing a *response* from the handler
+ * then we deal with that, otherwise we pass it on to the about: handler
+ */
+static nserror
+browser_window__navigate_internal_query_ssl(struct browser_window *bw,
+                                           struct browser_fetch_parameters 
*params)
+{
+       bool is_proceed = false, is_back = false;
+
+       assert(params->post_multipart != NULL);
+
+       is_proceed = fetch_multipart_data_find(params->post_multipart, 
"proceed") != NULL;
+       is_back = fetch_multipart_data_find(params->post_multipart, "back") != 
NULL;
+
+       if (!(is_proceed || is_back)) {
+               /* This is a request, so pass it on */
+               return browser_window__navigate_internal_real(bw, params);
+       }
+
+       return browser_window__handle_ssl_query_response(is_proceed, bw);
+}
+
+
 nserror
 browser_window__navigate_internal(struct browser_window *bw,
                                  struct browser_fetch_parameters *params)
@@ -3356,6 +3463,10 @@ browser_window__navigate_internal(struct browser_window 
*bw,
                lwc_string_unref(path);
                return browser_window__navigate_internal_query_auth(bw, params);
        }
+       if (path == corestring_lwc_query_ssl) {
+               lwc_string_unref(path);
+               return browser_window__navigate_internal_query_ssl(bw, params);
+       }
        lwc_string_unref(path);
 
        /* Fall through to a normal about: fetch */
diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c
index af9322e..a81de16 100644
--- a/frontends/amiga/gui.c
+++ b/frontends/amiga/gui.c
@@ -6086,7 +6086,6 @@ static struct gui_misc_table amiga_misc_table = {
 
        .quit = gui_quit,
        .launch_url = gui_launch_url,
-       .cert_verify = ami_cert_verify,
 };
 
 /** Normal entry point from OS */
diff --git a/frontends/atari/gui.c b/frontends/atari/gui.c
index cce4e13..517289d 100644
--- a/frontends/atari/gui.c
+++ b/frontends/atari/gui.c
@@ -1107,7 +1107,6 @@ static struct gui_misc_table atari_misc_table = {
     .warning = atari_warn_user,
 
     .quit = gui_quit,
-    .cert_verify = gui_cert_verify,
 };
 
 /* #define WITH_DBG_LOGFILE 1 */
diff --git a/frontends/gtk/gui.c b/frontends/gtk/gui.c
index 740543b..384f3fc 100644
--- a/frontends/gtk/gui.c
+++ b/frontends/gtk/gui.c
@@ -1072,7 +1072,6 @@ static struct gui_misc_table nsgtk_misc_table = {
 
        .quit = gui_quit,
        .launch_url = gui_launch_url,
-       .cert_verify = gtk_cert_verify,
        .pdf_password = nsgtk_pdf_password,
 };
 
diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c
index ef21548..169b89b 100644
--- a/frontends/riscos/gui.c
+++ b/frontends/riscos/gui.c
@@ -2431,7 +2431,6 @@ static struct gui_misc_table riscos_misc_table = {
 
        .quit = gui_quit,
        .launch_url = gui_launch_url,
-       .cert_verify = gui_cert_verify,
 };
 
 
diff --git a/frontends/windows/main.c b/frontends/windows/main.c
index bae7815..ea9d995 100644
--- a/frontends/windows/main.c
+++ b/frontends/windows/main.c
@@ -312,8 +312,6 @@ static nserror nsw32_messages_init(char **respaths)
 static struct gui_misc_table win32_misc_table = {
        .schedule = win32_schedule,
        .warning = win32_warning,
-
-       .cert_verify = nsw32_cert_verify,
 };
 
 /**
diff --git a/include/netsurf/ssl_certs.h b/include/netsurf/ssl_certs.h
new file mode 100644
index 0000000..a73dc60
--- /dev/null
+++ b/include/netsurf/ssl_certs.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019 Daniel Silverstone <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * SSL related types and values
+ */
+
+#ifndef NETSURF_SSL_CERTS_H_
+#define NETSURF_SSL_CERTS_H_
+
+/**
+ * ssl certificate error status
+ */
+typedef enum {
+       SSL_CERT_ERR_OK,        /**< Nothing wrong with this certificate */
+       SSL_CERT_ERR_UNKNOWN,   /**< Unknown error */
+       SSL_CERT_ERR_BAD_ISSUER, /**< Bad issuer */
+       SSL_CERT_ERR_BAD_SIG,   /**< Bad signature on this certificate */
+       SSL_CERT_ERR_TOO_YOUNG, /**< This certificate is not yet valid */
+       SSL_CERT_ERR_TOO_OLD,   /**< This certificate is no longer valid */
+       SSL_CERT_ERR_SELF_SIGNED, /**< This certificate (or the chain) is self 
signed */
+       SSL_CERT_ERR_CHAIN_SELF_SIGNED, /**< This certificate chain is self 
signed */
+       SSL_CERT_ERR_REVOKED,   /**< This certificate has been revoked */
+} ssl_cert_err;
+
+/**
+ * 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 */
+};
+
+/** maximum number of X509 certificates in chain for TLS connection */
+#define MAX_SSL_CERTS 10
+
+#endif /* NETSURF_SSL_CERTS_H_ */
diff --git a/utils/corestringlist.h b/utils/corestringlist.h
index e6530c5..82fffe2 100644
--- a/utils/corestringlist.h
+++ b/utils/corestringlist.h
@@ -147,6 +147,7 @@ CORESTRING_LWC_VALUE(max_age, "max-age");
 CORESTRING_LWC_VALUE(no_cache, "no-cache");
 CORESTRING_LWC_VALUE(no_store, "no-store");
 CORESTRING_LWC_VALUE(query_auth, "query/auth");
+CORESTRING_LWC_VALUE(query_ssl, "query/ssl");
 
 /* mime types */
 CORESTRING_LWC_VALUE(multipart_form_data, "multipart/form-data");
diff --git a/utils/messages.c b/utils/messages.c
index 5beeba3..29443f9 100644
--- a/utils/messages.c
+++ b/utils/messages.c
@@ -343,6 +343,54 @@ const char *messages_get_errorcode(nserror code)
        return messages_get_ctx("Unknown", messages_hash);
 }
 
+/* exported function documented in utils/messages.h */
+const char *messages_get_sslcode(ssl_cert_err code)
+{
+       switch (code) {
+       case SSL_CERT_ERR_OK:
+               /* Nothing wrong with this certificate */
+               return messages_get_ctx("SSLCertErrOk", messages_hash);
+
+       case SSL_CERT_ERR_UNKNOWN:
+               /* Unknown error */
+               return messages_get_ctx("SSLCertErrUnknown", messages_hash);
+
+       case SSL_CERT_ERR_BAD_ISSUER:
+               /* Bad issuer */
+               return messages_get_ctx("SSLCertErrBadIssuer", messages_hash);
+
+       case SSL_CERT_ERR_BAD_SIG:
+               /* Bad signature on this certificate */
+               return messages_get_ctx("SSLCertErrBadSig", messages_hash);
+
+       case SSL_CERT_ERR_TOO_YOUNG:
+               /* This certificate is not yet valid */
+               return messages_get_ctx("SSLCertErrTooYoung", messages_hash);
+
+       case SSL_CERT_ERR_TOO_OLD:
+               /* This certificate is no longer valid */
+               return messages_get_ctx("SSLCertErrTooOld", messages_hash);
+
+       case SSL_CERT_ERR_SELF_SIGNED:
+               /* This certificate is self signed */
+               return messages_get_ctx("SSLCertErrSelfSigned", messages_hash);
+
+       case SSL_CERT_ERR_CHAIN_SELF_SIGNED:
+               /* This certificate chain is self signed */
+               return messages_get_ctx("SSLCertErrChainSelfSigned", 
messages_hash);
+
+       case SSL_CERT_ERR_REVOKED:
+               /* This certificate has been revoked */
+               return messages_get_ctx("SSLCertErrRevoked", messages_hash);
+       }
+
+       /* The switch has no default, so the compiler should tell us when we
+        * forget to add messages for new error codes.  As such, we should
+        * never get here.
+        */
+       assert(0);
+       return messages_get_ctx("Unknown", messages_hash);
+}
 
 /* exported function documented in utils/messages.h */
 void messages_destroy(void)
diff --git a/utils/messages.h b/utils/messages.h
index 4024f7e..635d6e8 100644
--- a/utils/messages.h
+++ b/utils/messages.h
@@ -36,6 +36,7 @@
 #include <stdint.h>
 
 #include "utils/errors.h"
+#include "netsurf/ssl_certs.h"
 
 /**
  * Read keys and values from messages file into the standard Messages hash.
@@ -79,6 +80,14 @@ const char *messages_get(const char *key);
 const char *messages_get_errorcode(nserror code);
 
 /**
+ * lookup of a message by SSL error code from the standard Messages hash.
+ *
+ * \param code ssl error code
+ * \return message text
+ */
+const char *messages_get_sslcode(ssl_cert_err code);
+
+/**
  * Formatted message from a key in the global message hash.
  *
  * \param  key  key of message


-- 
NetSurf Browser

_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org

Reply via email to