]> spindle.queued.net Git - midori/commitdiff
Cache HSTS directives and handle sub domains
authorChristian Dywan <christian@twotoasts.de>
Sun, 2 Sep 2012 19:09:18 +0000 (21:09 +0200)
committerChristian Dywan <christian@twotoasts.de>
Sun, 2 Sep 2012 19:14:49 +0000 (21:14 +0200)
katze/midori-hsts.vala

index 32e8216bff47e4c8c8d8d145dc97b4a6fd6f4f43..989e95eb047367441b75516d6cae7c210a3e2e78 100644 (file)
@@ -35,17 +35,37 @@ namespace Midori {
             }
         }
 
-        public string? filename { get; set; default = null; }
+        File file;
         HashTable<string, Directive> whitelist;
         bool debug = false;
 
-        public HSTS (owned string new_filename) {
-            filename = new_filename;
+        public HSTS (owned string filename) {
             whitelist = new HashTable<string, Directive> (str_hash, str_equal);
+            read_cache (File.new_for_path (Paths.get_config_filename (null, "hsts")));
+            file = File.new_for_path (filename);
+            read_cache (file);
             if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "hsts") == 0)
                 debug = true;
         }
 
+        async void read_cache (File file) {
+            try {
+                var stream = new DataInputStream (yield file.read_async ());
+                do {
+                    string? line = yield stream.read_line_async ();
+                    if (line == null)
+                        break;
+                    string[] parts = line.split (" ", 2);
+                    if (parts[0] == null || parts[1] == null)
+                        break;
+                    var directive = new Directive.from_header (parts[1]);
+                    if (directive.is_valid ())
+                        append_to_whitelist (parts[0], directive);
+                } while (true);
+            }
+            catch (Error error) { }
+        }
+
         /* No sub-features */
         public bool add_feature (Type type) { return false; }
         public bool remove_feature (Type type) { return false; }
@@ -59,18 +79,44 @@ namespace Midori {
         public void request_queued (Soup.Session session, Soup.Message message) { }
         public void request_unqueued (Soup.Session session, Soup.Message msg) { }
 
+        bool should_secure_host (string host) {
+            Directive? directive = whitelist.lookup (host);
+            if (directive == null)
+                directive = whitelist.lookup ("*." + host);
+            return directive != null && directive.is_valid ();
+        }
+
         void queued (Soup.Session session, Soup.Message message) {
-            Directive? directive = whitelist.lookup (message.uri.host);
-            if (directive != null && directive.is_valid ()) {
+            if (should_secure_host (message.uri.host)) {
                 message.uri.set_scheme ("https");
                 session.requeue_message (message);
                 if (debug)
-                    stdout.printf ("HTPS: Enforce %s\n", message.uri.to_string (false));
+                    stdout.printf ("HSTS: Enforce %s\n", message.uri.host);
             }
             else if (message.uri.scheme == "http")
                 message.finished.connect (strict_transport_security_handled);
         }
 
+        void append_to_whitelist (string host, Directive directive) {
+            whitelist.insert (host, directive);
+            if (directive.sub_domains)
+                whitelist.insert ("*." + host, directive);
+        }
+
+        async void append_to_cache (string host, string header) {
+            if (Midori.Paths.is_readonly ())
+                return;
+
+            try {
+                var stream = file.append_to/* FIXME _async*/ (FileCreateFlags.NONE);
+                yield stream.write_async ((host + " " + header + "\n").data);
+                yield stream.flush_async ();
+            }
+            catch (Error error) {
+                critical ("Failed to update %s: %s", file.get_path (), error.message);
+            }
+        }
+
         void strict_transport_security_handled (Soup.Message message) {
             if (message == null || message.uri == null)
                 return;
@@ -80,11 +126,13 @@ namespace Midori {
                 return;
 
             var directive = new Directive.from_header (hsts);
-            if (directive.is_valid ())
-                whitelist.insert (message.uri.host, directive);
+            if (directive.is_valid ()) {
+                append_to_whitelist (message.uri.host, directive);
+                append_to_cache (message.uri.host, hsts);
+            }
             if (debug)
-                stdout.printf ("HTPS: '%s' sets '%s' valid? %s\n",
-                    message.uri.to_string (false), hsts, directive.is_valid ().to_string ());
+                stdout.printf ("HSTS: '%s' sets '%s' valid? %s\n",
+                    message.uri.host, hsts, directive.is_valid ().to_string ());
         }
 
     }