Bug 515460 - enforce CSP during image redirects, r=joe

This commit is contained in:
Brandon Sterne 2010-05-20 13:08:02 -07:00
parent e67987c906
commit bcab21793a
10 changed files with 76 additions and 22 deletions

View File

@ -198,6 +198,9 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "jstypedarray.h"
#include "xpcprivate.h"
#include "nsScriptSecurityManager.h"
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
using namespace mozilla::dom;
@ -2327,12 +2330,23 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
// check for a Content Security Policy to pass down to the channel that
// will get created to load the image
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
if (aLoadingPrincipal) {
nsresult rv = aLoadingPrincipal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
}
}
// Make the URI immutable so people won't change it under us
NS_TryToSetImmutable(aURI);
// We don't use aLoadingPrincipal for anything here yet... but we
// will. See bug 377092.
// XXXbz using "documentURI" for the initialDocumentURI is not quite
// right, but the best we can do here...
return sImgLoader->LoadImage(aURI, /* uri to load */
@ -2344,6 +2358,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
aLoadFlags, /* load flags */
nsnull, /* cache key */
nsnull, /* existing request*/
channelPolicy, /* CSP info */
aRequest);
}

View File

@ -13,7 +13,7 @@ var page = "/tests/content/base/test/file_csp_redirects_page.sjs";
var tests = { "font-src": thisSite+page+"?testid=font-src&csp=1",
"frame-src": thisSite+page+"?testid=frame-src&csp=1",
// "img-src": thisSite+page+"?testid=img-src&csp=1",
"img-src": thisSite+page+"?testid=img-src&csp=1",
"media-src": thisSite+page+"?testid=media-src&csp=1",
"object-src": thisSite+page+"?testid=object-src&csp=1",
"script-src": thisSite+page+"?testid=script-src&csp=1",

View File

@ -83,8 +83,8 @@ var testExpectedResults = { "font-src": true,
"font-src-redir": false,
"frame-src": true,
"frame-src-redir": false,
// "img-src": true,
// "img-src-redir": false,
"img-src": true,
"img-src-redir": false,
"media-src": true,
"media-src-redir": false,
"object-src": true,

View File

@ -59,6 +59,11 @@
#include "nsIDOMCSSPrimitiveValue.h"
#include "nsNetUtil.h"
#include "nsUnicharUtils.h"
#include "nsIDocument.h"
#include "nsIPrincipal.h"
#include "nsIChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIContentPolicy.h"
//*****************************************************************************
// class nsContextMenuInfo
@ -299,6 +304,22 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR
nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
nsAutoString bgStringValue;
// get Content Security Policy to pass to LoadImage
nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
if (doc) {
principal = doc->NodePrincipal();
nsresult rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
}
}
while (PR_TRUE) {
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
// bail for the parent node of the root element or null argument
@ -326,7 +347,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR
return il->LoadImage(bgUri, nsnull, nsnull, nsnull, nsnull, nsnull,
nsIRequest::LOAD_NORMAL, nsnull, nsnull,
aRequest);
channelPolicy, aRequest);
}
}

View File

@ -1671,6 +1671,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec,
loadFlags,
nsnull,
nsnull,
nsnull, /* channel policy not needed */
aRequest);
}

View File

@ -48,6 +48,7 @@ interface nsIStreamListener;
interface nsIURI;
interface nsISimpleEnumerator;
interface nsIChannelPolicy;
#include "nsIRequest.idl" // for nsLoadFlags
@ -58,7 +59,7 @@ interface nsISimpleEnumerator;
* @version 0.3
* @see imagelib2
*/
[scriptable, uuid(d2f50c69-1064-4ce3-a92d-01dc5f5b4842)]
[scriptable, uuid(7b776f98-3faf-40f9-b352-3283a884cb98)]
interface imgILoader : nsISupports
{
/**
@ -89,7 +90,8 @@ interface imgILoader : nsISupports
in nsISupports aCX,
in nsLoadFlags aLoadFlags,
in nsISupports cacheKey,
in imgIRequest aRequest);
in imgIRequest aRequest,
in nsIChannelPolicy channelPolicy);
/**
* Start the load and decode of an image.

View File

@ -74,6 +74,8 @@
// so we can associate the document URI with the load group.
// until this point, we have an evil hack:
#include "nsIHttpChannelInternal.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIChannelPolicy.h"
#include "mozilla/FunctionTimer.h"
@ -293,7 +295,8 @@ static nsresult NewImageChannel(nsIChannel **aResult,
nsIURI *aReferringURI,
nsILoadGroup *aLoadGroup,
const nsCString& aAcceptHeader,
nsLoadFlags aLoadFlags)
nsLoadFlags aLoadFlags,
nsIChannelPolicy *aPolicy)
{
nsresult rv;
nsCOMPtr<nsIChannel> newChannel;
@ -323,7 +326,8 @@ static nsresult NewImageChannel(nsIChannel **aResult,
nsnull, // Cached IOService
nsnull, // LoadGroup
callbacks, // Notification Callbacks
aLoadFlags);
aLoadFlags,
aPolicy);
if (NS_FAILED(rv))
return rv;
@ -984,7 +988,8 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
nsISupports *aCX,
nsLoadFlags aLoadFlags,
imgIRequest *aExistingRequest,
imgIRequest **aProxyRequest)
imgIRequest **aProxyRequest,
nsIChannelPolicy *aPolicy)
{
// now we need to insert a new channel request object inbetween the real
// request and the proxy that basically delays loading the image until it
@ -1012,7 +1017,8 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
aReferrerURI,
aLoadGroup,
mAcceptHeader,
aLoadFlags);
aLoadFlags,
aPolicy);
if (NS_FAILED(rv)) {
return PR_FALSE;
}
@ -1072,7 +1078,8 @@ PRBool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
nsLoadFlags aLoadFlags,
PRBool aCanMakeNewChannel,
imgIRequest *aExistingRequest,
imgIRequest **aProxyRequest)
imgIRequest **aProxyRequest,
nsIChannelPolicy *aPolicy = nsnull)
{
LOG_SCOPE(gImgLog, "imgLoader::ValidateEntry");
@ -1186,7 +1193,7 @@ PRBool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
return ValidateRequestWithNewChannel(request, aURI, aInitialDocumentURI,
aReferrerURI, aLoadGroup, aObserver,
aCX, aLoadFlags, aExistingRequest,
aProxyRequest);
aProxyRequest, aPolicy);
}
return !validateRequest;
@ -1327,6 +1334,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
nsLoadFlags aLoadFlags,
nsISupports *aCacheKey,
imgIRequest *aRequest,
nsIChannelPolicy *aPolicy,
imgIRequest **_retval)
{
VerifyCacheSizes();
@ -1382,8 +1390,9 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
imgCacheTable &cache = GetCache(aURI);
if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI, aLoadGroup, aObserver, aCX,
requestFlags, PR_TRUE, aRequest, _retval)) {
if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
aLoadGroup, aObserver, aCX, requestFlags, PR_TRUE,
aRequest, _retval, aPolicy)) {
request = getter_AddRefs(entry->GetRequest());
// If this entry has no proxies, its request has no reference to the entry.
@ -1422,7 +1431,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
aReferrerURI,
aLoadGroup,
mAcceptHeader,
requestFlags);
requestFlags,
aPolicy);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;

View File

@ -48,6 +48,7 @@
#include "prtypes.h"
#include "imgRequest.h"
#include "nsIObserverService.h"
#include "nsIChannelPolicy.h"
#ifdef LOADER_THREADSAFE
#include "prlock.h"
@ -300,7 +301,8 @@ private: // methods
imgIDecoderObserver *aObserver, nsISupports *aCX,
nsLoadFlags aLoadFlags, PRBool aCanMakeNewChannel,
imgIRequest *aExistingRequest,
imgIRequest **aProxyRequest);
imgIRequest **aProxyRequest,
nsIChannelPolicy *aPolicy);
PRBool ValidateRequestWithNewChannel(imgRequest *request, nsIURI *aURI,
nsIURI *aInitialDocumentURI,
nsIURI *aReferrerURI,
@ -308,7 +310,8 @@ private: // methods
imgIDecoderObserver *aObserver,
nsISupports *aCX, nsLoadFlags aLoadFlags,
imgIRequest *aExistingRequest,
imgIRequest **aProxyRequest);
imgIRequest **aProxyRequest,
nsIChannelPolicy *aPolicy);
nsresult CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup,
imgIDecoderObserver *aObserver,

View File

@ -266,7 +266,7 @@ nsAlertsIconListener::StartRequest(const nsAString & aImageUrl)
return il->LoadImage(imageUri, nsnull, nsnull, nsnull, this,
nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull,
getter_AddRefs(mIconRequest));
nsnull, getter_AddRefs(mIconRequest));
}
void

View File

@ -337,8 +337,10 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
[mNativeMenuItem setImage:sPlaceholderIconImage];
}
// Passing in null for channelPolicy here since nsMenuItemIconX::LoadIcon is
// not exposed to web content
rv = loader->LoadImage(aIconURI, nsnull, nsnull, loadGroup, this,
nsnull, nsIRequest::LOAD_NORMAL, nsnull,
nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull,
nsnull, getter_AddRefs(mIconRequest));
if (NS_FAILED(rv)) return rv;