Bug 1323644 - Isolate the HSTS and HPKP storage by first party domain (ForgetAboutSite) r=mossop,keeler draft
authorJonathan Hao <jhao@mozilla.com>
Tue, 24 Jan 2017 12:02:28 +0800
changeset 465947 1fb59daa3d9197412d08979c8c44d034b49ae527
parent 465946 1886e9abf6a490b1ad4f688c28933d69822ee96b
child 543295 fd9d4e24ebca6d5b6513116b0e1ef793be3ec209
push id42762
push userbmo:jhao@mozilla.com
push dateWed, 25 Jan 2017 03:22:43 +0000
reviewersmossop, keeler
bugs1323644
milestone53.0a1
Bug 1323644 - Isolate the HSTS and HPKP storage by first party domain (ForgetAboutSite) r=mossop,keeler
security/manager/ssl/tests/unit/test_forget_about_site_security_headers.js
toolkit/forgetaboutsite/ForgetAboutSite.jsm
--- a/security/manager/ssl/tests/unit/test_forget_about_site_security_headers.js
+++ b/security/manager/ssl/tests/unit/test_forget_about_site_security_headers.js
@@ -105,8 +105,61 @@ add_task(function* () {
   Assert.ok(!sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HPKP,
                               "a.pinning2.example.com", 0),
             "a.pinning2.example.com should not be HPKP now (subdomain case)");
 
   Assert.ok(sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
                              "example.org", 0),
             "example.org should still be HSTS");
 });
+
+// Test the case of processing HSTS and HPKP headers for a.pinning2.example.com
+// with multiple originAttributes, using "Forget About Site" on example.com, and
+// then checking that the platform doesn't consider the subdomain to be HSTS or
+// HPKP for any originAttributes any longer. Also test that unrelated sites
+// don't also get removed.
+add_task(function* () {
+  let originAttributesList = [
+    {},
+    { userContextId: 1},
+    { firstPartyDomain: "foo.com" },
+    { userContextId: 1, firstPartyDomain: "foo.com" },
+  ];
+  for (let originAttributes of originAttributesList) {
+    sss.processHeader(Ci.nsISiteSecurityService.HEADER_HSTS, uri, GOOD_MAX_AGE,
+                      sslStatus, 0, originAttributes);
+    sss.processHeader(Ci.nsISiteSecurityService.HEADER_HPKP, uri,
+                      GOOD_MAX_AGE + VALID_PIN + BACKUP_PIN, sslStatus, 0,
+                      originAttributes);
+
+    Assert.ok(sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
+                               "a.pinning2.example.com", 0, originAttributes),
+              "a.pinning2.example.com should be HSTS (originAttributes case)");
+    Assert.ok(sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HPKP,
+                               "a.pinning2.example.com", 0, originAttributes),
+              "a.pinning2.example.com should be HPKP (originAttributes case)");
+
+    // Add an unrelated site to HSTS.  Not HPKP because we have no valid keys.
+    let unrelatedURI = Services.io.newURI("https://example.org");
+    sss.processHeader(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI,
+                      GOOD_MAX_AGE, sslStatus, 0, originAttributes);
+    Assert.ok(sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
+                               "example.org", 0, originAttributes),
+              "example.org should be HSTS (originAttributes case)");
+  }
+
+  yield ForgetAboutSite.removeDataFromDomain("example.com");
+
+  for (let originAttributes of originAttributesList) {
+    Assert.ok(!sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
+                                "a.pinning2.example.com", 0, originAttributes),
+              "a.pinning2.example.com should not be HSTS now " +
+              "(originAttributes case)");
+    Assert.ok(!sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HPKP,
+                                "a.pinning2.example.com", 0, originAttributes),
+              "a.pinning2.example.com should not be HPKP now " +
+              "(originAttributes case)");
+
+    Assert.ok(sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
+                               "example.org", 0, originAttributes),
+              "example.org should still be HSTS (originAttributes case)");
+  }
+});
--- a/toolkit/forgetaboutsite/ForgetAboutSite.jsm
+++ b/toolkit/forgetaboutsite/ForgetAboutSite.jsm
@@ -197,29 +197,27 @@ this.ForgetAboutSite = {
     }));
 
     // HSTS and HPKP
     try {
       let sss = Cc["@mozilla.org/ssservice;1"].
                 getService(Ci.nsISiteSecurityService);
       for (let type of [Ci.nsISiteSecurityService.HEADER_HSTS,
                         Ci.nsISiteSecurityService.HEADER_HPKP]) {
-        sss.removeState(type, httpsURI, 0);
-
         // Also remove HSTS/HPKP information for subdomains by enumerating the
         // information in the site security service.
         let enumerator = sss.enumerate(type);
         while (enumerator.hasMoreElements()) {
           let entry = enumerator.getNext();
           let hostname = entry.QueryInterface(Ci.nsISiteSecurityState).hostname;
           // If the hostname is aDomain's subdomain, we remove its state.
-          if (hostname.endsWith("." + aDomain)) {
+          if (hostname == aDomain || hostname.endsWith("." + aDomain)) {
             // This uri is used as a key to remove the state.
             let uri = caUtils.makeURI("https://" + hostname);
-            sss.removeState(type, uri, 0);
+            sss.removeState(type, uri, 0, entry.originAttributes);
           }
         }
       }
     } catch (e) {
       Cu.reportError("Exception thrown while clearing HSTS/HPKP: " +
                      e.toString());
     }