]> git.armaanb.net Git - chorizo.git/commitdiff
Implement a simple certificate trust store
authorPeter Hofmann <scm@uninformativ.de>
Mon, 5 Jan 2015 19:05:35 +0000 (20:05 +0100)
committerPeter Hofmann <scm@uninformativ.de>
Mon, 5 Jan 2015 19:31:10 +0000 (20:31 +0100)
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
browser.c

diff --git a/README b/README
index 7c6b8f99c05aceabaf9f46e6a493cc0de3f1638c..c71668742b319c91a8c8d056fa9c75f6844031b9 100644 (file)
--- 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
 ====================
index 1b12fe184134a2b1b023a4d4a8e4e883b65a43a2..08c2b3e2d8fa569f0c2e7028bdbbd5699b2f2559 100644 (file)
--- 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)
 {