Bug 1323644 - Isolate the HSTS and HPKP storage by first party domain (ForgetAboutSite) r=mossop,keeler draft
authorJonathan Hao <jhao@mozilla.com>
Tue, 14 Feb 2017 10:29:54 +0800
changeset 486884 6e03f8eb900e38364dc577af772ac7471c331e37
parent 486883 7bd9d2f608e9f9c362ea1e842e98253d817034ca
child 546340 8fb2537fb0800f8a1cba6cbe6312922387f6a756
push id46085
push userbmo:jhao@mozilla.com
push dateMon, 20 Feb 2017 05:50:46 +0000
reviewersmossop, keeler
bugs1323644
milestone54.0a1
Bug 1323644 - Isolate the HSTS and HPKP storage by first party domain (ForgetAboutSite) r=mossop,keeler MozReview-Commit-ID: LjYb5coVxJl
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
@@ -96,8 +96,63 @@ add_task(function* () {
             "a.pinning2.example.com should not be HSTS now (subdomain case)");
   Assert.ok(!sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0),
             "a.pinning2.example.com should not be HPKP now (subdomain case)");
 
   Assert.ok(sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS,
                              unrelatedURI, 0),
             "example.org should still be HSTS");
 });
+
+// Test the case of processing HSTS and HPKP headers for a.pinning2.example.com
+// with various 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" },
+  ];
+
+  let unrelatedURI = Services.io.newURI("https://example.org");
+
+  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.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri,
+                               0, originAttributes),
+              "a.pinning2.example.com should be HSTS (originAttributes case)");
+    Assert.ok(sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri,
+                               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.
+    sss.processHeader(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI,
+                      GOOD_MAX_AGE, sslStatus, 0, originAttributes);
+    Assert.ok(sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS,
+                              unrelatedURI, 0, originAttributes),
+              "example.org should be HSTS (originAttributes case)");
+  }
+
+  yield ForgetAboutSite.removeDataFromDomain("example.com");
+
+  for (let originAttributes of originAttributesList) {
+    Assert.ok(!sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri,
+                                0, originAttributes),
+              "a.pinning2.example.com should not be HSTS now " +
+              "(originAttributes case)");
+    Assert.ok(!sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri,
+                                0, originAttributes),
+              "a.pinning2.example.com should not be HPKP now " +
+              "(originAttributes case)");
+
+    Assert.ok(sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS,
+                              unrelatedURI, 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());
     }