Bug 1235572 - Enforce SRI if content signature is enforced r?francois
* * *
[mq]: sri_fix
MozReview-Commit-ID: 8vY9J4j3Eog
* * *
[mq]: loadInfo
MozReview-Commit-ID: EZ8BUfCOXO6
* * *
[mq]: add-logs
MozReview-Commit-ID: 1jeyTq9nvlW
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -1408,30 +1408,39 @@ nsScriptLoader::OnStreamComplete(nsIIncr
nsresult aSRIStatus,
mozilla::Vector<char16_t> &aString,
mozilla::dom::SRICheckDataVerifier* aSRIDataVerifier)
{
nsScriptLoadRequest* request = static_cast<nsScriptLoadRequest*>(aContext);
NS_ASSERTION(request, "null request in stream complete handler");
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
+ nsCOMPtr<nsIRequest> channelRequest;
+ aLoader->GetRequest(getter_AddRefs(channelRequest));
+ nsCOMPtr<nsIChannel> channel;
+ channel = do_QueryInterface(channelRequest);
+
nsresult rv = NS_OK;
if (!request->mIntegrity.IsEmpty() &&
NS_SUCCEEDED((rv = aSRIStatus))) {
MOZ_ASSERT(aSRIDataVerifier);
-
- nsCOMPtr<nsIRequest> channelRequest;
- aLoader->GetRequest(getter_AddRefs(channelRequest));
- nsCOMPtr<nsIChannel> channel;
- channel = do_QueryInterface(channelRequest);
-
if (NS_FAILED(aSRIDataVerifier->Verify(request->mIntegrity, channel,
request->mCORSMode, mDocument))) {
rv = NS_ERROR_SRI_CORRUPT;
}
+ } else {
+ nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
+
+ bool enforceSRI = false;
+ loadInfo->GetEnforceSRI(&enforceSRI);
+ if (enforceSRI) {
+ MOZ_LOG(GetSriLog(), mozilla::LogLevel::Debug,
+ ("nsScriptLoader::OnStreamComplete, required SRI not found"));
+ rv = NS_ERROR_SRI_CORRUPT;
+ }
}
if (NS_SUCCEEDED(rv)) {
rv = PrepareLoadedRequest(request, aLoader, aChannelStatus, aString);
}
if (NS_FAILED(rv)) {
/*
--- a/ipc/glue/BackgroundUtils.cpp
+++ b/ipc/glue/BackgroundUtils.cpp
@@ -240,16 +240,17 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoa
LoadInfoArgs(
requestingPrincipalInfo,
triggeringPrincipalInfo,
aLoadInfo->GetSecurityFlags(),
aLoadInfo->InternalContentPolicyType(),
static_cast<uint32_t>(aLoadInfo->GetTainting()),
aLoadInfo->GetUpgradeInsecureRequests(),
aLoadInfo->GetVerifySignedContent(),
+ aLoadInfo->GetEnforceSRI(),
aLoadInfo->GetInnerWindowID(),
aLoadInfo->GetOuterWindowID(),
aLoadInfo->GetParentOuterWindowID(),
aLoadInfo->GetEnforceSecurity(),
aLoadInfo->GetInitialSecurityCheckDone(),
aLoadInfo->GetIsInThirdPartyContext(),
aLoadInfo->GetOriginAttributes(),
redirectChainIncludingInternalRedirects,
@@ -300,16 +301,17 @@ LoadInfoArgsToLoadInfo(const OptionalLoa
nsCOMPtr<nsILoadInfo> loadInfo =
new mozilla::LoadInfo(requestingPrincipal,
triggeringPrincipal,
loadInfoArgs.securityFlags(),
loadInfoArgs.contentPolicyType(),
static_cast<LoadTainting>(loadInfoArgs.tainting()),
loadInfoArgs.upgradeInsecureRequests(),
loadInfoArgs.verifySignedContent(),
+ loadInfoArgs.enforceSRI(),
loadInfoArgs.innerWindowID(),
loadInfoArgs.outerWindowID(),
loadInfoArgs.parentOuterWindowID(),
loadInfoArgs.enforceSecurity(),
loadInfoArgs.initialSecurityCheckDone(),
loadInfoArgs.isInThirdPartyContext(),
loadInfoArgs.originAttributes(),
redirectChainIncludingInternalRedirects,
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -951,25 +951,39 @@ SheetLoadData::OnStreamComplete(nsIUnich
contentType.get()));
mLoader->SheetComplete(this, NS_ERROR_NOT_AVAILABLE);
return NS_OK;
}
}
SRIMetadata sriMetadata;
mSheet->GetIntegrity(sriMetadata);
- if (!sriMetadata.IsEmpty() &&
- NS_FAILED(SRICheck::VerifyIntegrity(sriMetadata, aLoader,
- mSheet->GetCORSMode(), aBuffer,
- mLoader->mDocument))) {
- LOG((" Load was blocked by SRI"));
- MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
- ("css::Loader::OnStreamComplete, bad metadata"));
- mLoader->SheetComplete(this, NS_ERROR_SRI_CORRUPT);
- return NS_OK;
+
+ if (sriMetadata.IsEmpty()) {
+ nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
+ bool enforceSRI = false;
+ loadInfo->GetEnforceSRI(&enforceSRI);
+ if (enforceSRI) {
+ LOG((" Load was blocked by SRI"));
+ MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
+ ("css::Loader::OnStreamComplete, required SRI not found"));
+ mLoader->SheetComplete(this, NS_ERROR_SRI_CORRUPT);
+ return NS_OK;
+ }
+ } else {
+ nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader,
+ mSheet->GetCORSMode(), aBuffer,
+ mLoader->mDocument);
+ if (NS_FAILED(rv)) {
+ LOG((" Load was blocked by SRI"));
+ MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
+ ("css::Loader::OnStreamComplete, bad metadata"));
+ mLoader->SheetComplete(this, NS_ERROR_SRI_CORRUPT);
+ return NS_OK;
+ }
}
// Enough to set the URIs on mSheet, since any sibling datas we have share
// the same mInner as mSheet and will thus get the same URI.
mSheet->SetURIs(channelURI, originalURI, channelURI);
bool completed;
result = mLoader->ParseSheet(aBuffer, this, completed);
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -42,16 +42,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
, mTriggeringPrincipal(aTriggeringPrincipal ?
aTriggeringPrincipal : mLoadingPrincipal.get())
, mLoadingContext(do_GetWeakReference(aLoadingContext))
, mSecurityFlags(aSecurityFlags)
, mInternalContentPolicyType(aContentPolicyType)
, mTainting(LoadTainting::Basic)
, mUpgradeInsecureRequests(false)
, mVerifySignedContent(false)
+ , mEnforceSRI(false)
, mInnerWindowID(0)
, mOuterWindowID(0)
, mParentOuterWindowID(0)
, mEnforceSecurity(false)
, mInitialSecurityCheckDone(false)
, mIsThirdPartyContext(true)
, mForcePreflight(false)
, mIsPreflight(false)
@@ -99,32 +100,42 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
// if the document forces all requests to be upgraded from http to https, then
// we should do that for all requests. If it only forces preloads to be upgraded
// then we should enforce upgrade insecure requests only for preloads.
mUpgradeInsecureRequests =
aLoadingContext->OwnerDoc()->GetUpgradeInsecureRequests(false) ||
(nsContentUtils::IsPreloadType(mInternalContentPolicyType) &&
aLoadingContext->OwnerDoc()->GetUpgradeInsecureRequests(true));
+
+ // if owner doc has content signature, we enforce SRI
+ nsCOMPtr<nsIChannel> channel = aLoadingContext->OwnerDoc()->GetChannel();
+ if (channel) {
+ nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
+ if (loadInfo) {
+ loadInfo->GetVerifySignedContent(&mEnforceSRI);
+ }
+ }
}
InheritOriginAttributes(mLoadingPrincipal, mOriginAttributes);
}
LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal,
nsSecurityFlags aSecurityFlags)
: mLoadingPrincipal(aLoadingPrincipal)
, mTriggeringPrincipal(aTriggeringPrincipal)
, mSecurityFlags(aSecurityFlags)
, mInternalContentPolicyType(nsIContentPolicy::TYPE_DOCUMENT)
, mTainting(LoadTainting::Basic)
, mUpgradeInsecureRequests(false)
, mVerifySignedContent(false)
+ , mEnforceSRI(false)
, mInnerWindowID(0)
, mOuterWindowID(0)
, mParentOuterWindowID(0)
, mEnforceSecurity(false)
, mInitialSecurityCheckDone(false)
, mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party.
, mForcePreflight(false)
, mIsPreflight(false)
@@ -153,16 +164,17 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
: mLoadingPrincipal(rhs.mLoadingPrincipal)
, mTriggeringPrincipal(rhs.mTriggeringPrincipal)
, mLoadingContext(rhs.mLoadingContext)
, mSecurityFlags(rhs.mSecurityFlags)
, mInternalContentPolicyType(rhs.mInternalContentPolicyType)
, mTainting(rhs.mTainting)
, mUpgradeInsecureRequests(rhs.mUpgradeInsecureRequests)
, mVerifySignedContent(rhs.mVerifySignedContent)
+ , mEnforceSRI(rhs.mEnforceSRI)
, mInnerWindowID(rhs.mInnerWindowID)
, mOuterWindowID(rhs.mOuterWindowID)
, mParentOuterWindowID(rhs.mParentOuterWindowID)
, mEnforceSecurity(rhs.mEnforceSecurity)
, mInitialSecurityCheckDone(rhs.mInitialSecurityCheckDone)
, mIsThirdPartyContext(rhs.mIsThirdPartyContext)
, mOriginAttributes(rhs.mOriginAttributes)
, mRedirectChainIncludingInternalRedirects(
@@ -176,16 +188,17 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal,
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
LoadTainting aTainting,
bool aUpgradeInsecureRequests,
bool aVerifySignedContent,
+ bool aEnforceSRI,
uint64_t aInnerWindowID,
uint64_t aOuterWindowID,
uint64_t aParentOuterWindowID,
bool aEnforceSecurity,
bool aInitialSecurityCheckDone,
bool aIsThirdPartyContext,
const NeckoOriginAttributes& aOriginAttributes,
nsTArray<nsCOMPtr<nsIPrincipal>>& aRedirectChainIncludingInternalRedirects,
@@ -195,16 +208,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
bool aIsPreflight)
: mLoadingPrincipal(aLoadingPrincipal)
, mTriggeringPrincipal(aTriggeringPrincipal)
, mSecurityFlags(aSecurityFlags)
, mInternalContentPolicyType(aContentPolicyType)
, mTainting(aTainting)
, mUpgradeInsecureRequests(aUpgradeInsecureRequests)
, mVerifySignedContent(aVerifySignedContent)
+ , mEnforceSRI(aEnforceSRI)
, mInnerWindowID(aInnerWindowID)
, mOuterWindowID(aOuterWindowID)
, mParentOuterWindowID(aParentOuterWindowID)
, mEnforceSecurity(aEnforceSecurity)
, mInitialSecurityCheckDone(aInitialSecurityCheckDone)
, mIsThirdPartyContext(aIsThirdPartyContext)
, mOriginAttributes(aOriginAttributes)
, mCorsUnsafeHeaders(aCorsUnsafeHeaders)
@@ -444,16 +458,30 @@ LoadInfo::SetVerifySignedContent(bool aV
NS_IMETHODIMP
LoadInfo::GetVerifySignedContent(bool* aResult)
{
*aResult = mVerifySignedContent;
return NS_OK;
}
NS_IMETHODIMP
+LoadInfo::SetEnforceSRI(bool aEnforceSRI)
+{
+ mEnforceSRI = aEnforceSRI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+LoadInfo::GetEnforceSRI(bool* aResult)
+{
+ *aResult = mEnforceSRI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
LoadInfo::GetInnerWindowID(uint64_t* aResult)
{
*aResult = mInnerWindowID;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetOuterWindowID(uint64_t* aResult)
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -76,16 +76,17 @@ private:
// Please note that aRedirectChain uses swapElements.
LoadInfo(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal,
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
LoadTainting aTainting,
bool aUpgradeInsecureRequests,
bool aVerifySignedContent,
+ bool aEnforceSRI,
uint64_t aInnerWindowID,
uint64_t aOuterWindowID,
uint64_t aParentOuterWindowID,
bool aEnforceSecurity,
bool aInitialSecurityCheckDone,
bool aIsThirdPartyRequest,
const NeckoOriginAttributes& aOriginAttributes,
nsTArray<nsCOMPtr<nsIPrincipal>>& aRedirectChainIncludingInternalRedirects,
@@ -114,16 +115,17 @@ private:
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsWeakPtr mLoadingContext;
nsSecurityFlags mSecurityFlags;
nsContentPolicyType mInternalContentPolicyType;
LoadTainting mTainting;
bool mUpgradeInsecureRequests;
bool mVerifySignedContent;
+ bool mEnforceSRI;
uint64_t mInnerWindowID;
uint64_t mOuterWindowID;
uint64_t mParentOuterWindowID;
bool mEnforceSecurity;
bool mInitialSecurityCheckDone;
bool mIsThirdPartyContext;
NeckoOriginAttributes mOriginAttributes;
nsTArray<nsCOMPtr<nsIPrincipal>> mRedirectChainIncludingInternalRedirects;
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -343,16 +343,21 @@ interface nsILoadInfo : nsISupports
* can not start until all of the content is fetched from the
* netwerk.
*
* Only use that in combination with TYPE_DOCUMENT.
*/
[infallible] attribute boolean verifySignedContent;
/**
+ * If true, this load will fail if it has no SRI integrity
+ */
+ [infallible] attribute boolean enforceSRI;
+
+ /**
* Typically these are the window IDs of the window in which the element being
* loaded lives. However, if the element being loaded is <frame
* src="foo.html"> (or, more generally, if the element QIs to
* nsIFrameLoaderOwner) then the window IDs are for the window containing the
* foo.html document. In this case, parentOuterWindowID is the window ID of
* the window containing the <frame> element.
*
* Note that these window IDs can be 0 if the window is not
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -29,16 +29,17 @@ struct LoadInfoArgs
{
PrincipalInfo requestingPrincipalInfo;
PrincipalInfo triggeringPrincipalInfo;
uint32_t securityFlags;
uint32_t contentPolicyType;
uint32_t tainting;
bool upgradeInsecureRequests;
bool verifySignedContent;
+ bool enforceSRI;
uint64_t innerWindowID;
uint64_t outerWindowID;
uint64_t parentOuterWindowID;
bool enforceSecurity;
bool initialSecurityCheckDone;
bool isInThirdPartyContext;
NeckoOriginAttributes originAttributes;
PrincipalInfo[] redirectChainIncludingInternalRedirects;