Bug 1206961 - Use channel->AsyncOpen2() in image/imgLoader.cpp; removing security checks from the callsite reveals that we have to pass the accurate contentPolicyType to ValidateEntry (r=seth,bz)

This commit is contained in:
Christoph Kerschbaumer 2016-04-27 19:40:56 +02:00
parent 4b3726dd99
commit 0e1d963860

View File

@ -594,7 +594,8 @@ ShouldRevalidateEntry(imgCacheEntry* aEntry,
static bool
ShouldLoadCachedImage(imgRequest* aImgRequest,
nsISupports* aLoadingContext,
nsIPrincipal* aLoadingPrincipal)
nsIPrincipal* aLoadingPrincipal,
nsContentPolicyType aPolicyType)
{
/* Call content policies on cached images - Bug 1082837
* Cached images are keyed off of the first uri in a redirect chain.
@ -611,7 +612,7 @@ ShouldLoadCachedImage(imgRequest* aImgRequest,
nsresult rv;
int16_t decision = nsIContentPolicy::REJECT_REQUEST;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE,
rv = NS_CheckContentLoadPolicy(aPolicyType,
contentLocation,
aLoadingPrincipal,
aLoadingContext,
@ -638,7 +639,7 @@ ShouldLoadCachedImage(imgRequest* aImgRequest,
// reset the decision for mixed content blocker check
decision = nsIContentPolicy::REJECT_REQUEST;
rv = nsMixedContentBlocker::ShouldLoad(insecureRedirect,
nsIContentPolicy::TYPE_IMAGE,
aPolicyType,
contentLocation,
requestingLocation,
aLoadingContext,
@ -662,7 +663,8 @@ ShouldLoadCachedImage(imgRequest* aImgRequest,
static bool
ValidateSecurityInfo(imgRequest* request, bool forcePrincipalCheck,
int32_t corsmode, nsIPrincipal* loadingPrincipal,
nsISupports* aCX, ReferrerPolicy referrerPolicy)
nsISupports* aCX, nsContentPolicyType aPolicyType,
ReferrerPolicy referrerPolicy)
{
// If the entry's Referrer Policy doesn't match, we can't use this request.
// XXX: this will return false if an image has different referrer attributes,
@ -696,7 +698,7 @@ ValidateSecurityInfo(imgRequest* request, bool forcePrincipalCheck,
}
// Content Policy Check on Cached Images
return ShouldLoadCachedImage(request, aCX, loadingPrincipal);
return ShouldLoadCachedImage(request, aCX, loadingPrincipal, aPolicyType);
}
static nsresult
@ -710,6 +712,7 @@ NewImageChannel(nsIChannel** aResult,
bool* aForcePrincipalCheckForCacheEntry,
nsIURI* aURI,
nsIURI* aInitialDocumentURI,
int32_t aCORSMode,
nsIURI* aReferringURI,
ReferrerPolicy aReferrerPolicy,
nsILoadGroup* aLoadGroup,
@ -746,24 +749,18 @@ NewImageChannel(nsIChannel** aResult,
//
aLoadFlags |= nsIChannel::LOAD_CLASSIFY_URI;
nsCOMPtr<nsIPrincipal> triggeringPrincipal = aLoadingPrincipal;
bool isSandBoxed = false;
// only inherit if we have a principal
bool inherit = false;
if (triggeringPrincipal) {
inherit = nsContentUtils::
ChannelShouldInheritPrincipal(triggeringPrincipal,
aURI,
false, // aInheritForAboutBlank
false); // aForceInherit
} else {
triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
}
nsCOMPtr<nsINode> requestingNode = do_QueryInterface(aRequestingContext);
nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
if (inherit) {
securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
nsSecurityFlags securityFlags =
aCORSMode == imgIRequest::CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS
: nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (aCORSMode == imgIRequest::CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (aCORSMode == imgIRequest::CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
if (aRespectPrivacy) {
securityFlags |= nsILoadInfo::SEC_FORCE_PRIVATE_BROWSING;
@ -773,11 +770,11 @@ NewImageChannel(nsIChannel** aResult,
// node and a principal. This is for things like background images that are
// specified by user stylesheets, where the document is being styled, but
// the principal is that of the user stylesheet.
if (requestingNode) {
if (requestingNode && aLoadingPrincipal) {
rv = NS_NewChannelWithTriggeringPrincipal(aResult,
aURI,
requestingNode,
triggeringPrincipal,
aLoadingPrincipal,
securityFlags,
aPolicyType,
nullptr, // loadGroup
@ -786,14 +783,14 @@ NewImageChannel(nsIChannel** aResult,
} else {
// either we are loading something inside a document, in which case
// we should always have a requestingNode, or we are loading something
// outside a document, in which case the triggeringPrincipal
// should always be the systemPrincipal.
// outside a document, in which case the loadingPrincipal and
// triggeringPrincipal should always be the systemPrincipal.
// However, there are two exceptions: one is Notifications and the
// other one is Favicons which create a channel in the parent prcoess
// in which case we can't get a requestingNode.
rv = NS_NewChannel(aResult,
aURI,
triggeringPrincipal,
nsContentUtils::GetSystemPrincipal(),
securityFlags,
aPolicyType,
nullptr, // loadGroup
@ -805,7 +802,14 @@ NewImageChannel(nsIChannel** aResult,
return rv;
}
*aForcePrincipalCheckForCacheEntry = inherit && !isSandBoxed;
// only inherit if we have a principal
*aForcePrincipalCheckForCacheEntry =
aLoadingPrincipal &&
nsContentUtils::ChannelShouldInheritPrincipal(
aLoadingPrincipal,
aURI,
/* aInheritForAboutBlank */ false,
/* aForceInherit */ false);
// Initialize HTTP-specific attributes
newHttpChannel = do_QueryInterface(*aResult);
@ -1634,6 +1638,7 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request,
&forcePrincipalCheck,
aURI,
aInitialDocumentURI,
aCORSMode,
aReferrerURI,
aReferrerPolicy,
aLoadGroup,
@ -1675,18 +1680,6 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request,
// notification callbacks.
newChannel->SetNotificationCallbacks(hvc);
if (aCORSMode != imgIRequest::CORS_NONE) {
bool withCredentials = aCORSMode == imgIRequest::CORS_USE_CREDENTIALS;
RefPtr<nsCORSListenerProxy> corsproxy =
new nsCORSListenerProxy(listener, aLoadingPrincipal, withCredentials);
rv = corsproxy->Init(newChannel, DataURIHandling::Allow);
if (NS_FAILED(rv)) {
return false;
}
listener = corsproxy;
}
request->SetValidator(hvc);
// We will send notifications from imgCacheValidator::OnStartRequest().
@ -1701,7 +1694,7 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request,
mozilla::net::PredictorLearn(aURI, aInitialDocumentURI,
nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE, aLoadGroup);
rv = newChannel->AsyncOpen(listener, nullptr);
rv = newChannel->AsyncOpen2(listener);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
@ -1765,7 +1758,7 @@ imgLoader::ValidateEntry(imgCacheEntry* aEntry,
if (!ValidateSecurityInfo(request, aEntry->ForcePrincipalCheck(),
aCORSMode, aLoadingPrincipal,
aCX, aReferrerPolicy))
aCX, aLoadPolicyType, aReferrerPolicy))
return false;
// data URIs are immutable and by their nature can't leak data, so we can
@ -2170,6 +2163,7 @@ imgLoader::LoadImage(nsIURI* aURI,
&forcePrincipalCheck,
aURI,
aInitialDocumentURI,
corsmode,
aReferrerURI,
aReferrerPolicy,
aLoadGroup,
@ -2206,43 +2200,20 @@ imgLoader::LoadImage(nsIURI* aURI,
}
// create the proxy listener
nsCOMPtr<nsIStreamListener> pl = new ProxyListener(request.get());
// See if we need to insert a CORS proxy between the proxy listener and the
// request.
nsCOMPtr<nsIStreamListener> listener = pl;
if (corsmode != imgIRequest::CORS_NONE) {
MOZ_LOG(gImgLog, LogLevel::Debug,
("[this=%p] imgLoader::LoadImage -- Setting up a CORS load",
this));
bool withCredentials = corsmode == imgIRequest::CORS_USE_CREDENTIALS;
RefPtr<nsCORSListenerProxy> corsproxy =
new nsCORSListenerProxy(pl, aLoadingPrincipal, withCredentials);
rv = corsproxy->Init(newChannel, DataURIHandling::Allow);
if (NS_FAILED(rv)) {
MOZ_LOG(gImgLog, LogLevel::Debug,
("[this=%p] imgLoader::LoadImage -- nsCORSListenerProxy "
"creation failed: 0x%x\n", this, rv));
request->CancelAndAbort(rv);
return NS_ERROR_FAILURE;
}
listener = corsproxy;
}
nsCOMPtr<nsIStreamListener> listener = new ProxyListener(request.get());
MOZ_LOG(gImgLog, LogLevel::Debug,
("[this=%p] imgLoader::LoadImage -- Calling channel->AsyncOpen()\n",
("[this=%p] imgLoader::LoadImage -- Calling channel->AsyncOpen2()\n",
this));
mozilla::net::PredictorLearn(aURI, aInitialDocumentURI,
nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE, aLoadGroup);
nsresult openRes = newChannel->AsyncOpen(listener, nullptr);
nsresult openRes = newChannel->AsyncOpen2(listener);
if (NS_FAILED(openRes)) {
MOZ_LOG(gImgLog, LogLevel::Debug,
("[this=%p] imgLoader::LoadImage -- AsyncOpen() failed: 0x%x\n",
("[this=%p] imgLoader::LoadImage -- AsyncOpen2() failed: 0x%x\n",
this, openRes));
request->CancelAndAbort(openRes);
return openRes;
@ -2373,9 +2344,17 @@ imgLoader::LoadImageWithChannel(nsIChannel* channel,
//
// Since aCanMakeNewChannel == false, we don't need to pass content policy
// type/principal/etc
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
// if there is a loadInfo, use the right contentType, otherwise
// default to the internal image type
nsContentPolicyType policyType = loadInfo
? loadInfo->InternalContentPolicyType()
: nsIContentPolicy::TYPE_INTERNAL_IMAGE;
if (ValidateEntry(entry, uri, nullptr, nullptr, RP_Default,
nullptr, aObserver, aCX, requestFlags,
nsIContentPolicy::TYPE_INVALID, false, nullptr,
policyType, false, nullptr,
nullptr, imgIRequest::CORS_NONE)) {
request = entry->GetRequest();
} else {