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

This commit is contained in:
Brandon Sterne 2010-05-20 13:08:02 -07:00
Родитель 6f2c9d9235
Коммит 576c1b9813
10 изменённых файлов: 76 добавлений и 22 удалений

Просмотреть файл

@ -198,6 +198,9 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "jstypedarray.h" #include "jstypedarray.h"
#include "xpcprivate.h" #include "xpcprivate.h"
#include "nsScriptSecurityManager.h" #include "nsScriptSecurityManager.h"
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
using namespace mozilla::dom; using namespace mozilla::dom;
@ -2327,12 +2330,23 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
nsIURI *documentURI = aLoadingDocument->GetDocumentURI(); 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 // Make the URI immutable so people won't change it under us
NS_TryToSetImmutable(aURI); 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 // XXXbz using "documentURI" for the initialDocumentURI is not quite
// right, but the best we can do here... // right, but the best we can do here...
return sImgLoader->LoadImage(aURI, /* uri to load */ return sImgLoader->LoadImage(aURI, /* uri to load */
@ -2344,6 +2358,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
aLoadFlags, /* load flags */ aLoadFlags, /* load flags */
nsnull, /* cache key */ nsnull, /* cache key */
nsnull, /* existing request*/ nsnull, /* existing request*/
channelPolicy, /* CSP info */
aRequest); aRequest);
} }

Просмотреть файл

@ -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", var tests = { "font-src": thisSite+page+"?testid=font-src&csp=1",
"frame-src": thisSite+page+"?testid=frame-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", "media-src": thisSite+page+"?testid=media-src&csp=1",
"object-src": thisSite+page+"?testid=object-src&csp=1", "object-src": thisSite+page+"?testid=object-src&csp=1",
"script-src": thisSite+page+"?testid=script-src&csp=1", "script-src": thisSite+page+"?testid=script-src&csp=1",

Просмотреть файл

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

Просмотреть файл

@ -59,6 +59,11 @@
#include "nsIDOMCSSPrimitiveValue.h" #include "nsIDOMCSSPrimitiveValue.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"
#include "nsIDocument.h"
#include "nsIPrincipal.h"
#include "nsIChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIContentPolicy.h"
//***************************************************************************** //*****************************************************************************
// class nsContextMenuInfo // class nsContextMenuInfo
@ -299,6 +304,22 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR
nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue; nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
nsAutoString bgStringValue; 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) { while (PR_TRUE) {
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode)); nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
// bail for the parent node of the root element or null argument // 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, return il->LoadImage(bgUri, nsnull, nsnull, nsnull, nsnull, nsnull,
nsIRequest::LOAD_NORMAL, nsnull, nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull,
aRequest); channelPolicy, aRequest);
} }
} }

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -337,8 +337,10 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
[mNativeMenuItem setImage:sPlaceholderIconImage]; [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, rv = loader->LoadImage(aIconURI, nsnull, nsnull, loadGroup, this,
nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull,
nsnull, getter_AddRefs(mIconRequest)); nsnull, getter_AddRefs(mIconRequest));
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;