Properly implement various HSTS states.

This commit is contained in:
Fedor 2019-09-20 13:14:00 +03:00
parent bb33363faf
commit 34eb8aadc5
2 changed files with 27 additions and 16 deletions

View File

@ -23,7 +23,7 @@ namespace mozilla
[ref] native nsCStringTArrayRef(nsTArray<nsCString>);
[ref] native mozillaPkixTime(mozilla::pkix::Time);
[scriptable, uuid(275127f8-dbd7-4681-afbf-6df0c6587a01)]
[scriptable, uuid(233908bd-6741-4474-a6e1-f298c6ce9eaf)]
interface nsISiteSecurityService : nsISupports
{
const uint32_t HEADER_HSTS = 0;
@ -98,15 +98,21 @@ interface nsISiteSecurityService : nsISupports
* Given a header type, removes state relating to that header of a host,
* including the includeSubdomains state that would affect subdomains.
* This essentially removes the state for the domain tree rooted at this
* host.
* host. If any preloaded information is present for that host, that
* information will then be used instead of any other previously existing
* state, unless the force parameter is set.
*
* @param aType the type of security state in question
* @param aURI the URI of the target host
* @param aFlags options for this request as defined in nsISocketProvider:
* NO_PERMANENT_STORAGE
* @param force if set, forces no-HSTS state by writing a knockout value,
* overriding any preload list state
*/
void removeState(in uint32_t aType,
in nsIURI aURI,
in uint32_t aFlags);
in uint32_t aFlags,
[optional] in boolean force);
/**
* See isSecureURI

View File

@ -330,21 +330,22 @@ nsSiteSecurityService::SetHSTSState(uint32_t aType,
uint32_t flags,
SecurityPropertyState aHSTSState)
{
// If max-age is zero, that's an indication to immediately remove the
// security state, so here's a shortcut.
if (!maxage) {
return RemoveState(aType, aSourceURI, flags);
// Exit early if STS not enabled
if (!mUseStsService) {
return NS_OK;
}
// If max-age is zero, the host is no longer considered HSTS. If the host was
// preloaded, we store an entry indicating that this host is not HSTS, causing
// the preloaded information to be ignored.
if (maxage == 0) {
return RemoveState(aType, aSourceURI, flags, true);
}
MOZ_ASSERT((aHSTSState == SecurityPropertySet ||
aHSTSState == SecurityPropertyNegative),
"HSTS State must be SecurityPropertySet or SecurityPropertyNegative");
// Exit early if STS not enabled
if (!mUseStsService) {
return NS_OK;
}
int64_t expiretime = ExpireTimeFromMaxAge(maxage);
SiteHSTSState siteState(expiretime, aHSTSState, includeSubdomains);
nsAutoCString stateString;
@ -367,7 +368,7 @@ nsSiteSecurityService::SetHSTSState(uint32_t aType,
NS_IMETHODIMP
nsSiteSecurityService::RemoveState(uint32_t aType, nsIURI* aURI,
uint32_t aFlags)
uint32_t aFlags, bool force = false)
{
// Child processes are not allowed direct access to this.
if (!XRE_IsParentProcess()) {
@ -387,8 +388,9 @@ nsSiteSecurityService::RemoveState(uint32_t aType, nsIURI* aURI,
mozilla::DataStorageType storageType = isPrivate
? mozilla::DataStorage_Private
: mozilla::DataStorage_Persistent;
// If this host is in the preload list, we have to store a knockout entry.
if (GetPreloadListEntry(hostname.get())) {
// If this host is in the preload list, we have to store a knockout entry
// if it's explicitly forced to not be HSTS anymore
if (force && GetPreloadListEntry(hostname.get())) {
SSSLOG(("SSS: storing knockout entry for %s", hostname.get()));
SiteHSTSState siteState(0, SecurityPropertyKnockout, false);
nsAutoCString stateString;
@ -769,7 +771,10 @@ nsSiteSecurityService::ProcessPKPHeader(nsIURI* aSourceURI,
return NS_ERROR_FAILURE;
}
// if maxAge == 0 we must delete all state, for now no hole-punching
// If maxAge == 0, we remove dynamic HPKP state for this host. Due to
// architectural constraints, if this host was preloaded, any future lookups
// will use the preloaded state (i.e. we can't store a "this host is not HPKP"
// entry like we can for HSTS).
if (maxAge == 0) {
return RemoveState(aType, aSourceURI, aFlags);
}