From 99e3756464d92b496cd5e118da46c560bf213c15 Mon Sep 17 00:00:00 2001 From: Peter Hofmann Date: Mon, 5 Jan 2015 20:05:35 +0100 Subject: [PATCH] Implement a simple certificate trust store The WebKit1 version of lariza simply ignored certificate errors. I could have turned off validation in WebKit2 as well, but I wanted to try to do it right. :-) Closes #12. --- README | 34 ++++++++++++++++++++++++++++++++++ browser.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/README b/README index 7c6b8f9..c716687 100644 --- a/README +++ b/README @@ -16,6 +16,7 @@ Features: - Keyword based searching: Opening "wi foo" will search wikipedia - Global content zoom - Cooperative instances using FIFOs + - Certificate trust store - Support for Flash and Java - Bundled web extensions: - Adblock @@ -127,6 +128,9 @@ Main windows Mod1 + 3 Repeat the last search (backward). + Mod1 + c + Reload trusted certificates. + Escape Stop loading. @@ -160,6 +164,9 @@ Main windows Mod1 + k Reset the content of the location bar to "/". + Mod1 + c + Reload trusted certificates. + Escape Reset the content of the location bar to the current URI. @@ -316,6 +323,33 @@ make. To use them, though, make sure to copy them to the directory mentioned above. +==================== +Trusted certificates +==================== + +By default, lariza trusts whatever CAs are trusted by WebKit, i.e. by +your GnuTLS installation. If you wish to trust additional certificates, +such as self-signed certificates, the first thing you should do is try +to add the appropriate CAs to your system-wide store. + +If you wish to add simple exceptions, you can grab the certificate and +store it in the directory ~/.config/lariza/certs. The filename must be +equal to the hostname: + + $ echo | openssl s_client -connect foo.de:443 | openssl x509 >foo.de + +This tells lariza to trust the given certificate when connecting to host +"foo.de". + +You can reload these certificates at runtime by pressing the appropriate +hotkey (see above). Note that removed certificates will be kept in +memory until you restart lariza. + +Note: This is NOT equal to certificate pinning. WebKit ignores +user-specified certificates if the server's certificate can be validated +by any system-wide CA. + + ==================== WebKit local storage ==================== diff --git a/browser.c b/browser.c index 1b12fe1..08c2b3e 100644 --- a/browser.c +++ b/browser.c @@ -41,6 +41,7 @@ static gboolean keywords_try_search(WebKitWebView *, const gchar *); static gboolean remote_msg(GIOChannel *, GIOCondition, gpointer); static void search(gpointer, gint); static Window tabbed_launch(void); +static void trust_user_certs(WebKitWebContext *); static void usage(void); @@ -187,6 +188,8 @@ client_new(const gchar *uri) g_signal_connect(G_OBJECT(wc), "download-started", G_CALLBACK(download_handle_start), NULL); + trust_user_certs(wc); + initial_wc_setup_done = TRUE; } @@ -593,6 +596,7 @@ key_location(GtkWidget *widget, GdkEvent *event, gpointer data) struct Client *c = (struct Client *)data; const gchar *t; gchar *f; + WebKitWebContext *wc = webkit_web_view_get_context(WEBKIT_WEB_VIEW(c->web_view)); if (event->type == GDK_KEY_PRESS) { @@ -614,6 +618,9 @@ key_location(GtkWidget *widget, GdkEvent *event, gpointer data) gtk_entry_set_text(GTK_ENTRY(c->location), "/"); gtk_editable_set_position(GTK_EDITABLE(c->location), -1); return TRUE; + case GDK_KEY_c: /* reload trusted certs (left hand) */ + trust_user_certs(wc); + return TRUE; } } else @@ -656,6 +663,7 @@ key_web_view(GtkWidget *widget, GdkEvent *event, gpointer data) gdouble dx, dy; gchar *f; gfloat z; + WebKitWebContext *wc = webkit_web_view_get_context(WEBKIT_WEB_VIEW(c->web_view)); if (event->type == GDK_KEY_PRESS) { @@ -698,6 +706,9 @@ key_web_view(GtkWidget *widget, GdkEvent *event, gpointer data) gtk_entry_set_text(GTK_ENTRY(c->location), "/"); gtk_editable_set_position(GTK_EDITABLE(c->location), -1); return TRUE; + case GDK_KEY_c: /* reload trusted certs (left hand) */ + trust_user_certs(wc); + return TRUE; } } else if (((GdkEventKey *)event)->keyval == GDK_KEY_Escape) @@ -882,6 +893,33 @@ tabbed_launch(void) return plug_into; } +void +trust_user_certs(WebKitWebContext *wc) +{ + GTlsCertificate *cert; + const gchar *basedir, *file, *absfile; + GDir *dir; + + basedir = g_build_filename(g_get_user_config_dir(), __NAME__, "certs", NULL); + dir = g_dir_open(basedir, 0, NULL); + if (dir != NULL) + { + file = g_dir_read_name(dir); + while (file != NULL) + { + absfile = g_build_filename(g_get_user_config_dir(), __NAME__, "certs", + file, NULL); + cert = g_tls_certificate_new_from_file(absfile, NULL); + if (cert == NULL) + fprintf(stderr, __NAME__": Could not load trusted cert '%s'\n", file); + else + webkit_web_context_allow_tls_certificate_for_host(wc, cert, file); + file = g_dir_read_name(dir); + } + g_dir_close(dir); + } +} + void usage(void) { -- 2.39.2