зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset d7e39be85498 (bug 1246540) for Mochitest failures
This commit is contained in:
Родитель
4f9ca91292
Коммит
a7c8429fc4
|
@ -4966,10 +4966,10 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||||
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
|
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
|
||||||
flags, nullptr, &isStsHost);
|
flags, &isStsHost);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI,
|
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI,
|
||||||
flags, nullptr, &isPinnedHost);
|
flags, &isPinnedHost);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
} else {
|
} else {
|
||||||
mozilla::dom::ContentChild* cc =
|
mozilla::dom::ContentChild* cc =
|
||||||
|
@ -9848,25 +9848,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||||
return NS_ERROR_CONTENT_BLOCKED;
|
return NS_ERROR_CONTENT_BLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
|
|
||||||
// would block due to mixed content, go ahead and block here. If we try to
|
|
||||||
// proceed with priming, we will error out later on.
|
|
||||||
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(context);
|
|
||||||
NS_ENSURE_TRUE(docShell, NS_OK);
|
|
||||||
if (docShell) {
|
|
||||||
nsIDocument* document = docShell->GetDocument();
|
|
||||||
NS_ENSURE_TRUE(document, NS_OK);
|
|
||||||
|
|
||||||
HSTSPrimingState state = document->GetHSTSPrimingStateForLocation(aURI);
|
|
||||||
if (state == HSTSPrimingState::eHSTS_PRIMING_BLOCK) {
|
|
||||||
// HSTS Priming currently disabled for InternalLoad, so we need to clear
|
|
||||||
// the location that was added by nsMixedContentBlocker::ShouldLoad
|
|
||||||
// Bug 1269815 will address images loaded via InternalLoad
|
|
||||||
document->ClearHSTSPrimingLocation(aURI);
|
|
||||||
return NS_ERROR_CONTENT_BLOCKED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> owner(aOwner);
|
nsCOMPtr<nsISupports> owner(aOwner);
|
||||||
//
|
//
|
||||||
// Get an owner from the current document if necessary. Note that we only
|
// Get an owner from the current document if necessary. Note that we only
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
#include "nsIUUIDGenerator.h"
|
#include "nsIUUIDGenerator.h"
|
||||||
#include "nsPIDOMWindow.h" // for use in inline functions
|
#include "nsPIDOMWindow.h" // for use in inline functions
|
||||||
#include "nsPropertyTable.h" // for member
|
#include "nsPropertyTable.h" // for member
|
||||||
#include "nsDataHashtable.h" // for member
|
#include "nsTHashtable.h" // for member
|
||||||
#include "nsURIHashKey.h" // for member
|
|
||||||
#include "mozilla/net/ReferrerPolicy.h" // for member
|
#include "mozilla/net/ReferrerPolicy.h" // for member
|
||||||
#include "nsWeakReference.h"
|
#include "nsWeakReference.h"
|
||||||
#include "mozilla/dom/DocumentBinding.h"
|
#include "mozilla/dom/DocumentBinding.h"
|
||||||
|
@ -167,13 +166,6 @@ enum DocumentFlavor {
|
||||||
DocumentFlavorPlain, // Just a Document
|
DocumentFlavorPlain, // Just a Document
|
||||||
};
|
};
|
||||||
|
|
||||||
// Enum for HSTS priming states
|
|
||||||
enum class HSTSPrimingState {
|
|
||||||
eNO_HSTS_PRIMING = 0, // don't do HSTS Priming
|
|
||||||
eHSTS_PRIMING_ALLOW = 1, // if HSTS priming fails, allow the load to proceed
|
|
||||||
eHSTS_PRIMING_BLOCK = 2 // if HSTS priming fails, block the load
|
|
||||||
};
|
|
||||||
|
|
||||||
// Document states
|
// Document states
|
||||||
|
|
||||||
// RTL locale: specific to the XUL localedir attribute
|
// RTL locale: specific to the XUL localedir attribute
|
||||||
|
@ -357,34 +349,6 @@ public:
|
||||||
mReferrer = aReferrer;
|
mReferrer = aReferrer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check to see if a subresource we want to load requires HSTS priming
|
|
||||||
* to be done.
|
|
||||||
*/
|
|
||||||
HSTSPrimingState GetHSTSPrimingStateForLocation(nsIURI* aContentLocation) const
|
|
||||||
{
|
|
||||||
HSTSPrimingState state;
|
|
||||||
if (mHSTSPrimingURIList.Get(aContentLocation, &state)) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
return HSTSPrimingState::eNO_HSTS_PRIMING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a subresource to the HSTS priming list. If this URI is
|
|
||||||
* not in the HSTS cache, it will trigger an HSTS priming request
|
|
||||||
* when we try to load it.
|
|
||||||
*/
|
|
||||||
void AddHSTSPrimingLocation(nsIURI* aContentLocation, HSTSPrimingState aState)
|
|
||||||
{
|
|
||||||
mHSTSPrimingURIList.Put(aContentLocation, aState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearHSTSPrimingLocation(nsIURI* aContentLocation)
|
|
||||||
{
|
|
||||||
mHSTSPrimingURIList.Remove(aContentLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the principal responsible for this document.
|
* Set the principal responsible for this document.
|
||||||
*/
|
*/
|
||||||
|
@ -2905,11 +2869,6 @@ protected:
|
||||||
bool mUpgradeInsecureRequests;
|
bool mUpgradeInsecureRequests;
|
||||||
bool mUpgradeInsecurePreloads;
|
bool mUpgradeInsecurePreloads;
|
||||||
|
|
||||||
// if nsMixedContentBlocker requires sending an HSTS priming request,
|
|
||||||
// temporarily store that in the document so that it can be propogated to the
|
|
||||||
// LoadInfo and eventually the HTTP Channel
|
|
||||||
nsDataHashtable<nsURIHashKey, HSTSPrimingState> mHSTSPrimingURIList;
|
|
||||||
|
|
||||||
mozilla::WeakPtr<nsDocShell> mDocumentContainer;
|
mozilla::WeakPtr<nsDocShell> mDocumentContainer;
|
||||||
|
|
||||||
nsCString mCharacterSet;
|
nsCString mCharacterSet;
|
||||||
|
|
|
@ -4289,18 +4289,18 @@ ContentParent::RecvIsSecureURI(const uint32_t& type,
|
||||||
if (!ourURI) {
|
if (!ourURI) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
nsresult rv = sss->IsSecureURI(type, ourURI, flags, isSecureURI, nullptr);
|
nsresult rv = sss->IsSecureURI(type, ourURI, flags, isSecureURI);
|
||||||
return NS_SUCCEEDED(rv);
|
return NS_SUCCEEDED(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive, const bool& aHSTSPriming)
|
ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIURI> ourURI = DeserializeURI(aURI);
|
nsCOMPtr<nsIURI> ourURI = DeserializeURI(aURI);
|
||||||
if (!ourURI) {
|
if (!ourURI) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive, aHSTSPriming);
|
nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -822,8 +822,7 @@ private:
|
||||||
const uint32_t& aFlags, bool* aIsSecureURI) override;
|
const uint32_t& aFlags, bool* aIsSecureURI) override;
|
||||||
|
|
||||||
virtual bool RecvAccumulateMixedContentHSTS(const URIParams& aURI,
|
virtual bool RecvAccumulateMixedContentHSTS(const URIParams& aURI,
|
||||||
const bool& aActive,
|
const bool& aActive) override;
|
||||||
const bool& aHSTSPriming) override;
|
|
||||||
|
|
||||||
virtual bool DeallocPHalParent(PHalParent*) override;
|
virtual bool DeallocPHalParent(PHalParent*) override;
|
||||||
|
|
||||||
|
|
|
@ -821,7 +821,7 @@ parent:
|
||||||
sync IsSecureURI(uint32_t type, URIParams uri, uint32_t flags)
|
sync IsSecureURI(uint32_t type, URIParams uri, uint32_t flags)
|
||||||
returns (bool isSecureURI);
|
returns (bool isSecureURI);
|
||||||
|
|
||||||
async AccumulateMixedContentHSTS(URIParams uri, bool active, bool hasHSTSPriming);
|
async AccumulateMixedContentHSTS(URIParams uri, bool active);
|
||||||
|
|
||||||
sync GetLookAndFeelCache()
|
sync GetLookAndFeelCache()
|
||||||
returns (LookAndFeelInt[] lookAndFeelIntCache);
|
returns (LookAndFeelInt[] lookAndFeelIntCache);
|
||||||
|
|
|
@ -20,7 +20,6 @@ EXPORTS.mozilla.dom += [
|
||||||
|
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'nsContentSecurityManager.h',
|
'nsContentSecurityManager.h',
|
||||||
'nsMixedContentBlocker.h',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsCORSListenerProxy.h"
|
#include "nsCORSListenerProxy.h"
|
||||||
#include "nsIStreamListener.h"
|
#include "nsIStreamListener.h"
|
||||||
#include "nsIDocument.h"
|
|
||||||
#include "nsMixedContentBlocker.h"
|
|
||||||
|
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
|
|
||||||
|
@ -383,14 +381,6 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
|
||||||
if (NS_CP_REJECTED(shouldLoad)) {
|
if (NS_CP_REJECTED(shouldLoad)) {
|
||||||
return NS_ERROR_CONTENT_BLOCKED;
|
return NS_ERROR_CONTENT_BLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsMixedContentBlocker::sSendHSTSPriming) {
|
|
||||||
rv = nsMixedContentBlocker::MarkLoadInfoForPriming(uri,
|
|
||||||
requestingContext,
|
|
||||||
aLoadInfo);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,11 +54,6 @@ bool nsMixedContentBlocker::sBlockMixedScript = false;
|
||||||
// Is mixed display content blocking (images, audio, video, <a ping>) enabled?
|
// Is mixed display content blocking (images, audio, video, <a ping>) enabled?
|
||||||
bool nsMixedContentBlocker::sBlockMixedDisplay = false;
|
bool nsMixedContentBlocker::sBlockMixedDisplay = false;
|
||||||
|
|
||||||
// Do we move HSTS before mixed-content
|
|
||||||
bool nsMixedContentBlocker::sUseHSTS = false;
|
|
||||||
// Do we send an HSTS priming request
|
|
||||||
bool nsMixedContentBlocker::sSendHSTSPriming = false;
|
|
||||||
|
|
||||||
// Fired at the document that attempted to load mixed content. The UI could
|
// Fired at the document that attempted to load mixed content. The UI could
|
||||||
// handle this event, for example, by displaying an info bar that offers the
|
// handle this event, for example, by displaying an info bar that offers the
|
||||||
// choice to reload the page with mixed content permitted.
|
// choice to reload the page with mixed content permitted.
|
||||||
|
@ -200,14 +195,6 @@ nsMixedContentBlocker::nsMixedContentBlocker()
|
||||||
// Cache the pref for mixed display blocking
|
// Cache the pref for mixed display blocking
|
||||||
Preferences::AddBoolVarCache(&sBlockMixedDisplay,
|
Preferences::AddBoolVarCache(&sBlockMixedDisplay,
|
||||||
"security.mixed_content.block_display_content");
|
"security.mixed_content.block_display_content");
|
||||||
|
|
||||||
// Cache the pref for HSTS
|
|
||||||
Preferences::AddBoolVarCache(&sUseHSTS,
|
|
||||||
"security.mixed_content.use_hsts");
|
|
||||||
|
|
||||||
// Cache the pref for sending HSTS priming
|
|
||||||
Preferences::AddBoolVarCache(&sSendHSTSPriming,
|
|
||||||
"security.mixed_content.send_hsts_priming");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsMixedContentBlocker::~nsMixedContentBlocker()
|
nsMixedContentBlocker::~nsMixedContentBlocker()
|
||||||
|
@ -254,6 +241,8 @@ LogMixedContentMessage(MixedContentTypes aClassification,
|
||||||
messageLookupKey.get(), strings, ArrayLength(strings));
|
messageLookupKey.get(), strings, ArrayLength(strings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* nsIChannelEventSink implementation
|
/* nsIChannelEventSink implementation
|
||||||
* This code is called when a request is redirected.
|
* This code is called when a request is redirected.
|
||||||
* We check the channel associated with the new uri is allowed to load
|
* We check the channel associated with the new uri is allowed to load
|
||||||
|
@ -477,6 +466,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
*aDecision = ACCEPT;
|
*aDecision = ACCEPT;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
|
|
||||||
// Static display content is considered moderate risk for mixed content so
|
// Static display content is considered moderate risk for mixed content so
|
||||||
// these will be blocked according to the mixed display preference
|
// these will be blocked according to the mixed display preference
|
||||||
case TYPE_IMAGE:
|
case TYPE_IMAGE:
|
||||||
|
@ -510,6 +500,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
// This content policy works as a whitelist.
|
// This content policy works as a whitelist.
|
||||||
default:
|
default:
|
||||||
MOZ_ASSERT(false, "Mixed content of unknown type");
|
MOZ_ASSERT(false, "Mixed content of unknown type");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure to get the URI the load started with. No need to check
|
// Make sure to get the URI the load started with. No need to check
|
||||||
|
@ -689,9 +680,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
bool isHttpScheme = false;
|
bool isHttpScheme = false;
|
||||||
rv = innerContentLocation->SchemeIs("http", &isHttpScheme);
|
rv = innerContentLocation->SchemeIs("http", &isHttpScheme);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
nsIDocument* document = docShell->GetDocument();
|
if (isHttpScheme && docShell->GetDocument()->GetUpgradeInsecureRequests(isPreload)) {
|
||||||
MOZ_ASSERT(document, "Expected a document");
|
|
||||||
if (isHttpScheme && document->GetUpgradeInsecureRequests(isPreload)) {
|
|
||||||
*aDecision = ACCEPT;
|
*aDecision = ACCEPT;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -702,7 +691,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
// Block all non secure loads in case the CSP directive is present. Please note
|
// Block all non secure loads in case the CSP directive is present. Please note
|
||||||
// that at this point we already know, based on |schemeSecure| that the load is
|
// that at this point we already know, based on |schemeSecure| that the load is
|
||||||
// not secure, so we can bail out early at this point.
|
// not secure, so we can bail out early at this point.
|
||||||
if (document->GetBlockAllMixedContent(isPreload)) {
|
if (docShell->GetDocument()->GetBlockAllMixedContent(isPreload)) {
|
||||||
// log a message to the console before returning.
|
// log a message to the console before returning.
|
||||||
nsAutoCString spec;
|
nsAutoCString spec;
|
||||||
rv = aContentLocation->GetSpec(spec);
|
rv = aContentLocation->GetSpec(spec);
|
||||||
|
@ -717,7 +706,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
0, // aLineNumber
|
0, // aLineNumber
|
||||||
0, // aColumnNumber
|
0, // aColumnNumber
|
||||||
nsIScriptError::errorFlag, "CSP",
|
nsIScriptError::errorFlag, "CSP",
|
||||||
document->InnerWindowID());
|
docShell->GetDocument()->InnerWindowID());
|
||||||
*aDecision = REJECT_REQUEST;
|
*aDecision = REJECT_REQUEST;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -810,34 +799,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
}
|
}
|
||||||
nsresult stateRV = securityUI->GetState(&state);
|
nsresult stateRV = securityUI->GetState(&state);
|
||||||
|
|
||||||
bool doHSTSPriming = false;
|
|
||||||
if (isHttpScheme) {
|
|
||||||
bool hsts = false;
|
|
||||||
bool cached = false;
|
|
||||||
nsCOMPtr<nsISiteSecurityService> sss =
|
|
||||||
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aContentLocation,
|
|
||||||
0, &cached, &hsts);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (hsts && sUseHSTS) {
|
|
||||||
// assume we will be upgraded later
|
|
||||||
*aDecision = ACCEPT;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a priming request if the result is not already cached and priming
|
|
||||||
// requests are allowed
|
|
||||||
if (!cached && sSendHSTSPriming) {
|
|
||||||
// add this URI as a priming location
|
|
||||||
doHSTSPriming = true;
|
|
||||||
document->AddHSTSPrimingLocation(innerContentLocation,
|
|
||||||
HSTSPrimingState::eHSTS_PRIMING_ALLOW);
|
|
||||||
*aDecision = ACCEPT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point we know that the request is mixed content, and the only
|
// At this point we know that the request is mixed content, and the only
|
||||||
// question is whether we block it. Record telemetry at this point as to
|
// question is whether we block it. Record telemetry at this point as to
|
||||||
// whether HSTS would have fixed things by making the content location
|
// whether HSTS would have fixed things by making the content location
|
||||||
|
@ -853,14 +814,14 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
bool active = (classification == eMixedScript);
|
bool active = (classification == eMixedScript);
|
||||||
if (!aHadInsecureImageRedirect) {
|
if (!aHadInsecureImageRedirect) {
|
||||||
if (XRE_IsParentProcess()) {
|
if (XRE_IsParentProcess()) {
|
||||||
AccumulateMixedContentHSTS(innerContentLocation, active, doHSTSPriming);
|
AccumulateMixedContentHSTS(innerContentLocation, active);
|
||||||
} else {
|
} else {
|
||||||
// Ask the parent process to do the same call
|
// Ask the parent process to do the same call
|
||||||
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
|
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
|
||||||
if (cc) {
|
if (cc) {
|
||||||
mozilla::ipc::URIParams uri;
|
mozilla::ipc::URIParams uri;
|
||||||
SerializeURI(innerContentLocation, uri);
|
SerializeURI(innerContentLocation, uri);
|
||||||
cc->SendAccumulateMixedContentHSTS(uri, active, doHSTSPriming);
|
cc->SendAccumulateMixedContentHSTS(uri, active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -903,13 +864,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (doHSTSPriming) {
|
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||||
document->AddHSTSPrimingLocation(innerContentLocation,
|
|
||||||
HSTSPrimingState::eHSTS_PRIMING_BLOCK);
|
|
||||||
*aDecision = nsIContentPolicy::ACCEPT;
|
|
||||||
} else {
|
|
||||||
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
|
||||||
}
|
|
||||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
|
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
|
||||||
if (!rootDoc->GetHasMixedDisplayContentBlocked() && NS_SUCCEEDED(stateRV)) {
|
if (!rootDoc->GetHasMixedDisplayContentBlocked() && NS_SUCCEEDED(stateRV)) {
|
||||||
rootDoc->SetHasMixedDisplayContentBlocked(true);
|
rootDoc->SetHasMixedDisplayContentBlocked(true);
|
||||||
|
@ -955,13 +910,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//User has not overriden the pref by Disabling protection. Reject the request and update the security state.
|
//User has not overriden the pref by Disabling protection. Reject the request and update the security state.
|
||||||
if (doHSTSPriming) {
|
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||||
document->AddHSTSPrimingLocation(innerContentLocation,
|
|
||||||
HSTSPrimingState::eHSTS_PRIMING_BLOCK);
|
|
||||||
*aDecision = nsIContentPolicy::ACCEPT;
|
|
||||||
} else {
|
|
||||||
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
|
||||||
}
|
|
||||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
|
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
|
||||||
// See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
|
// See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
|
||||||
if (rootDoc->GetHasMixedActiveContentBlocked()) {
|
if (rootDoc->GetHasMixedActiveContentBlocked()) {
|
||||||
|
@ -976,6 +925,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// The content is not blocked by the mixed content prefs.
|
// The content is not blocked by the mixed content prefs.
|
||||||
|
|
||||||
|
@ -1026,24 +976,10 @@ enum MixedContentHSTSState {
|
||||||
MCB_HSTS_ACTIVE_WITH_HSTS = 3
|
MCB_HSTS_ACTIVE_WITH_HSTS = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
// Similar to the existing mixed-content HSTS, except MCB_HSTS_*_NO_HSTS is
|
|
||||||
// broken into two distinct states, indicating whether we plan to send a priming
|
|
||||||
// request or not. If we decided not go send a priming request, it could be
|
|
||||||
// because it is a type we do not support, or because we cached a previous
|
|
||||||
// negative response.
|
|
||||||
enum MixedContentHSTSPrimingState {
|
|
||||||
eMCB_HSTS_PASSIVE_WITH_HSTS = 0,
|
|
||||||
eMCB_HSTS_ACTIVE_WITH_HSTS = 1,
|
|
||||||
eMCB_HSTS_PASSIVE_NO_PRIMING = 2,
|
|
||||||
eMCB_HSTS_PASSIVE_DO_PRIMING = 3,
|
|
||||||
eMCB_HSTS_ACTIVE_NO_PRIMING = 4,
|
|
||||||
eMCB_HSTS_ACTIVE_DO_PRIMING = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
// Record information on when HSTS would have made mixed content not mixed
|
// Record information on when HSTS would have made mixed content not mixed
|
||||||
// content (regardless of whether it was actually blocked)
|
// content (regardless of whether it was actually blocked)
|
||||||
void
|
void
|
||||||
nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive, bool aHasHSTSPriming)
|
nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive)
|
||||||
{
|
{
|
||||||
// This method must only be called in the parent, because
|
// This method must only be called in the parent, because
|
||||||
// nsSiteSecurityService is only available in the parent
|
// nsSiteSecurityService is only available in the parent
|
||||||
|
@ -1058,88 +994,28 @@ nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive, bo
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, 0, nullptr, &hsts);
|
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, 0, &hsts);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// states: would upgrade, would prime, hsts info cached
|
|
||||||
// active, passive
|
|
||||||
//
|
|
||||||
if (!aActive) {
|
if (!aActive) {
|
||||||
if (!hsts) {
|
if (!hsts) {
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
||||||
MCB_HSTS_PASSIVE_NO_HSTS);
|
MCB_HSTS_PASSIVE_NO_HSTS);
|
||||||
if (aHasHSTSPriming) {
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
|
||||||
eMCB_HSTS_PASSIVE_DO_PRIMING);
|
|
||||||
} else {
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
|
||||||
eMCB_HSTS_PASSIVE_NO_PRIMING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
||||||
MCB_HSTS_PASSIVE_WITH_HSTS);
|
MCB_HSTS_PASSIVE_WITH_HSTS);
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
|
||||||
eMCB_HSTS_PASSIVE_WITH_HSTS);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!hsts) {
|
if (!hsts) {
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
||||||
MCB_HSTS_ACTIVE_NO_HSTS);
|
MCB_HSTS_ACTIVE_NO_HSTS);
|
||||||
if (aHasHSTSPriming) {
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
|
||||||
eMCB_HSTS_ACTIVE_DO_PRIMING);
|
|
||||||
} else {
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
|
||||||
eMCB_HSTS_ACTIVE_NO_PRIMING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
||||||
MCB_HSTS_ACTIVE_WITH_HSTS);
|
MCB_HSTS_ACTIVE_WITH_HSTS);
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
|
||||||
eMCB_HSTS_ACTIVE_WITH_HSTS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
|
||||||
nsresult
|
|
||||||
nsMixedContentBlocker::MarkLoadInfoForPriming(nsIURI* aURI,
|
|
||||||
nsISupports* aRequestingContext,
|
|
||||||
nsILoadInfo* aLoadInfo)
|
|
||||||
{
|
|
||||||
// If we marked for priming, we used the innermost URI, so get that
|
|
||||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
|
|
||||||
if (!innerURI) {
|
|
||||||
NS_ERROR("Can't get innerURI from aContentLocation");
|
|
||||||
return NS_ERROR_CONTENT_BLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isHttp = false;
|
|
||||||
innerURI->SchemeIs("http", &isHttp);
|
|
||||||
if (!isHttp) {
|
|
||||||
// there is nothign to do
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the DocShell was marked for HSTS priming, propagate that to the LoadInfo
|
|
||||||
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
|
|
||||||
if (!docShell) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
nsIDocument* document = docShell->GetDocument();
|
|
||||||
if (!document) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HSTSPrimingState status = document->GetHSTSPrimingStateForLocation(innerURI);
|
|
||||||
// set it on the loadInfo
|
|
||||||
if (status != HSTSPrimingState::eNO_HSTS_PRIMING) {
|
|
||||||
aLoadInfo->SetHSTSPriming(status == HSTSPrimingState::eHSTS_PRIMING_BLOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,8 +28,6 @@ enum MixedContentTypes {
|
||||||
#include "nsIChannelEventSink.h"
|
#include "nsIChannelEventSink.h"
|
||||||
#include "imgRequest.h"
|
#include "imgRequest.h"
|
||||||
|
|
||||||
class nsILoadInfo; // forward declaration
|
|
||||||
|
|
||||||
class nsMixedContentBlocker : public nsIContentPolicy,
|
class nsMixedContentBlocker : public nsIContentPolicy,
|
||||||
public nsIChannelEventSink
|
public nsIChannelEventSink
|
||||||
{
|
{
|
||||||
|
@ -61,25 +59,9 @@ public:
|
||||||
nsISupports* aExtra,
|
nsISupports* aExtra,
|
||||||
nsIPrincipal* aRequestPrincipal,
|
nsIPrincipal* aRequestPrincipal,
|
||||||
int16_t* aDecision);
|
int16_t* aDecision);
|
||||||
static void AccumulateMixedContentHSTS(nsIURI* aURI,
|
static void AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive);
|
||||||
bool aActive,
|
|
||||||
bool aHasHSTSPriming);
|
|
||||||
/* If the document associated with aRequestingContext requires priming for
|
|
||||||
* aURI, propagate that to the LoadInfo so the HttpChannel will find out about
|
|
||||||
* it.
|
|
||||||
*
|
|
||||||
* @param aURI The URI associated with the load
|
|
||||||
* @param aRequestingContext the requesting context passed to ShouldLoad
|
|
||||||
* @param aLoadInfo the LoadInfo for the load
|
|
||||||
*/
|
|
||||||
static nsresult MarkLoadInfoForPriming(nsIURI* aURI,
|
|
||||||
nsISupports* aRequestingContext,
|
|
||||||
nsILoadInfo* aLoadInfo);
|
|
||||||
|
|
||||||
static bool sBlockMixedScript;
|
static bool sBlockMixedScript;
|
||||||
static bool sBlockMixedDisplay;
|
static bool sBlockMixedDisplay;
|
||||||
static bool sUseHSTS;
|
|
||||||
static bool sSendHSTSPriming;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* nsMixedContentBlocker_h___ */
|
#endif /* nsMixedContentBlocker_h___ */
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
[DEFAULT]
|
|
||||||
support-files =
|
|
||||||
file_priming-top.html
|
|
||||||
file_testserver.sjs
|
|
||||||
file_1x1.png
|
|
||||||
file_priming.js
|
|
||||||
file_stylesheet.css
|
|
||||||
|
|
||||||
[browser_hsts-priming_main.js]
|
|
|
@ -1,295 +0,0 @@
|
||||||
/*
|
|
||||||
* Description of the test:
|
|
||||||
* Check that HSTS priming occurs correctly with mixed content
|
|
||||||
*
|
|
||||||
* This test uses three hostnames, each of which treats an HSTS priming
|
|
||||||
* request differently.
|
|
||||||
* * no-ssl never returns an ssl response
|
|
||||||
* * reject-upgrade returns an ssl response, but with no STS header
|
|
||||||
* * prime-hsts returns an ssl response with the appropriate STS header
|
|
||||||
*
|
|
||||||
* For each server, test that it response appropriately when the we allow
|
|
||||||
* or block active or display content, as well as when we send an hsts priming
|
|
||||||
* request, but do not change the order of mixed-content and HSTS.
|
|
||||||
*
|
|
||||||
* This test uses http-on-examine-response, so must be run in browser context.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var TOP_URI = "https://example.com/browser/dom/security/test/hsts/file_priming-top.html";
|
|
||||||
|
|
||||||
var test_servers = {
|
|
||||||
// a test server that does not support TLS
|
|
||||||
'no-ssl': {
|
|
||||||
host: 'example.co.jp',
|
|
||||||
response: false,
|
|
||||||
id: 'no-ssl',
|
|
||||||
},
|
|
||||||
// a test server which does not support STS upgrade
|
|
||||||
'reject-upgrade': {
|
|
||||||
host: 'example.org',
|
|
||||||
response: true,
|
|
||||||
id: 'reject-upgrade',
|
|
||||||
},
|
|
||||||
// a test server when sends an STS header when priming
|
|
||||||
'prime-hsts': {
|
|
||||||
host: 'test1.example.com',
|
|
||||||
response: true,
|
|
||||||
id: 'prime-hsts'
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// The number of priming responses we expect to see
|
|
||||||
var priming_count = 2;
|
|
||||||
|
|
||||||
var test_settings = {
|
|
||||||
// mixed active content is allowed, priming will upgrade
|
|
||||||
allow_active: {
|
|
||||||
block_active: false,
|
|
||||||
block_display: false,
|
|
||||||
use_hsts: true,
|
|
||||||
send_hsts_priming: true,
|
|
||||||
type: 'script',
|
|
||||||
result: {
|
|
||||||
'no-ssl': 'insecure',
|
|
||||||
'reject-upgrade': 'insecure',
|
|
||||||
'prime-hsts': 'secure',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// mixed active content is blocked, priming will upgrade
|
|
||||||
block_active: {
|
|
||||||
block_active: true,
|
|
||||||
block_display: false,
|
|
||||||
use_hsts: true,
|
|
||||||
send_hsts_priming: true,
|
|
||||||
type: 'script',
|
|
||||||
result: {
|
|
||||||
'no-ssl': 'blocked',
|
|
||||||
'reject-upgrade': 'blocked',
|
|
||||||
'prime-hsts': 'secure',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// keep the original order of mixed-content and HSTS, but send
|
|
||||||
// priming requests
|
|
||||||
hsts_after_mixed: {
|
|
||||||
block_active: true,
|
|
||||||
block_display: false,
|
|
||||||
use_hsts: false,
|
|
||||||
send_hsts_priming: true,
|
|
||||||
type: 'script',
|
|
||||||
result: {
|
|
||||||
'no-ssl': 'blocked',
|
|
||||||
'reject-upgrade': 'blocked',
|
|
||||||
'prime-hsts': 'blocked',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// mixed display content is allowed, priming will upgrade
|
|
||||||
allow_display: {
|
|
||||||
block_active: true,
|
|
||||||
block_display: false,
|
|
||||||
use_hsts: true,
|
|
||||||
send_hsts_priming: true,
|
|
||||||
type: 'img',
|
|
||||||
result: {
|
|
||||||
'no-ssl': 'insecure',
|
|
||||||
'reject-upgrade': 'insecure',
|
|
||||||
'prime-hsts': 'secure',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// mixed display content is blocked, priming will upgrade
|
|
||||||
block_display: {
|
|
||||||
block_active: true,
|
|
||||||
block_display: true,
|
|
||||||
use_hsts: true,
|
|
||||||
send_hsts_priming: true,
|
|
||||||
type: 'img',
|
|
||||||
result: {
|
|
||||||
'no-ssl': 'blocked',
|
|
||||||
'reject-upgrade': 'blocked',
|
|
||||||
'prime-hsts': 'secure',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// mixed active content is blocked, priming will upgrade (css)
|
|
||||||
block_active_css: {
|
|
||||||
block_active: true,
|
|
||||||
block_display: false,
|
|
||||||
use_hsts: true,
|
|
||||||
send_hsts_priming: true,
|
|
||||||
type: 'css',
|
|
||||||
result: {
|
|
||||||
'no-ssl': 'blocked',
|
|
||||||
'reject-upgrade': 'blocked',
|
|
||||||
'prime-hsts': 'secure',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// mixed active content is blocked, priming will upgrade
|
|
||||||
// redirect to the same host
|
|
||||||
block_active_with_redir_same: {
|
|
||||||
block_active: true,
|
|
||||||
block_display: false,
|
|
||||||
use_hsts: true,
|
|
||||||
send_hsts_priming: true,
|
|
||||||
type: 'script',
|
|
||||||
redir: 'same',
|
|
||||||
result: {
|
|
||||||
'no-ssl': 'blocked',
|
|
||||||
'reject-upgrade': 'blocked',
|
|
||||||
'prime-hsts': 'secure',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// track which test we are on
|
|
||||||
var which_test = "";
|
|
||||||
|
|
||||||
const Observer = {
|
|
||||||
observe: function (subject, topic, data) {
|
|
||||||
switch (topic) {
|
|
||||||
case 'console-api-log-event':
|
|
||||||
return Observer.console_api_log_event(subject, topic, data);
|
|
||||||
case 'http-on-examine-response':
|
|
||||||
return Observer.http_on_examine_response(subject, topic, data);
|
|
||||||
}
|
|
||||||
throw "Can't handle topic "+topic;
|
|
||||||
},
|
|
||||||
// When a load is blocked which results in an error event within a page, the
|
|
||||||
// test logs to the console.
|
|
||||||
console_api_log_event: function (subject, topic, data) {
|
|
||||||
var message = subject.wrappedJSObject.arguments[0];
|
|
||||||
// when we are blocked, this will match the message we sent to the console,
|
|
||||||
// ignore everything else.
|
|
||||||
var re = RegExp(/^HSTS_PRIMING: Blocked ([-\w]+).*$/);
|
|
||||||
if (!re.test(message)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let id = message.replace(re, '$1');
|
|
||||||
let curTest =test_servers[id];
|
|
||||||
|
|
||||||
if (!curTest) {
|
|
||||||
ok(false, "HSTS priming got a console message blocked, "+
|
|
||||||
"but doesn't match expectations "+id+" (msg="+message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
is("blocked", test_settings[which_test].result[curTest.id], "HSTS priming "+
|
|
||||||
which_test+":"+curTest.id+" expected "+
|
|
||||||
test_settings[which_test].result[curTest.id]+", got blocked");
|
|
||||||
test_settings[which_test].finished[curTest.id] = "blocked";
|
|
||||||
},
|
|
||||||
// When we see a response come back, peek at the response and test it is secure
|
|
||||||
// or insecure as needed. Addtionally, watch the response for priming requests.
|
|
||||||
http_on_examine_response: function (subject, topic, data) {
|
|
||||||
let curTest = null;
|
|
||||||
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
|
|
||||||
for (let item in test_servers) {
|
|
||||||
let re = RegExp('https?://'+test_servers[item].host);
|
|
||||||
if (re.test(channel.URI.asciiSpec)) {
|
|
||||||
curTest = test_servers[item];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!curTest) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = (channel.URI.asciiSpec.startsWith('https:')) ? "secure" : "insecure";
|
|
||||||
|
|
||||||
// This is a priming request, go ahead and validate we were supposed to see
|
|
||||||
// a response from the server
|
|
||||||
if (channel.requestMethod == 'HEAD') {
|
|
||||||
is(true, curTest.response, "HSTS priming response found " + curTest.id);
|
|
||||||
test_settings[which_test].priming[curTest.id] = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the response to our query, make sure it matches
|
|
||||||
is(result, test_settings[which_test].result[curTest.id],
|
|
||||||
"HSTS priming result " + which_test + ":" + curTest.id);
|
|
||||||
test_settings[which_test].finished[curTest.id] = result;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// opens `uri' in a new tab and focuses it.
|
|
||||||
// returns the newly opened tab
|
|
||||||
function openTab(uri) {
|
|
||||||
let tab = gBrowser.addTab(uri);
|
|
||||||
|
|
||||||
// select tab and make sure its browser is focused
|
|
||||||
gBrowser.selectedTab = tab;
|
|
||||||
tab.ownerDocument.defaultView.focus();
|
|
||||||
|
|
||||||
return tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear_sts_data() {
|
|
||||||
for (let test in test_servers) {
|
|
||||||
SpecialPowers.cleanUpSTSData('http://'+test_servers[test].host);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function do_cleanup() {
|
|
||||||
clear_sts_data();
|
|
||||||
|
|
||||||
Services.obs.removeObserver(Observer, "console-api-log-event");
|
|
||||||
Services.obs.removeObserver(Observer, "http-on-examine-response");
|
|
||||||
}
|
|
||||||
|
|
||||||
function SetupPrefTestEnvironment(which) {
|
|
||||||
which_test = which;
|
|
||||||
clear_sts_data();
|
|
||||||
|
|
||||||
var settings = test_settings[which];
|
|
||||||
// priming counts how many priming requests we saw
|
|
||||||
settings.priming = {};
|
|
||||||
// priming counts how many tests were finished
|
|
||||||
settings.finished= {};
|
|
||||||
|
|
||||||
SpecialPowers.pushPrefEnv({'set': [["security.mixed_content.block_active_content",
|
|
||||||
settings.block_active],
|
|
||||||
["security.mixed_content.block_display_content",
|
|
||||||
settings.block_display],
|
|
||||||
["security.mixed_content.use_hsts",
|
|
||||||
settings.use_hsts],
|
|
||||||
["security.mixed_content.send_hsts_priming",
|
|
||||||
settings.send_hsts_priming]]});
|
|
||||||
}
|
|
||||||
|
|
||||||
// make the top-level test uri
|
|
||||||
function build_test_uri(base_uri, host, test_id, type) {
|
|
||||||
return base_uri +
|
|
||||||
"?host=" + escape(host) +
|
|
||||||
"&id=" + escape(test_id) +
|
|
||||||
"&type=" + escape(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// open a new tab, load the test, and wait for it to finish
|
|
||||||
function execute_test(test, mimetype) {
|
|
||||||
var src = build_test_uri(TOP_URI, test_servers[test].host,
|
|
||||||
test, test_settings[which_test].type);
|
|
||||||
|
|
||||||
let tab = openTab(src);
|
|
||||||
test_servers[test]['tab'] = tab;
|
|
||||||
|
|
||||||
let browser = gBrowser.getBrowserForTab(tab);
|
|
||||||
yield BrowserTestUtils.browserLoaded(browser);
|
|
||||||
|
|
||||||
gBrowser.removeTab(tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
//jscs:disable
|
|
||||||
add_task(function*() {
|
|
||||||
//jscs:enable
|
|
||||||
Services.obs.addObserver(Observer, "console-api-log-event", false);
|
|
||||||
Services.obs.addObserver(Observer, "http-on-examine-response", false);
|
|
||||||
registerCleanupFunction(do_cleanup);
|
|
||||||
|
|
||||||
for (let which of Object.keys(test_settings)) {
|
|
||||||
SetupPrefTestEnvironment(which);
|
|
||||||
|
|
||||||
for (let server of Object.keys(test_servers)) {
|
|
||||||
yield execute_test(server, test_settings[which].mimetype);
|
|
||||||
}
|
|
||||||
|
|
||||||
SpecialPowers.popPrefEnv();
|
|
||||||
}
|
|
||||||
});
|
|
Двоичные данные
dom/security/test/hsts/file_1x1.png
Двоичные данные
dom/security/test/hsts/file_1x1.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 17 KiB |
|
@ -1,84 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Bug 1246540</title>
|
|
||||||
<meta http-equiv='content-type' content="text/html;charset=utf-8" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p id="display"></p>
|
|
||||||
<div id="content" style="visibility: hidden">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
/*
|
|
||||||
* Description of the test:
|
|
||||||
* Attempt to load an insecure resource. If the resource responds to HSTS
|
|
||||||
* priming with an STS header, the load should continue securely.
|
|
||||||
* If it does not, the load should continue be blocked or continue insecurely.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parse_query_string() {
|
|
||||||
var q = {};
|
|
||||||
document.location.search.substr(1).
|
|
||||||
split('&').forEach(function (item, idx, ar) {
|
|
||||||
let [k, v] = item.split('=');
|
|
||||||
q[k] = unescape(v);
|
|
||||||
});
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
var args = parse_query_string();
|
|
||||||
|
|
||||||
var subresources = {
|
|
||||||
css: { mimetype: 'text/css', file: 'file_stylesheet.css' },
|
|
||||||
img: { mimetype: 'image/png', file: 'file_1x1.png' },
|
|
||||||
script: { mimetype: 'text/javascript', file: 'file_priming.js' },
|
|
||||||
};
|
|
||||||
|
|
||||||
function handler(ev) {
|
|
||||||
console.log("HSTS_PRIMING: Blocked "+args.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadCss(src) {
|
|
||||||
let head = document.getElementsByTagName("head")[0];
|
|
||||||
let link = document.createElement("link");
|
|
||||||
link.setAttribute("rel", "stylesheet");
|
|
||||||
link.setAttribute("type", subresources[args.type].mimetype);
|
|
||||||
link.setAttribute("href", src);
|
|
||||||
head.appendChild(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadResource(src) {
|
|
||||||
let content = document.getElementById("content");
|
|
||||||
let testElem = document.createElement(args.type);
|
|
||||||
testElem.setAttribute("id", args.id);
|
|
||||||
testElem.setAttribute("charset", "UTF-8");
|
|
||||||
testElem.onerror = handler;
|
|
||||||
content.appendChild(testElem);
|
|
||||||
testElem.src = src;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadTest() {
|
|
||||||
let subresource = subresources[args.type];
|
|
||||||
|
|
||||||
let src = "http://"
|
|
||||||
+ args.host
|
|
||||||
+ "/browser/dom/security/test/hsts/file_testserver.sjs"
|
|
||||||
+ "?file=" +escape("browser/dom/security/test/hsts/" + subresource.file)
|
|
||||||
+ "&primer=" + escape(args.id)
|
|
||||||
+ "&mimetype=" + escape(subresource.mimetype)
|
|
||||||
;
|
|
||||||
if (args.type == 'css') {
|
|
||||||
loadCss(src);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadResource(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// start running the tests
|
|
||||||
loadTest();
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,4 +0,0 @@
|
||||||
function completed() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
completed();
|
|
|
@ -1,66 +0,0 @@
|
||||||
// SJS file for HSTS mochitests
|
|
||||||
|
|
||||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
|
||||||
Components.utils.importGlobalProperties(["URLSearchParams"]);
|
|
||||||
|
|
||||||
function loadFromFile(path) {
|
|
||||||
// Load the HTML to return in the response from file.
|
|
||||||
// Since it's relative to the cwd of the test runner, we start there and
|
|
||||||
// append to get to the actual path of the file.
|
|
||||||
var testFile =
|
|
||||||
Components.classes["@mozilla.org/file/directory_service;1"].
|
|
||||||
getService(Components.interfaces.nsIProperties).
|
|
||||||
get("CurWorkD", Components.interfaces.nsILocalFile);
|
|
||||||
var dirs = path.split("/");
|
|
||||||
for (var i = 0; i < dirs.length; i++) {
|
|
||||||
testFile.append(dirs[i]);
|
|
||||||
}
|
|
||||||
var testFileStream =
|
|
||||||
Components.classes["@mozilla.org/network/file-input-stream;1"].
|
|
||||||
createInstance(Components.interfaces.nsIFileInputStream);
|
|
||||||
testFileStream.init(testFile, -1, 0, 0);
|
|
||||||
var test = NetUtil.readInputStreamToString(testFileStream, testFileStream.available());
|
|
||||||
return test;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleRequest(request, response)
|
|
||||||
{
|
|
||||||
const query = new URLSearchParams(request.queryString);
|
|
||||||
|
|
||||||
redir = query.get('redir');
|
|
||||||
if (redir == 'same') {
|
|
||||||
query.delete("redir");
|
|
||||||
response.setStatus(302);
|
|
||||||
let newURI = request.uri;
|
|
||||||
newURI.queryString = query.serialize();
|
|
||||||
response.setHeader("Location", newURI.spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
// avoid confusing cache behaviors
|
|
||||||
response.setHeader("Cache-Control", "no-cache", false);
|
|
||||||
|
|
||||||
// if we have a priming header, check for required behavior
|
|
||||||
// and set header appropriately
|
|
||||||
if (request.hasHeader('Upgrade-Insecure-Requests')) {
|
|
||||||
var expected = query.get('primer');
|
|
||||||
if (expected == 'prime-hsts') {
|
|
||||||
// set it for 5 minutes
|
|
||||||
response.setHeader("Strict-Transport-Security", "max-age="+(60*5), false);
|
|
||||||
} else if (expected == 'reject-upgrade') {
|
|
||||||
response.setHeader("Strict-Transport-Security", "max-age=0", false);
|
|
||||||
}
|
|
||||||
response.write('');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var file = query.get('file');
|
|
||||||
if (file) {
|
|
||||||
var mimetype = unescape(query.get('mimetype'));
|
|
||||||
response.setHeader("Content-Type", mimetype, false);
|
|
||||||
response.write(loadFromFile(unescape(file)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
response.setHeader("Content-Type", "application/json", false);
|
|
||||||
response.write('{}');
|
|
||||||
}
|
|
|
@ -162,9 +162,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=62178
|
||||||
}
|
}
|
||||||
|
|
||||||
function startTest() {
|
function startTest() {
|
||||||
// Set prefs to use mixed-content before HSTS
|
|
||||||
SpecialPowers.pushPrefEnv({'set': [["security.mixed_content.use_hsts", false],
|
|
||||||
["security.mixed_content.send_hsts_priming", false]]});
|
|
||||||
//Set the first set of mixed content settings and increment the counter.
|
//Set the first set of mixed content settings and increment the counter.
|
||||||
//Enable <picture> and <img srcset> for the test.
|
//Enable <picture> and <img srcset> for the test.
|
||||||
changePrefs([[ "dom.image.srcset.enabled", true ], [ "dom.image.picture.enabled", true ]],
|
changePrefs([[ "dom.image.srcset.enabled", true ], [ "dom.image.picture.enabled", true ]],
|
||||||
|
|
|
@ -27,5 +27,4 @@ MOCHITEST_CHROME_MANIFESTS += [
|
||||||
BROWSER_CHROME_MANIFESTS += [
|
BROWSER_CHROME_MANIFESTS += [
|
||||||
'contentverifier/browser.ini',
|
'contentverifier/browser.ini',
|
||||||
'csp/browser.ini',
|
'csp/browser.ini',
|
||||||
'hsts/browser.ini',
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -263,9 +263,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
|
||||||
redirectChain,
|
redirectChain,
|
||||||
aLoadInfo->CorsUnsafeHeaders(),
|
aLoadInfo->CorsUnsafeHeaders(),
|
||||||
aLoadInfo->GetForcePreflight(),
|
aLoadInfo->GetForcePreflight(),
|
||||||
aLoadInfo->GetIsPreflight(),
|
aLoadInfo->GetIsPreflight());
|
||||||
aLoadInfo->GetForceHSTSPriming(),
|
|
||||||
aLoadInfo->GetMixedContentWouldBlock());
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -331,10 +329,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
|
||||||
redirectChain,
|
redirectChain,
|
||||||
loadInfoArgs.corsUnsafeHeaders(),
|
loadInfoArgs.corsUnsafeHeaders(),
|
||||||
loadInfoArgs.forcePreflight(),
|
loadInfoArgs.forcePreflight(),
|
||||||
loadInfoArgs.isPreflight(),
|
loadInfoArgs.isPreflight());
|
||||||
loadInfoArgs.forceHSTSPriming(),
|
|
||||||
loadInfoArgs.mixedContentWouldBlock()
|
|
||||||
);
|
|
||||||
|
|
||||||
loadInfo.forget(outLoadInfo);
|
loadInfo.forget(outLoadInfo);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
@ -60,8 +60,6 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
|
||||||
, mIsThirdPartyContext(false)
|
, mIsThirdPartyContext(false)
|
||||||
, mForcePreflight(false)
|
, mForcePreflight(false)
|
||||||
, mIsPreflight(false)
|
, mIsPreflight(false)
|
||||||
, mForceHSTSPriming(false)
|
|
||||||
, mMixedContentWouldBlock(false)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mLoadingPrincipal);
|
MOZ_ASSERT(mLoadingPrincipal);
|
||||||
MOZ_ASSERT(mTriggeringPrincipal);
|
MOZ_ASSERT(mTriggeringPrincipal);
|
||||||
|
@ -215,8 +213,6 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
|
||||||
, mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party.
|
, mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party.
|
||||||
, mForcePreflight(false)
|
, mForcePreflight(false)
|
||||||
, mIsPreflight(false)
|
, mIsPreflight(false)
|
||||||
, mForceHSTSPriming(false)
|
|
||||||
, mMixedContentWouldBlock(false)
|
|
||||||
{
|
{
|
||||||
// Top-level loads are never third-party
|
// Top-level loads are never third-party
|
||||||
// Grab the information we can out of the window.
|
// Grab the information we can out of the window.
|
||||||
|
@ -269,8 +265,6 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
|
||||||
, mCorsUnsafeHeaders(rhs.mCorsUnsafeHeaders)
|
, mCorsUnsafeHeaders(rhs.mCorsUnsafeHeaders)
|
||||||
, mForcePreflight(rhs.mForcePreflight)
|
, mForcePreflight(rhs.mForcePreflight)
|
||||||
, mIsPreflight(rhs.mIsPreflight)
|
, mIsPreflight(rhs.mIsPreflight)
|
||||||
, mForceHSTSPriming(rhs.mForceHSTSPriming)
|
|
||||||
, mMixedContentWouldBlock(rhs.mMixedContentWouldBlock)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,9 +288,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
|
||||||
nsTArray<nsCOMPtr<nsIPrincipal>>& aRedirectChain,
|
nsTArray<nsCOMPtr<nsIPrincipal>>& aRedirectChain,
|
||||||
const nsTArray<nsCString>& aCorsUnsafeHeaders,
|
const nsTArray<nsCString>& aCorsUnsafeHeaders,
|
||||||
bool aForcePreflight,
|
bool aForcePreflight,
|
||||||
bool aIsPreflight,
|
bool aIsPreflight)
|
||||||
bool aForceHSTSPriming,
|
|
||||||
bool aMixedContentWouldBlock)
|
|
||||||
: mLoadingPrincipal(aLoadingPrincipal)
|
: mLoadingPrincipal(aLoadingPrincipal)
|
||||||
, mTriggeringPrincipal(aTriggeringPrincipal)
|
, mTriggeringPrincipal(aTriggeringPrincipal)
|
||||||
, mSecurityFlags(aSecurityFlags)
|
, mSecurityFlags(aSecurityFlags)
|
||||||
|
@ -316,8 +308,6 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
|
||||||
, mCorsUnsafeHeaders(aCorsUnsafeHeaders)
|
, mCorsUnsafeHeaders(aCorsUnsafeHeaders)
|
||||||
, mForcePreflight(aForcePreflight)
|
, mForcePreflight(aForcePreflight)
|
||||||
, mIsPreflight(aIsPreflight)
|
, mIsPreflight(aIsPreflight)
|
||||||
, mForceHSTSPriming (aForceHSTSPriming)
|
|
||||||
, mMixedContentWouldBlock(aMixedContentWouldBlock)
|
|
||||||
{
|
{
|
||||||
// Only top level TYPE_DOCUMENT loads can have a null loadingPrincipal
|
// Only top level TYPE_DOCUMENT loads can have a null loadingPrincipal
|
||||||
MOZ_ASSERT(mLoadingPrincipal || aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT);
|
MOZ_ASSERT(mLoadingPrincipal || aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT);
|
||||||
|
@ -770,34 +760,6 @@ LoadInfo::GetIsPreflight(bool* aIsPreflight)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
LoadInfo::GetForceHSTSPriming(bool* aForceHSTSPriming)
|
|
||||||
{
|
|
||||||
*aForceHSTSPriming = mForceHSTSPriming;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
LoadInfo::GetMixedContentWouldBlock(bool *aMixedContentWouldBlock)
|
|
||||||
{
|
|
||||||
*aMixedContentWouldBlock = mMixedContentWouldBlock;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LoadInfo::SetHSTSPriming(bool aMixedContentWouldBlock)
|
|
||||||
{
|
|
||||||
mForceHSTSPriming = true;
|
|
||||||
mMixedContentWouldBlock = aMixedContentWouldBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LoadInfo::ClearHSTSPriming()
|
|
||||||
{
|
|
||||||
mForceHSTSPriming = false;
|
|
||||||
mMixedContentWouldBlock = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
LoadInfo::GetTainting(uint32_t* aTaintingOut)
|
LoadInfo::GetTainting(uint32_t* aTaintingOut)
|
||||||
{
|
{
|
||||||
|
|
|
@ -104,9 +104,7 @@ private:
|
||||||
nsTArray<nsCOMPtr<nsIPrincipal>>& aRedirectChain,
|
nsTArray<nsCOMPtr<nsIPrincipal>>& aRedirectChain,
|
||||||
const nsTArray<nsCString>& aUnsafeHeaders,
|
const nsTArray<nsCString>& aUnsafeHeaders,
|
||||||
bool aForcePreflight,
|
bool aForcePreflight,
|
||||||
bool aIsPreflight,
|
bool aIsPreflight);
|
||||||
bool aForceHSTSPriming,
|
|
||||||
bool aMixedContentWouldBlock);
|
|
||||||
LoadInfo(const LoadInfo& rhs);
|
LoadInfo(const LoadInfo& rhs);
|
||||||
|
|
||||||
friend nsresult
|
friend nsresult
|
||||||
|
@ -147,9 +145,6 @@ private:
|
||||||
nsTArray<nsCString> mCorsUnsafeHeaders;
|
nsTArray<nsCString> mCorsUnsafeHeaders;
|
||||||
bool mForcePreflight;
|
bool mForcePreflight;
|
||||||
bool mIsPreflight;
|
bool mIsPreflight;
|
||||||
|
|
||||||
bool mForceHSTSPriming : 1;
|
|
||||||
bool mMixedContentWouldBlock : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
|
|
|
@ -541,32 +541,6 @@ interface nsILoadInfo : nsISupports
|
||||||
*/
|
*/
|
||||||
[infallible] readonly attribute boolean isPreflight;
|
[infallible] readonly attribute boolean isPreflight;
|
||||||
|
|
||||||
/**
|
|
||||||
* When this request would be mixed-content and we do not have an
|
|
||||||
* entry in the HSTS cache, we send an HSTS priming request to
|
|
||||||
* determine if it is ok to upgrade the request to HTTPS.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* True if this is a mixed-content load and HSTS priming request will be sent.
|
|
||||||
*/
|
|
||||||
[noscript, infallible] readonly attribute boolean forceHSTSPriming;
|
|
||||||
/**
|
|
||||||
* Carry the decision whether this load would be blocked by mixed content so
|
|
||||||
* that if HSTS priming fails, the correct decision can be made.
|
|
||||||
*/
|
|
||||||
[noscript, infallible] readonly attribute boolean mixedContentWouldBlock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark this LoadInfo as needing HSTS Priming
|
|
||||||
*
|
|
||||||
* @param wouldBlock Carry the decision of Mixed Content Blocking to be
|
|
||||||
* applied when HSTS priming is complete.
|
|
||||||
*/
|
|
||||||
[noscript, notxpcom, nostdcall]
|
|
||||||
void setHSTSPriming(in boolean mixeContentWouldBlock);
|
|
||||||
[noscript, notxpcom, nostdcall]
|
|
||||||
void clearHSTSPriming();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants reflecting the channel tainting. These are mainly defined here
|
* Constants reflecting the channel tainting. These are mainly defined here
|
||||||
* for script. Internal C++ code should use the enum defined in LoadTainting.h.
|
* for script. Internal C++ code should use the enum defined in LoadTainting.h.
|
||||||
|
|
|
@ -2339,7 +2339,7 @@ NS_ShouldSecureUpgrade(nsIURI* aURI,
|
||||||
bool isStsHost = false;
|
bool isStsHost = false;
|
||||||
uint32_t flags = aPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
|
uint32_t flags = aPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
|
||||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
|
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
|
||||||
nullptr, &isStsHost);
|
&isStsHost);
|
||||||
|
|
||||||
// if the SSS check fails, it's likely because this load is on a
|
// if the SSS check fails, it's likely because this load is on a
|
||||||
// malformed URI or something else in the setup is wrong, so any error
|
// malformed URI or something else in the setup is wrong, so any error
|
||||||
|
|
|
@ -97,15 +97,3 @@ pref("security.ssl.errorReporting.automatic", false);
|
||||||
// blacking themselves out by setting a bad pin. (60 days by default)
|
// blacking themselves out by setting a bad pin. (60 days by default)
|
||||||
// https://tools.ietf.org/html/rfc7469#section-4.1
|
// https://tools.ietf.org/html/rfc7469#section-4.1
|
||||||
pref("security.cert_pinning.max_max_age_seconds", 5184000);
|
pref("security.cert_pinning.max_max_age_seconds", 5184000);
|
||||||
|
|
||||||
// If a request is mixed-content, send an HSTS priming request to attempt to
|
|
||||||
// see if it is available over HTTPS.
|
|
||||||
pref("security.mixed_content.send_hsts_priming", true);
|
|
||||||
#ifdef RELEASE_BUILD
|
|
||||||
// Don't change the order of evaluation of mixed-content and HSTS upgrades
|
|
||||||
pref("security.mixed_content.use_hsts", false);
|
|
||||||
#else
|
|
||||||
// Change the order of evaluation so HSTS upgrades happen before
|
|
||||||
// mixed-content blocking
|
|
||||||
pref("security.mixed_content.use_hsts", true);
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -49,8 +49,6 @@ struct LoadInfoArgs
|
||||||
nsCString[] corsUnsafeHeaders;
|
nsCString[] corsUnsafeHeaders;
|
||||||
bool forcePreflight;
|
bool forcePreflight;
|
||||||
bool isPreflight;
|
bool isPreflight;
|
||||||
bool forceHSTSPriming;
|
|
||||||
bool mixedContentWouldBlock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,249 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#include "nsHttp.h"
|
|
||||||
|
|
||||||
#include "HSTSPrimerListener.h"
|
|
||||||
#include "nsIHstsPrimingCallback.h"
|
|
||||||
#include "nsIPrincipal.h"
|
|
||||||
#include "nsSecurityHeaderParser.h"
|
|
||||||
#include "nsISiteSecurityService.h"
|
|
||||||
#include "nsISocketProvider.h"
|
|
||||||
#include "nsISSLStatus.h"
|
|
||||||
#include "nsISSLStatusProvider.h"
|
|
||||||
#include "nsStreamUtils.h"
|
|
||||||
#include "nsHttpChannel.h"
|
|
||||||
#include "LoadInfo.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace net {
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(HSTSPrimingListener, nsIStreamListener,
|
|
||||||
nsIRequestObserver, nsIInterfaceRequestor)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
HSTSPrimingListener::GetInterface(const nsIID & aIID, void **aResult)
|
|
||||||
{
|
|
||||||
return QueryInterface(aIID, aResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
HSTSPrimingListener::OnStartRequest(nsIRequest *aRequest,
|
|
||||||
nsISupports *aContext)
|
|
||||||
{
|
|
||||||
nsresult rv = CheckHSTSPrimingRequestStatus(aRequest);
|
|
||||||
nsCOMPtr<nsIHstsPrimingCallback> callback(mCallback);
|
|
||||||
mCallback = nullptr;
|
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
LOG(("HSTS Priming Failed (request was not approved)"));
|
|
||||||
return callback->OnHSTSPrimingFailed(rv, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(("HSTS Priming Succeeded (request was approved)"));
|
|
||||||
return callback->OnHSTSPrimingSucceeded(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
HSTSPrimingListener::OnStopRequest(nsIRequest *aRequest,
|
|
||||||
nsISupports *aContext,
|
|
||||||
nsresult aStatus)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
HSTSPrimingListener::CheckHSTSPrimingRequestStatus(nsIRequest* aRequest)
|
|
||||||
{
|
|
||||||
nsresult status;
|
|
||||||
nsresult rv = aRequest->GetStatus(&status);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
if (NS_FAILED(status)) {
|
|
||||||
return NS_ERROR_CONTENT_BLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that things worked on a HTTP level
|
|
||||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
|
|
||||||
NS_ENSURE_STATE(httpChannel);
|
|
||||||
nsCOMPtr<nsIHttpChannelInternal> internal = do_QueryInterface(aRequest);
|
|
||||||
NS_ENSURE_STATE(internal);
|
|
||||||
|
|
||||||
bool succeedded;
|
|
||||||
rv = httpChannel->GetRequestSucceeded(&succeedded);
|
|
||||||
if (NS_FAILED(rv) || !succeedded) {
|
|
||||||
// If the request did not return a 2XX response, don't process it
|
|
||||||
return NS_ERROR_CONTENT_BLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool synthesized = false;
|
|
||||||
nsHttpChannel* rawHttpChannel = static_cast<nsHttpChannel*>(httpChannel.get());
|
|
||||||
rv = rawHttpChannel->GetResponseSynthesized(&synthesized);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
if (synthesized) {
|
|
||||||
// Don't consider synthesized responses
|
|
||||||
return NS_ERROR_CONTENT_BLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if the HSTS cache was updated
|
|
||||||
nsCOMPtr<nsISiteSecurityService> sss = do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
|
||||||
rv = httpChannel->GetURI(getter_AddRefs(uri));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
NS_ENSURE_TRUE(uri, NS_ERROR_CONTENT_BLOCKED);
|
|
||||||
|
|
||||||
bool hsts;
|
|
||||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, uri, 0, nullptr, &hsts);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (hsts) {
|
|
||||||
// An HSTS upgrade was found
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There is no HSTS upgrade available
|
|
||||||
return NS_ERROR_CONTENT_BLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** nsIStreamListener methods **/
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
HSTSPrimingListener::OnDataAvailable(nsIRequest *aRequest,
|
|
||||||
nsISupports *ctxt,
|
|
||||||
nsIInputStream *inStr,
|
|
||||||
uint64_t sourceOffset,
|
|
||||||
uint32_t count)
|
|
||||||
{
|
|
||||||
uint32_t totalRead;
|
|
||||||
return inStr->ReadSegments(NS_DiscardSegment, nullptr, count, &totalRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
nsresult
|
|
||||||
HSTSPrimingListener::StartHSTSPriming(nsIChannel* aRequestChannel,
|
|
||||||
nsIHstsPrimingCallback* aCallback)
|
|
||||||
{
|
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> finalChannelURI;
|
|
||||||
nsresult rv = NS_GetFinalChannelURI(aRequestChannel, getter_AddRefs(finalChannelURI));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
|
||||||
rv = finalChannelURI->Clone(getter_AddRefs(uri));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
rv = uri->SetScheme(NS_LITERAL_CSTRING("https"));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// check the HSTS cache
|
|
||||||
bool hsts;
|
|
||||||
bool cached;
|
|
||||||
nsCOMPtr<nsISiteSecurityService> sss = do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, uri, 0, &cached, &hsts);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (hsts) {
|
|
||||||
// already saw this host and will upgrade if allowed by preferences
|
|
||||||
return aCallback->OnHSTSPrimingSucceeded(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cached) {
|
|
||||||
// there is a non-expired entry in the cache that doesn't allow us to
|
|
||||||
// upgrade, so go ahead and fail early.
|
|
||||||
return aCallback->OnHSTSPrimingFailed(NS_ERROR_CONTENT_BLOCKED, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Either it wasn't cached or the cached result has expired. Build a
|
|
||||||
// channel for the HEAD request.
|
|
||||||
|
|
||||||
nsCOMPtr<nsILoadInfo> originalLoadInfo = aRequestChannel->GetLoadInfo();
|
|
||||||
MOZ_ASSERT(originalLoadInfo, "can not perform HSTS priming without a loadInfo");
|
|
||||||
if (!originalLoadInfo) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo = static_cast<mozilla::LoadInfo*>
|
|
||||||
(originalLoadInfo.get())->CloneForNewRequest();
|
|
||||||
|
|
||||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
|
||||||
rv = aRequestChannel->GetLoadGroup(getter_AddRefs(loadGroup));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsLoadFlags loadFlags;
|
|
||||||
rv = aRequestChannel->GetLoadFlags(&loadFlags);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
loadFlags &= HttpBaseChannel::INHIBIT_CACHING |
|
|
||||||
HttpBaseChannel::INHIBIT_PERSISTENT_CACHING |
|
|
||||||
HttpBaseChannel::LOAD_BYPASS_CACHE |
|
|
||||||
HttpBaseChannel::LOAD_FROM_CACHE |
|
|
||||||
HttpBaseChannel::VALIDATE_ALWAYS;
|
|
||||||
// Priming requests should never be intercepted by service workers and
|
|
||||||
// are always anonymous.
|
|
||||||
loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER |
|
|
||||||
nsIRequest::LOAD_ANONYMOUS;
|
|
||||||
|
|
||||||
// Create a new channel to send the priming request
|
|
||||||
nsCOMPtr<nsIChannel> primingChannel;
|
|
||||||
rv = NS_NewChannelInternal(getter_AddRefs(primingChannel),
|
|
||||||
uri,
|
|
||||||
loadInfo,
|
|
||||||
loadGroup,
|
|
||||||
nullptr, // aCallbacks are set later
|
|
||||||
loadFlags);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// Set method and headers
|
|
||||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(primingChannel);
|
|
||||||
if (!httpChannel) {
|
|
||||||
NS_ERROR("HSTSPrimingListener: Failed to QI to nsIHttpChannel!");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Currently using HEAD per the draft, but under discussion to change to GET
|
|
||||||
// with credentials so if the upgrade is approved the result is already cached.
|
|
||||||
rv = httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("HEAD"));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = httpChannel->
|
|
||||||
SetRequestHeader(NS_LITERAL_CSTRING("Upgrade-Insecure-Requests"),
|
|
||||||
NS_LITERAL_CSTRING("1"), false);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// attempt to set the class of service flags on the new channel
|
|
||||||
nsCOMPtr<nsIClassOfService> requestClass = do_QueryInterface(aRequestChannel);
|
|
||||||
if (!requestClass) {
|
|
||||||
NS_ERROR("HSTSPrimingListener: aRequestChannel is not an nsIClassOfService");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
nsCOMPtr<nsIClassOfService> primingClass = do_QueryInterface(httpChannel);
|
|
||||||
if (!primingClass) {
|
|
||||||
NS_ERROR("HSTSPrimingListener: aRequestChannel is not an nsIClassOfService");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t classFlags = 0;
|
|
||||||
rv = requestClass ->GetClassFlags(&classFlags);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
rv = primingClass->SetClassFlags(classFlags);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// Set up listener which will start the original channel
|
|
||||||
RefPtr<HSTSPrimingListener> primingListener =
|
|
||||||
new HSTSPrimingListener(aCallback);
|
|
||||||
|
|
||||||
// Start priming
|
|
||||||
rv = primingChannel->AsyncOpen2(primingListener);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace net
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,108 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#ifndef HSTSPrimingListener_h__
|
|
||||||
#define HSTSPrimingListener_h__
|
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIChannelEventSink.h"
|
|
||||||
#include "nsIInterfaceRequestor.h"
|
|
||||||
#include "nsIStreamListener.h"
|
|
||||||
#include "nsIThreadRetargetableStreamListener.h"
|
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
|
||||||
|
|
||||||
class nsIPrincipal;
|
|
||||||
class nsINetworkInterceptController;
|
|
||||||
class nsIHstsPrimingCallback;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace net {
|
|
||||||
|
|
||||||
class HttpChannelParent;
|
|
||||||
class nsHttpChannel;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* How often do we get back an HSTS priming result which upgrades the connection to HTTPS?
|
|
||||||
*/
|
|
||||||
enum HSTSPrimingResult {
|
|
||||||
// This site has been seen before and won't be upgraded
|
|
||||||
eHSTS_PRIMING_CACHED_NO_UPGRADE = 0,
|
|
||||||
// This site has been seen before and will be upgraded
|
|
||||||
eHSTS_PRIMING_CACHED_DO_UPGRADE = 1,
|
|
||||||
// This site has been seen before and will be blocked
|
|
||||||
eHSTS_PRIMING_CACHED_BLOCK = 2,
|
|
||||||
// The request was already upgraded, probably through
|
|
||||||
// upgrade-insecure-requests
|
|
||||||
eHSTS_PRIMING_ALREADY_UPGRADED = 3,
|
|
||||||
// HSTS priming is successful and the connection will be upgraded to HTTPS
|
|
||||||
eHSTS_PRIMING_SUCCEEDED = 4,
|
|
||||||
// When priming succeeds, but preferences require preservation of the order
|
|
||||||
// of mixed-content and hsts, and mixed-content blocks the load
|
|
||||||
eHSTS_PRIMING_SUCCEEDED_BLOCK = 5,
|
|
||||||
// When priming succeeds, but preferences require preservation of the order
|
|
||||||
// of mixed-content and hsts, and mixed-content allows the load over http
|
|
||||||
eHSTS_PRIMING_SUCCEEDED_HTTP = 6,
|
|
||||||
// HSTS priming failed, and the load is blocked by mixed-content
|
|
||||||
eHSTS_PRIMING_FAILED_BLOCK = 7,
|
|
||||||
// HSTS priming failed, and the load is allowed by mixed-content
|
|
||||||
eHSTS_PRIMING_FAILED_ACCEPT = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Class used as streamlistener and notification callback when
|
|
||||||
// doing the HEAD request for an HSTS Priming check. Needs to be an
|
|
||||||
// nsIStreamListener in order to receive events from AsyncOpen2
|
|
||||||
class HSTSPrimingListener final : public nsIStreamListener,
|
|
||||||
public nsIInterfaceRequestor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit HSTSPrimingListener(nsIHstsPrimingCallback* aCallback)
|
|
||||||
: mCallback(aCallback)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSISTREAMLISTENER
|
|
||||||
NS_DECL_NSIREQUESTOBSERVER
|
|
||||||
NS_DECL_NSIINTERFACEREQUESTOR
|
|
||||||
|
|
||||||
private:
|
|
||||||
~HSTSPrimingListener() {}
|
|
||||||
|
|
||||||
// Only nsHttpChannel can invoke HSTS priming
|
|
||||||
friend class mozilla::net::nsHttpChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the HSTS priming request. This will send an anonymous HEAD request to
|
|
||||||
* the URI aRequestChannel is attempting to load. On success, the new HSTS
|
|
||||||
* priming channel is allocated in aHSTSPrimingChannel.
|
|
||||||
*
|
|
||||||
* @param aRequestChannel the reference channel used to initialze the HSTS
|
|
||||||
* priming channel
|
|
||||||
* @param aCallback the callback stored to handle the results of HSTS priming.
|
|
||||||
* @param aHSTSPrimingChannel if the new HSTS priming channel is allocated
|
|
||||||
* successfully, it will be placed here.
|
|
||||||
*/
|
|
||||||
static nsresult StartHSTSPriming(nsIChannel* aRequestChannel,
|
|
||||||
nsIHstsPrimingCallback* aCallback);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a request, return NS_OK if it has resulted in a cached HSTS update.
|
|
||||||
* We don't need to check for the header as that has already been done for us.
|
|
||||||
*/
|
|
||||||
nsresult CheckHSTSPrimingRequestStatus(nsIRequest* aRequest);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the nsIHttpChannel to notify with the result of HSTS priming.
|
|
||||||
*/
|
|
||||||
nsCOMPtr<nsIHstsPrimingCallback> mCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}} // mozilla::net
|
|
||||||
|
|
||||||
#endif // HSTSPrimingListener_h__
|
|
|
@ -5,7 +5,6 @@
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
'nsIHstsPrimingCallback.idl',
|
|
||||||
'nsIHttpActivityObserver.idl',
|
'nsIHttpActivityObserver.idl',
|
||||||
'nsIHttpAuthenticableChannel.idl',
|
'nsIHttpAuthenticableChannel.idl',
|
||||||
'nsIHttpAuthenticator.idl',
|
'nsIHttpAuthenticator.idl',
|
||||||
|
@ -55,7 +54,6 @@ SOURCES += [
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'CacheControlParser.cpp',
|
'CacheControlParser.cpp',
|
||||||
'ConnectionDiagnostics.cpp',
|
'ConnectionDiagnostics.cpp',
|
||||||
'HSTSPrimerListener.cpp',
|
|
||||||
'Http2Compression.cpp',
|
'Http2Compression.cpp',
|
||||||
'Http2Push.cpp',
|
'Http2Push.cpp',
|
||||||
'Http2Session.cpp',
|
'Http2Session.cpp',
|
||||||
|
|
|
@ -98,8 +98,6 @@
|
||||||
#include "nsISocketProvider.h"
|
#include "nsISocketProvider.h"
|
||||||
#include "mozilla/net/Predictor.h"
|
#include "mozilla/net/Predictor.h"
|
||||||
#include "CacheControlParser.h"
|
#include "CacheControlParser.h"
|
||||||
#include "nsMixedContentBlocker.h"
|
|
||||||
#include "HSTSPrimerListener.h"
|
|
||||||
|
|
||||||
namespace mozilla { namespace net {
|
namespace mozilla { namespace net {
|
||||||
|
|
||||||
|
@ -407,50 +405,12 @@ nsHttpChannel::Connect()
|
||||||
// otherwise, let's just proceed without using the cache.
|
// otherwise, let's just proceed without using the cache.
|
||||||
}
|
}
|
||||||
|
|
||||||
return TryHSTSPriming();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsHttpChannel::TryHSTSPriming()
|
|
||||||
{
|
|
||||||
if (mLoadInfo) {
|
|
||||||
// HSTS priming requires the LoadInfo provided with AsyncOpen2
|
|
||||||
bool requireHSTSPriming =
|
|
||||||
mLoadInfo->GetForceHSTSPriming();
|
|
||||||
|
|
||||||
if (requireHSTSPriming &&
|
|
||||||
nsMixedContentBlocker::sSendHSTSPriming &&
|
|
||||||
mInterceptCache == DO_NOT_INTERCEPT) {
|
|
||||||
bool isHttpsScheme;
|
|
||||||
nsresult rv = mURI->SchemeIs("https", &isHttpsScheme);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
if (!isHttpsScheme) {
|
|
||||||
rv = HSTSPrimingListener::StartHSTSPriming(this, this);
|
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
CloseCacheEntry(false);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The request was already upgraded, for example by
|
|
||||||
// upgrade-insecure-requests or a prior successful priming request
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT,
|
|
||||||
HSTSPrimingResult::eHSTS_PRIMING_ALREADY_UPGRADED);
|
|
||||||
mLoadInfo->ClearHSTSPriming();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ContinueConnect();
|
return ContinueConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHttpChannel::ContinueConnect()
|
nsHttpChannel::ContinueConnect()
|
||||||
{
|
{
|
||||||
// If we have had HSTS priming, we need to reevaluate whether we need
|
|
||||||
// a CORS preflight. Bug: 1272440
|
|
||||||
// If we need to start a CORS preflight, do it now!
|
// If we need to start a CORS preflight, do it now!
|
||||||
// Note that it is important to do this before the early returns below.
|
// Note that it is important to do this before the early returns below.
|
||||||
if (!mIsCorsPreflightDone && mRequireCORSPreflight &&
|
if (!mIsCorsPreflightDone && mRequireCORSPreflight &&
|
||||||
|
@ -4058,7 +4018,7 @@ nsHttpChannel::OnCacheEntryAvailableInternal(nsICacheEntry *entry,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TryHSTSPriming();
|
return ContinueConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -5398,7 +5358,6 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIDNSListener)
|
NS_INTERFACE_MAP_ENTRY(nsIDNSListener)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsICorsPreflightCallback)
|
NS_INTERFACE_MAP_ENTRY(nsICorsPreflightCallback)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIHstsPrimingCallback)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIChannelWithDivertableParentListener)
|
NS_INTERFACE_MAP_ENTRY(nsIChannelWithDivertableParentListener)
|
||||||
// we have no macro that covers this case.
|
// we have no macro that covers this case.
|
||||||
if (aIID.Equals(NS_GET_IID(nsHttpChannel)) ) {
|
if (aIID.Equals(NS_GET_IID(nsHttpChannel)) ) {
|
||||||
|
@ -7719,103 +7678,6 @@ nsHttpChannel::OnPreflightFailed(nsresult aError)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// nsIHstsPrimingCallback functions
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/*
|
|
||||||
* May be invoked synchronously if HSTS priming has already been performed
|
|
||||||
* for the host.
|
|
||||||
*/
|
|
||||||
nsresult
|
|
||||||
nsHttpChannel::OnHSTSPrimingSucceeded(bool aCached)
|
|
||||||
{
|
|
||||||
if (nsMixedContentBlocker::sUseHSTS) {
|
|
||||||
// redirect the channel to HTTPS if the pref
|
|
||||||
// "security.mixed_content.use_hsts" is true
|
|
||||||
LOG(("HSTS Priming succeeded, redirecting to HTTPS [this=%p]", this));
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT,
|
|
||||||
(aCached) ? HSTSPrimingResult::eHSTS_PRIMING_CACHED_DO_UPGRADE :
|
|
||||||
HSTSPrimingResult::eHSTS_PRIMING_SUCCEEDED);
|
|
||||||
return AsyncCall(&nsHttpChannel::HandleAsyncRedirectChannelToHttps);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If "security.mixed_content.use_hsts" is false, record the result of
|
|
||||||
// HSTS priming and block or proceed with the load as required by
|
|
||||||
// mixed-content blocking
|
|
||||||
bool wouldBlock = mLoadInfo->GetMixedContentWouldBlock();
|
|
||||||
|
|
||||||
// preserve the mixed-content-before-hsts order and block if required
|
|
||||||
if (wouldBlock) {
|
|
||||||
LOG(("HSTS Priming succeeded, blocking for mixed-content [this=%p]",
|
|
||||||
this));
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT,
|
|
||||||
HSTSPrimingResult::eHSTS_PRIMING_SUCCEEDED_BLOCK);
|
|
||||||
CloseCacheEntry(false);
|
|
||||||
return AsyncAbort(NS_ERROR_CONTENT_BLOCKED);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(("HSTS Priming succeeded, loading insecure: [this=%p]", this));
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT,
|
|
||||||
HSTSPrimingResult::eHSTS_PRIMING_SUCCEEDED_HTTP);
|
|
||||||
|
|
||||||
nsresult rv = ContinueConnect();
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
CloseCacheEntry(false);
|
|
||||||
return AsyncAbort(rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* May be invoked synchronously if HSTS priming has already been performed
|
|
||||||
* for the host.
|
|
||||||
*/
|
|
||||||
nsresult
|
|
||||||
nsHttpChannel::OnHSTSPrimingFailed(nsresult aError, bool aCached)
|
|
||||||
{
|
|
||||||
bool wouldBlock = mLoadInfo->GetMixedContentWouldBlock();
|
|
||||||
|
|
||||||
LOG(("HSTS Priming Failed [this=%p], %s the load", this,
|
|
||||||
(wouldBlock) ? "blocking" : "allowing"));
|
|
||||||
if (aCached) {
|
|
||||||
// Between the time we marked for priming and started the priming request,
|
|
||||||
// the host was found to not allow the upgrade, probably from another
|
|
||||||
// priming request.
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT,
|
|
||||||
(wouldBlock) ? HSTSPrimingResult::eHSTS_PRIMING_CACHED_BLOCK :
|
|
||||||
HSTSPrimingResult::eHSTS_PRIMING_CACHED_NO_UPGRADE);
|
|
||||||
} else {
|
|
||||||
// A priming request was sent, and no HSTS header was found that allows
|
|
||||||
// the upgrade.
|
|
||||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_RESULT,
|
|
||||||
(wouldBlock) ? HSTSPrimingResult::eHSTS_PRIMING_FAILED_BLOCK :
|
|
||||||
HSTSPrimingResult::eHSTS_PRIMING_FAILED_ACCEPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't visit again for at least one day
|
|
||||||
nsISiteSecurityService* sss = gHttpHandler->GetSSService();
|
|
||||||
NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
nsresult rv = sss->CacheNegativeHSTSResult(mURI, 24 * 60 * 60);
|
|
||||||
NS_WARN_IF(NS_FAILED(rv));
|
|
||||||
|
|
||||||
// If we would block, go ahead and abort with the error provided
|
|
||||||
if (wouldBlock) {
|
|
||||||
CloseCacheEntry(false);
|
|
||||||
return AsyncAbort(aError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we can continue the load and the UI has been updated as mixed content
|
|
||||||
rv = ContinueConnect();
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
CloseCacheEntry(false);
|
|
||||||
return AsyncAbort(rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// AChannelHasDivertableParentChannelAsListener internal functions
|
// AChannelHasDivertableParentChannelAsListener internal functions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "nsIStreamListener.h"
|
#include "nsIStreamListener.h"
|
||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsICorsPreflightCallback.h"
|
#include "nsICorsPreflightCallback.h"
|
||||||
#include "nsIHstsPrimingCallback.h"
|
|
||||||
|
|
||||||
class nsDNSPrefetch;
|
class nsDNSPrefetch;
|
||||||
class nsICancelable;
|
class nsICancelable;
|
||||||
|
@ -75,7 +74,6 @@ class nsHttpChannel final : public HttpBaseChannel
|
||||||
, public nsSupportsWeakReference
|
, public nsSupportsWeakReference
|
||||||
, public nsICorsPreflightCallback
|
, public nsICorsPreflightCallback
|
||||||
, public nsIChannelWithDivertableParentListener
|
, public nsIChannelWithDivertableParentListener
|
||||||
, public nsIHstsPrimingCallback
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
@ -91,7 +89,6 @@ public:
|
||||||
NS_DECL_NSIAPPLICATIONCACHECONTAINER
|
NS_DECL_NSIAPPLICATIONCACHECONTAINER
|
||||||
NS_DECL_NSIAPPLICATIONCACHECHANNEL
|
NS_DECL_NSIAPPLICATIONCACHECHANNEL
|
||||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||||
NS_DECL_NSIHSTSPRIMINGCALLBACK
|
|
||||||
NS_DECL_NSITHREADRETARGETABLEREQUEST
|
NS_DECL_NSITHREADRETARGETABLEREQUEST
|
||||||
NS_DECL_NSIDNSLISTENER
|
NS_DECL_NSIDNSLISTENER
|
||||||
NS_DECL_NSICHANNELWITHDIVERTABLEPARENTLISTENER
|
NS_DECL_NSICHANNELWITHDIVERTABLEPARENTLISTENER
|
||||||
|
@ -206,9 +203,6 @@ public: /* internal necko use only */
|
||||||
nsresult OpenCacheEntry(bool usingSSL);
|
nsresult OpenCacheEntry(bool usingSSL);
|
||||||
nsresult ContinueConnect();
|
nsresult ContinueConnect();
|
||||||
|
|
||||||
// If the load is mixed-content, build and send an HSTS priming request.
|
|
||||||
nsresult TryHSTSPriming();
|
|
||||||
|
|
||||||
nsresult StartRedirectChannelToURI(nsIURI *, uint32_t);
|
nsresult StartRedirectChannelToURI(nsIURI *, uint32_t);
|
||||||
|
|
||||||
// This allows cache entry to be marked as foreign even after channel itself
|
// This allows cache entry to be marked as foreign even after channel itself
|
||||||
|
|
|
@ -2244,8 +2244,7 @@ nsHttpHandler::SpeculativeConnectInternal(nsIURI *aURI,
|
||||||
flags |= nsISocketProvider::NO_PERMANENT_STORAGE;
|
flags |= nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||||
nsCOMPtr<nsIURI> clone;
|
nsCOMPtr<nsIURI> clone;
|
||||||
if (NS_SUCCEEDED(sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS,
|
if (NS_SUCCEEDED(sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS,
|
||||||
aURI, flags, nullptr, &isStsHost)) &&
|
aURI, flags, &isStsHost)) && isStsHost) {
|
||||||
isStsHost) {
|
|
||||||
if (NS_SUCCEEDED(NS_GetSecureUpgradedURI(aURI,
|
if (NS_SUCCEEDED(NS_GetSecureUpgradedURI(aURI,
|
||||||
getter_AddRefs(clone)))) {
|
getter_AddRefs(clone)))) {
|
||||||
aURI = clone.get();
|
aURI = clone.get();
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HSTS priming attempts to prevent mixed-content by looking for the
|
|
||||||
* Strict-Transport-Security header as a signal from the server that it is
|
|
||||||
* safe to upgrade HTTP to HTTPS.
|
|
||||||
*
|
|
||||||
* Since mixed-content blocking happens very early in the process in AsyncOpen2,
|
|
||||||
* the status of mixed-content blocking is stored in the LoadInfo and then used
|
|
||||||
* to determine whether to send a priming request or not.
|
|
||||||
*
|
|
||||||
* This interface is implemented by nsHttpChannel so that it can receive the
|
|
||||||
* result of HSTS priming.
|
|
||||||
*/
|
|
||||||
[builtinclass, uuid(eca6daca-3f2a-4a2a-b3bf-9f24f79bc999)]
|
|
||||||
interface nsIHstsPrimingCallback : nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* HSTS priming has succeeded with an STS header, and the site asserts it is
|
|
||||||
* safe to upgrade the request from HTTP to HTTPS. The request may still be
|
|
||||||
* blocked based on the user's preferences.
|
|
||||||
*
|
|
||||||
* May be invoked synchronously if HSTS priming has already been performed
|
|
||||||
* for the host.
|
|
||||||
*
|
|
||||||
* @param aCached whether the result was already in the HSTS cache
|
|
||||||
*/
|
|
||||||
[noscript, nostdcall]
|
|
||||||
void onHSTSPrimingSucceeded(in bool aCached);
|
|
||||||
/**
|
|
||||||
* HSTS priming has seen no STS header, the request itself has failed,
|
|
||||||
* or some other failure which does not constitute a positive signal that the
|
|
||||||
* site can be upgraded safely to HTTPS. The request may still be allowed
|
|
||||||
* based on the user's preferences.
|
|
||||||
*
|
|
||||||
* May be invoked synchronously if HSTS priming has already been performed
|
|
||||||
* for the host.
|
|
||||||
*
|
|
||||||
* param aError The error which caused this failure, or NS_ERROR_CONTENT_BLOCKED
|
|
||||||
* @param aCached whether the result was already in the HSTS cache
|
|
||||||
*/
|
|
||||||
[noscript, nostdcall]
|
|
||||||
void onHSTSPrimingFailed(in nsresult aError, in bool aCached);
|
|
||||||
};
|
|
|
@ -506,7 +506,6 @@ CertErrorRunnable::CheckCertOverrides()
|
||||||
nsresult nsrv = sss->IsSecureHost(nsISiteSecurityService::HEADER_HSTS,
|
nsresult nsrv = sss->IsSecureHost(nsISiteSecurityService::HEADER_HSTS,
|
||||||
mInfoObject->GetHostNameRaw(),
|
mInfoObject->GetHostNameRaw(),
|
||||||
mProviderFlags,
|
mProviderFlags,
|
||||||
nullptr,
|
|
||||||
&strictTransportSecurityEnabled);
|
&strictTransportSecurityEnabled);
|
||||||
if (NS_FAILED(nsrv)) {
|
if (NS_FAILED(nsrv)) {
|
||||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||||
|
@ -517,7 +516,6 @@ CertErrorRunnable::CheckCertOverrides()
|
||||||
nsrv = sss->IsSecureHost(nsISiteSecurityService::HEADER_HPKP,
|
nsrv = sss->IsSecureHost(nsISiteSecurityService::HEADER_HPKP,
|
||||||
mInfoObject->GetHostNameRaw(),
|
mInfoObject->GetHostNameRaw(),
|
||||||
mProviderFlags,
|
mProviderFlags,
|
||||||
nullptr,
|
|
||||||
&hasPinningInformation);
|
&hasPinningInformation);
|
||||||
if (NS_FAILED(nsrv)) {
|
if (NS_FAILED(nsrv)) {
|
||||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||||
|
|
|
@ -115,13 +115,10 @@ interface nsISiteSecurityService : nsISupports
|
||||||
* @param aHost the hostname (punycode) to query for state.
|
* @param aHost the hostname (punycode) to query for state.
|
||||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||||
* NO_PERMANENT_STORAGE
|
* NO_PERMANENT_STORAGE
|
||||||
* @param aCached true if we have cached information regarding whether or not
|
|
||||||
* the host is HSTS, false otherwise.
|
|
||||||
*/
|
*/
|
||||||
boolean isSecureHost(in uint32_t aType,
|
boolean isSecureHost(in uint32_t aType,
|
||||||
in string aHost,
|
in string aHost,
|
||||||
in uint32_t aFlags,
|
in uint32_t aFlags);
|
||||||
[optional] out boolean aCached);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether or not the URI's hostname has a given security state set.
|
* Checks whether or not the URI's hostname has a given security state set.
|
||||||
|
@ -136,11 +133,8 @@ interface nsISiteSecurityService : nsISupports
|
||||||
* @param aURI the URI to query for STS state.
|
* @param aURI the URI to query for STS state.
|
||||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||||
* NO_PERMANENT_STORAGE
|
* NO_PERMANENT_STORAGE
|
||||||
* @param aCached true if we have cached information regarding whether or not
|
|
||||||
* the host is HSTS, false otherwise.
|
|
||||||
*/
|
*/
|
||||||
boolean isSecureURI(in uint32_t aType, in nsIURI aURI, in uint32_t aFlags,
|
boolean isSecureURI(in uint32_t aType, in nsIURI aURI, in uint32_t aFlags);
|
||||||
[optional] out boolean aCached);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all security state by resetting to factory-original settings.
|
* Removes all security state by resetting to factory-original settings.
|
||||||
|
@ -180,14 +174,6 @@ interface nsISiteSecurityService : nsISupports
|
||||||
in unsigned long aMaxAge, in unsigned long aPinCount,
|
in unsigned long aMaxAge, in unsigned long aPinCount,
|
||||||
[array, size_is(aPinCount)] in string aSha256Pins);
|
[array, size_is(aPinCount)] in string aSha256Pins);
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark a host as declining to provide a given security state so that features
|
|
||||||
* such as HSTS priming will not flood a server with requests.
|
|
||||||
*
|
|
||||||
* @param aHost the hostname (punycode) that this applies to
|
|
||||||
* @param aMaxAge lifetime (in seconds) of this negative cache
|
|
||||||
*/
|
|
||||||
[noscript] void cacheNegativeHSTSResult(in nsIURI aURI, in unsigned long long aMaxAge);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
|
|
|
@ -314,8 +314,7 @@ nsSiteSecurityService::SetHSTSState(uint32_t aType,
|
||||||
nsIURI* aSourceURI,
|
nsIURI* aSourceURI,
|
||||||
int64_t maxage,
|
int64_t maxage,
|
||||||
bool includeSubdomains,
|
bool includeSubdomains,
|
||||||
uint32_t flags,
|
uint32_t flags)
|
||||||
SecurityPropertyState aHSTSState)
|
|
||||||
{
|
{
|
||||||
// If max-age is zero, that's an indication to immediately remove the
|
// If max-age is zero, that's an indication to immediately remove the
|
||||||
// security state, so here's a shortcut.
|
// security state, so here's a shortcut.
|
||||||
|
@ -323,12 +322,8 @@ nsSiteSecurityService::SetHSTSState(uint32_t aType,
|
||||||
return RemoveState(aType, aSourceURI, flags);
|
return RemoveState(aType, aSourceURI, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT((aHSTSState == SecurityPropertySet
|
|
||||||
|| aHSTSState == SecurityPropertyNegative),
|
|
||||||
"HSTS State must be SecurityPropertySet or SecurityPropertyNegative");
|
|
||||||
|
|
||||||
int64_t expiretime = ExpireTimeFromMaxAge(maxage);
|
int64_t expiretime = ExpireTimeFromMaxAge(maxage);
|
||||||
SiteHSTSState siteState(expiretime, aHSTSState, includeSubdomains);
|
SiteHSTSState siteState(expiretime, SecurityPropertySet, includeSubdomains);
|
||||||
nsAutoCString stateString;
|
nsAutoCString stateString;
|
||||||
siteState.ToString(stateString);
|
siteState.ToString(stateString);
|
||||||
nsAutoCString hostname;
|
nsAutoCString hostname;
|
||||||
|
@ -347,14 +342,6 @@ nsSiteSecurityService::SetHSTSState(uint32_t aType,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsSiteSecurityService::CacheNegativeHSTSResult(nsIURI* aSourceURI,
|
|
||||||
uint64_t aMaxAge)
|
|
||||||
{
|
|
||||||
return SetHSTSState(nsISiteSecurityService::HEADER_HSTS, aSourceURI,
|
|
||||||
aMaxAge, false, 0, SecurityPropertyNegative);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSiteSecurityService::RemoveState(uint32_t aType, nsIURI* aURI,
|
nsSiteSecurityService::RemoveState(uint32_t aType, nsIURI* aURI,
|
||||||
uint32_t aFlags)
|
uint32_t aFlags)
|
||||||
|
@ -877,7 +864,7 @@ nsSiteSecurityService::ProcessSTSHeader(nsIURI* aSourceURI,
|
||||||
|
|
||||||
// record the successfully parsed header data.
|
// record the successfully parsed header data.
|
||||||
nsresult rv = SetHSTSState(aType, aSourceURI, maxAge, foundIncludeSubdomains,
|
nsresult rv = SetHSTSState(aType, aSourceURI, maxAge, foundIncludeSubdomains,
|
||||||
aFlags, SecurityPropertySet);
|
aFlags);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
SSSLOG(("SSS: failed to set STS state"));
|
SSSLOG(("SSS: failed to set STS state"));
|
||||||
if (aFailureResult) {
|
if (aFailureResult) {
|
||||||
|
@ -901,8 +888,7 @@ nsSiteSecurityService::ProcessSTSHeader(nsIURI* aSourceURI,
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
|
nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
|
||||||
uint32_t aFlags, bool* aCached,
|
uint32_t aFlags, bool* aResult)
|
||||||
bool* aResult)
|
|
||||||
{
|
{
|
||||||
// Child processes are not allowed direct access to this.
|
// Child processes are not allowed direct access to this.
|
||||||
if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
|
if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
|
||||||
|
@ -926,7 +912,7 @@ nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return IsSecureHost(aType, hostname.get(), aFlags, aCached, aResult);
|
return IsSecureHost(aType, hostname.get(), aFlags, aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
int STSPreloadCompare(const void *key, const void *entry)
|
int STSPreloadCompare(const void *key, const void *entry)
|
||||||
|
@ -956,8 +942,7 @@ nsSiteSecurityService::GetPreloadListEntry(const char *aHost)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
||||||
uint32_t aFlags, bool* aCached,
|
uint32_t aFlags, bool* aResult)
|
||||||
bool* aResult)
|
|
||||||
{
|
{
|
||||||
// Child processes are not allowed direct access to this.
|
// Child processes are not allowed direct access to this.
|
||||||
if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
|
if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
|
||||||
|
@ -974,9 +959,6 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
||||||
|
|
||||||
// set default in case if we can't find any STS information
|
// set default in case if we can't find any STS information
|
||||||
*aResult = false;
|
*aResult = false;
|
||||||
if (aCached) {
|
|
||||||
*aCached = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* An IP address never qualifies as a secure URI. */
|
/* An IP address never qualifies as a secure URI. */
|
||||||
if (HostIsIPAddress(aHost)) {
|
if (HostIsIPAddress(aHost)) {
|
||||||
|
@ -1002,9 +984,6 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
||||||
nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHost));
|
nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHost));
|
||||||
if (host.EqualsLiteral("chart.apis.google.com") ||
|
if (host.EqualsLiteral("chart.apis.google.com") ||
|
||||||
StringEndsWith(host, NS_LITERAL_CSTRING(".chart.apis.google.com"))) {
|
StringEndsWith(host, NS_LITERAL_CSTRING(".chart.apis.google.com"))) {
|
||||||
if (aCached) {
|
|
||||||
*aCached = true;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,17 +1007,9 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
||||||
if (siteState.mHSTSState != SecurityPropertyUnset) {
|
if (siteState.mHSTSState != SecurityPropertyUnset) {
|
||||||
SSSLOG(("Found entry for %s", host.get()));
|
SSSLOG(("Found entry for %s", host.get()));
|
||||||
bool expired = siteState.IsExpired(aType);
|
bool expired = siteState.IsExpired(aType);
|
||||||
if (!expired) {
|
if (!expired && siteState.mHSTSState == SecurityPropertySet) {
|
||||||
if (aCached) {
|
*aResult = true;
|
||||||
*aCached = true;
|
return NS_OK;
|
||||||
}
|
|
||||||
if (siteState.mHSTSState == SecurityPropertySet) {
|
|
||||||
*aResult = true;
|
|
||||||
return NS_OK;
|
|
||||||
} else if (siteState.mHSTSState == SecurityPropertyNegative) {
|
|
||||||
*aResult = false;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the entry is expired and not in the preload list, we can remove it.
|
// If the entry is expired and not in the preload list, we can remove it.
|
||||||
|
@ -1051,9 +1022,6 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
||||||
else if (GetPreloadListEntry(host.get())) {
|
else if (GetPreloadListEntry(host.get())) {
|
||||||
SSSLOG(("%s is a preloaded STS host", host.get()));
|
SSSLOG(("%s is a preloaded STS host", host.get()));
|
||||||
*aResult = true;
|
*aResult = true;
|
||||||
if (aCached) {
|
|
||||||
*aCached = true;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,17 +1054,9 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
||||||
if (siteState.mHSTSState != SecurityPropertyUnset) {
|
if (siteState.mHSTSState != SecurityPropertyUnset) {
|
||||||
SSSLOG(("Found entry for %s", subdomain));
|
SSSLOG(("Found entry for %s", subdomain));
|
||||||
bool expired = siteState.IsExpired(aType);
|
bool expired = siteState.IsExpired(aType);
|
||||||
if (!expired) {
|
if (!expired && siteState.mHSTSState == SecurityPropertySet) {
|
||||||
if (aCached) {
|
*aResult = siteState.mHSTSIncludeSubdomains;
|
||||||
*aCached = true;
|
break;
|
||||||
}
|
|
||||||
if (siteState.mHSTSState == SecurityPropertySet) {
|
|
||||||
*aResult = siteState.mHSTSIncludeSubdomains;
|
|
||||||
break;
|
|
||||||
} else if (siteState.mHSTSState == SecurityPropertyNegative) {
|
|
||||||
*aResult = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the entry is expired and not in the preload list, we can remove it.
|
// If the entry is expired and not in the preload list, we can remove it.
|
||||||
|
@ -1110,9 +1070,6 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
|
||||||
if (preload->mIncludeSubdomains) {
|
if (preload->mIncludeSubdomains) {
|
||||||
SSSLOG(("%s is a preloaded STS host", subdomain));
|
SSSLOG(("%s is a preloaded STS host", subdomain));
|
||||||
*aResult = true;
|
*aResult = true;
|
||||||
if (aCached) {
|
|
||||||
*aCached = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,7 @@ class nsISSLStatus;
|
||||||
enum SecurityPropertyState {
|
enum SecurityPropertyState {
|
||||||
SecurityPropertyUnset = 0,
|
SecurityPropertyUnset = 0,
|
||||||
SecurityPropertySet = 1,
|
SecurityPropertySet = 1,
|
||||||
SecurityPropertyKnockout = 2,
|
SecurityPropertyKnockout = 2
|
||||||
SecurityPropertyNegative = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,8 +128,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
nsresult GetHost(nsIURI *aURI, nsACString &aResult);
|
nsresult GetHost(nsIURI *aURI, nsACString &aResult);
|
||||||
nsresult SetHSTSState(uint32_t aType, nsIURI* aSourceURI, int64_t maxage,
|
nsresult SetHSTSState(uint32_t aType, nsIURI* aSourceURI, int64_t maxage,
|
||||||
bool includeSubdomains, uint32_t flags,
|
bool includeSubdomains, uint32_t flags);
|
||||||
SecurityPropertyState aHSTSState);
|
|
||||||
nsresult ProcessHeaderInternal(uint32_t aType, nsIURI* aSourceURI,
|
nsresult ProcessHeaderInternal(uint32_t aType, nsIURI* aSourceURI,
|
||||||
const char* aHeader, nsISSLStatus* aSSLStatus,
|
const char* aHeader, nsISSLStatus* aSSLStatus,
|
||||||
uint32_t aFlags, uint64_t* aMaxAge,
|
uint32_t aFlags, uint64_t* aMaxAge,
|
||||||
|
|
|
@ -563,7 +563,6 @@ SpecialPowersObserverAPI.prototype = {
|
||||||
let sss = Cc["@mozilla.org/ssservice;1"].
|
let sss = Cc["@mozilla.org/ssservice;1"].
|
||||||
getService(Ci.nsISiteSecurityService);
|
getService(Ci.nsISiteSecurityService);
|
||||||
sss.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, flags);
|
sss.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, flags);
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case "SPLoadExtension": {
|
case "SPLoadExtension": {
|
||||||
|
|
|
@ -7316,22 +7316,6 @@
|
||||||
"n_values": 10,
|
"n_values": 10,
|
||||||
"description": "How often would blocked mixed content be allowed if HSTS upgrades were allowed? 0=display/no-HSTS, 1=display/HSTS, 2=active/no-HSTS, 3=active/HSTS"
|
"description": "How often would blocked mixed content be allowed if HSTS upgrades were allowed? 0=display/no-HSTS, 1=display/HSTS, 2=active/no-HSTS, 3=active/HSTS"
|
||||||
},
|
},
|
||||||
"MIXED_CONTENT_HSTS_PRIMING": {
|
|
||||||
"alert_emails": ["seceng@mozilla.org"],
|
|
||||||
"bug_numbers": [1246540],
|
|
||||||
"expires_in_version": "60",
|
|
||||||
"kind": "enumerated",
|
|
||||||
"n_values": 16,
|
|
||||||
"description": "How often would blocked mixed content be allowed if HSTS upgrades were allowed, including how often would we send an HSTS priming request? 0=display/no-HSTS, 1=display/HSTS, 2=active/no-HSTS, 3=active/HSTS, 4=display/no-HSTS-priming, 5=display/do-HSTS-priming, 6=active/no-HSTS-priming, 7=active/do-HSTS-priming"
|
|
||||||
},
|
|
||||||
"MIXED_CONTENT_HSTS_PRIMING_RESULT": {
|
|
||||||
"alert_emails": ["seceng@mozilla.org"],
|
|
||||||
"bug_numbers": [1246540],
|
|
||||||
"expires_in_version": "60",
|
|
||||||
"kind": "enumerated",
|
|
||||||
"n_values": 16,
|
|
||||||
"description": "How often do we get back an HSTS priming result which upgrades the connection to HTTPS? 0=cached (no upgrade), 1=cached (do upgrade), 2=cached (blocked), 3=already upgraded, 4=priming succeeded, 5=priming succeeded (block due to pref), 6=priming succeeded (no upgrade due to pref), 7=priming failed (block), 8=priming failed (accept)"
|
|
||||||
},
|
|
||||||
"MIXED_CONTENT_OBJECT_SUBREQUEST": {
|
"MIXED_CONTENT_OBJECT_SUBREQUEST": {
|
||||||
"alert_emails": ["seceng@mozilla.org"],
|
"alert_emails": ["seceng@mozilla.org"],
|
||||||
"bug_numbers": [1244116],
|
"bug_numbers": [1244116],
|
||||||
|
|
Загрузка…
Ссылка в новой задаче