Bug 1290529 - Clear HSTS and HPKP for subdomains in ForgetAboutSite. r=MattN,keeler
--- 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
@@ -66,35 +66,47 @@ add_task(function* () {
Assert.ok(!sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
"a.pinning2.example.com", 0),
"a.pinning2.example.com should not be HSTS now");
Assert.ok(!sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HPKP,
"a.pinning2.example.com", 0),
"a.pinning2.example.com should not be HPKP now");
});
-// TODO (bug 1290529): the platform does not support this yet.
// Test the case of processing HSTS and HPKP headers for a.pinning2.example.com,
// using "Forget About Site" on example.com, and then checking that the platform
-// doesn't consider the subdomain to be HSTS or HPKP any longer.
+// doesn't consider the subdomain to be HSTS or HPKP any longer. Also test that
+// unrelated sites don't also get removed.
add_task(function* () {
sss.processHeader(Ci.nsISiteSecurityService.HEADER_HSTS, uri, GOOD_MAX_AGE,
sslStatus, 0);
sss.processHeader(Ci.nsISiteSecurityService.HEADER_HPKP, uri,
GOOD_MAX_AGE + VALID_PIN + BACKUP_PIN, sslStatus, 0);
Assert.ok(sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
"a.pinning2.example.com", 0),
"a.pinning2.example.com should be HSTS (subdomain case)");
Assert.ok(sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HPKP,
"a.pinning2.example.com", 0),
"a.pinning2.example.com should be HPKP (subdomain case)");
+ // Add an unrelated site to HSTS. Not HPKP because we have no valid keys for
+ // example.org.
+ let unrelatedURI = Services.io.newURI("https://example.org");
+ sss.processHeader(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI,
+ GOOD_MAX_AGE, sslStatus, 0);
+ Assert.ok(sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
+ "example.org", 0),
+ "example.org should be HSTS");
+
yield ForgetAboutSite.removeDataFromDomain("example.com");
- // TODO (bug 1290529):
- // Assert.ok(!sss.isSecureHost(Ci.nsISiteSecurityService.HEADER_HSTS,
- // "a.pinning2.example.com", 0),
- // "a.pinning2.example.com should not be HSTS now (subdomain case)");
- // 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,
+ "a.pinning2.example.com", 0),
+ "a.pinning2.example.com should not be HSTS now (subdomain case)");
+ 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");
});
--- a/toolkit/forgetaboutsite/ForgetAboutSite.jsm
+++ b/toolkit/forgetaboutsite/ForgetAboutSite.jsm
@@ -192,24 +192,37 @@ this.ForgetAboutSite = {
(Components.isSuccessCode(status) ? resolve : reject)(status);
});
}).catch(e => {
Cu.reportError("Exception thrown while clearing Push notifications: " +
e.toString());
}));
// HSTS and HPKP
- // TODO (bug 1290529): also remove HSTS/HPKP information for subdomains.
- // Since we can't enumerate the information in the site security service
- // (bug 1115712), we can't implement this right now.
try {
let sss = Cc["@mozilla.org/ssservice;1"].
getService(Ci.nsISiteSecurityService);
- sss.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, httpsURI, 0);
- sss.removeState(Ci.nsISiteSecurityService.HEADER_HPKP, httpsURI, 0);
+ 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)) {
+ // This uri is used as a key to remove the state.
+ let uri = caUtils.makeURI("https://" + hostname);
+ sss.removeState(type, uri, 0);
+ }
+ }
+ }
} catch (e) {
Cu.reportError("Exception thrown while clearing HSTS/HPKP: " +
e.toString());
}
return Promise.all(promises);
}
};