X-Git-Url: https://git.danieliu.xyz/?p=surf.git;a=blobdiff_plain;f=surf.c;h=40f514f16f3f24e890be1104bed25947fc452b13;hp=4ead12296b286553bf298c6650366ef7e8af31eb;hb=1dc3cd513a75570cc2fc33a86d4af565ecf9255e;hpb=eb32dd6eca5b6224bb5fb28cadef5bd035581ef3 diff --git a/surf.c b/surf.c index 4ead122..40f514f 100644 --- a/surf.c +++ b/surf.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,7 @@ enum { typedef enum { AcceleratedCanvas, CaretBrowsing, + Certificate, CookiePolicies, DiskCache, DNSPrefetch, @@ -162,6 +164,8 @@ static WebKitCookieAcceptPolicy cookiepolicy_get(void); static char cookiepolicy_set(const WebKitCookieAcceptPolicy p); static void seturiparameters(Client *c, const char *uri); static void setparameter(Client *c, int refresh, ParamName p, const Arg *a); +static const char *getcert(const char *uri); +static void setcert(Client *c, const char *file); static const char *getstyle(const char *uri); static void setstyle(Client *c, const char *file); static void runscript(Client *c); @@ -184,6 +188,9 @@ static GdkFilterReturn processx(GdkXEvent *xevent, GdkEvent *event, static gboolean winevent(GtkWidget *w, GdkEvent *e, Client *c); static void showview(WebKitWebView *v, Client *c); static GtkWidget *createwindow(Client *c); +static gboolean loadfailedtls(WebKitWebView *v, gchar *uri, + GTlsCertificate *cert, + GTlsCertificateFlags err, Client *c); static void loadchanged(WebKitWebView *v, WebKitLoadEvent e, Client *c); static void progresschanged(WebKitWebView *v, GParamSpec *ps, Client *c); static void titlechanged(WebKitWebView *view, GParamSpec *ps, Client *c); @@ -291,21 +298,33 @@ setup(void) cookiefile = buildfile(cookiefile); scriptfile = buildfile(scriptfile); cachedir = buildpath(cachedir); + certdir = buildpath(certdir); gdkkb = gdk_seat_get_keyboard(gdk_display_get_default_seat(gdpy)); + for (i = 0; i < LENGTH(certs); ++i) { + if (!regcomp(&(certs[i].re), certs[i].regex, REG_EXTENDED)) { + certs[i].file = g_strconcat(certdir, "/", certs[i].file, + NULL); + } else { + fprintf(stderr, "Could not compile regex: %s\n", + certs[i].regex); + certs[i].regex = NULL; + } + } + if (!stylefile) { styledir = buildpath(styledir); for (i = 0; i < LENGTH(styles); ++i) { - if (regcomp(&(styles[i].re), styles[i].regex, + if (!regcomp(&(styles[i].re), styles[i].regex, REG_EXTENDED)) { - fprintf(stderr, - "Could not compile regex: %s\n", + styles[i].file = g_strconcat(styledir, "/", + styles[i].file, NULL); + } else { + fprintf(stderr, "Could not compile regex: %s\n", styles[i].regex); styles[i].regex = NULL; } - styles[i].file = g_strconcat(styledir, "/", - styles[i].file, NULL); } g_free(styledir); } else { @@ -323,8 +342,7 @@ setup(void) uriparams[i].config[j] = defconfig[j]; } } else { - fprintf(stderr, - "Could not compile regex: %s\n", + fprintf(stderr, "Could not compile regex: %s\n", uriparams[i].uri); uriparams[i].uri = NULL; } @@ -642,6 +660,10 @@ setparameter(Client *c, int refresh, ParamName p, const Arg *a) webkit_settings_set_enable_caret_browsing(s, a->b); refresh = 0; break; + case Certificate: + if (a->b) + setcert(c, geturi(c)); + return; /* do not update */ case CookiePolicies: webkit_cookie_manager_set_accept_policy( webkit_web_context_get_cookie_manager( @@ -737,6 +759,45 @@ setparameter(Client *c, int refresh, ParamName p, const Arg *a) reload(c, a); } +const char * +getcert(const char *uri) +{ + int i; + + for (i = 0; i < LENGTH(certs); ++i) { + if (certs[i].regex && + !regexec(&(certs[i].re), uri, 0, NULL, 0)) + return certs[i].file; + } + + return NULL; +} + +void +setcert(Client *c, const char *uri) +{ + const char *file = getcert(uri); + char *host; + GTlsCertificate *cert; + + if (!file) + return; + + if (!(cert = g_tls_certificate_new_from_file(file, NULL))) { + fprintf(stderr, "Could not read certificate file: %s\n", file); + return; + } + + uri = strstr(uri, "://") + sizeof("://") - 1; + host = strndup(uri, strstr(uri, "/") - uri); + + webkit_web_context_allow_tls_certificate_for_host( + webkit_web_view_get_context(c->view), cert, host); + g_object_unref(cert); + + free(host); +} + const char * getstyle(const char *uri) { @@ -1013,6 +1074,8 @@ newview(Client *c, WebKitWebView *rv) G_CALLBACK(decidepolicy), c); g_signal_connect(G_OBJECT(v), "insecure-content-detected", G_CALLBACK(insecurecontent), c); + g_signal_connect(G_OBJECT(v), "load-failed-with-tls-errors", + G_CALLBACK(loadfailedtls), c); g_signal_connect(G_OBJECT(v), "load-changed", G_CALLBACK(loadchanged), c); g_signal_connect(G_OBJECT(v), "mouse-target-changed", @@ -1224,6 +1287,51 @@ createwindow(Client *c) return w; } +gboolean +loadfailedtls(WebKitWebView *v, gchar *uri, GTlsCertificate *cert, + GTlsCertificateFlags err, Client *c) +{ + GString *errmsg = g_string_new(NULL); + gchar *html, *pem; + + c->tlserr = err; + + if (err & G_TLS_CERTIFICATE_UNKNOWN_CA) + g_string_append(errmsg, + "The signing certificate authority is not known.
"); + if (err & G_TLS_CERTIFICATE_BAD_IDENTITY) + g_string_append(errmsg, + "The certificate does not match the expected identity " + "of the site that it was retrieved from.
"); + if (err & G_TLS_CERTIFICATE_NOT_ACTIVATED) + g_string_append(errmsg, + "The certificate's activation time " + "is still in the future.
"); + if (err & G_TLS_CERTIFICATE_EXPIRED) + g_string_append(errmsg, "The certificate has expired.
"); + if (err & G_TLS_CERTIFICATE_REVOKED) + g_string_append(errmsg, + "The certificate has been revoked according to " + "the GTlsConnection's certificate revocation list.
"); + if (err & G_TLS_CERTIFICATE_INSECURE) + g_string_append(errmsg, + "The certificate's algorithm is considered insecure.
"); + if (err & G_TLS_CERTIFICATE_GENERIC_ERROR) + g_string_append(errmsg, + "Some error occurred validating the certificate.
"); + + g_object_get(cert, "certificate-pem", &pem, NULL); + html = g_strdup_printf("

Could not validate TLS for “%s”
%s

" + "

%s

", uri, errmsg->str, pem); + g_free(pem); + g_string_free(errmsg, TRUE); + + webkit_web_view_load_alternate_html(c->view, html, uri, NULL); + g_free(html); + + return TRUE; +} + void loadchanged(WebKitWebView *v, WebKitLoadEvent e, Client *c) {