Propagate the principal responsible an image load all the way to

CanLoadImage/LoadImage in nsContentUtils, and use it for security checks
there.  Bug 310165, r=sicking, sr=dbaron
This commit is contained in:
bzbarsky@mit.edu 2007-07-03 11:45:39 -07:00
parent a9973017aa
commit bdded13f7c
9 changed files with 95 additions and 36 deletions

View File

@ -531,6 +531,7 @@ public:
* @param aURI uri of the image to be loaded
* @param aContext the context the image is loaded in (eg an element)
* @param aLoadingDocument the document we belong to
* @param aLoadingPrincipal the principal doing the load
* @param aImageBlockingStatus the nsIContentPolicy blocking status for this
* image. This will be set even if a security check fails for the
* image, to some reasonable REJECT_* value. This out param will only
@ -543,18 +544,22 @@ public:
static PRBool CanLoadImage(nsIURI* aURI,
nsISupports* aContext,
nsIDocument* aLoadingDocument,
nsIPrincipal* aLoadingPrincipal,
PRInt16* aImageBlockingStatus = nsnull);
/**
* Method to start an image load. This does not do any security checks.
*
* @param aURI uri of the image to be loaded
* @param aLoadingDocument the document we belong to
* @param aLoadingPrincipal the principal doing the load
* @param aReferrer the referrer URI
* @param aObserver the observer for the image load
* @param aLoadFlags the load flags to use. See nsIRequest
* @return the imgIRequest for the image load
*/
static nsresult LoadImage(nsIURI* aURI,
nsIDocument* aLoadingDocument,
nsIPrincipal* aLoadingPrincipal,
nsIURI* aReferrer,
imgIDecoderObserver* aObserver,
PRInt32 aLoadFlags,

View File

@ -2056,10 +2056,12 @@ nsContentUtils::SplitExpatName(const PRUnichar *aExpatName, nsIAtom **aPrefix,
PRBool
nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
nsIDocument* aLoadingDocument,
nsIPrincipal* aLoadingPrincipal,
PRInt16* aImageBlockingStatus)
{
NS_PRECONDITION(aURI, "Must have a URI");
NS_PRECONDITION(aLoadingDocument, "Must have a document");
NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal");
nsresult rv;
@ -2084,9 +2086,10 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
if (appType != nsIDocShell::APP_TYPE_EDITOR) {
// Editor apps get special treatment here, editors can load images
// from anywhere.
// from anywhere. This allows editor to insert images from file://
// into documents that are being edited.
rv = sSecurityManager->
CheckLoadURIWithPrincipal(aLoadingDocument->NodePrincipal(), aURI,
CheckLoadURIWithPrincipal(aLoadingPrincipal, aURI,
nsIScriptSecurityManager::ALLOW_CHROME);
if (NS_FAILED(rv)) {
if (aImageBlockingStatus) {
@ -2098,11 +2101,15 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
}
}
nsCOMPtr<nsIURI> loadingURI;
nsresult rv = aLoadingPrincipal->GetURI(getter_AddRefs(loadingURI));
NS_ENSURE_SUCCESS(rv, PR_FALSE);
PRInt16 decision = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_IMAGE,
aURI,
aLoadingDocument->GetDocumentURI(),
loadingURI,
aContext,
EmptyCString(), //mime guess
nsnull, //extra
@ -2119,11 +2126,13 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
// static
nsresult
nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
nsIURI* aReferrer, imgIDecoderObserver* aObserver,
PRInt32 aLoadFlags, imgIRequest** aRequest)
nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer,
imgIDecoderObserver* aObserver, PRInt32 aLoadFlags,
imgIRequest** aRequest)
{
NS_PRECONDITION(aURI, "Must have a URI");
NS_PRECONDITION(aLoadingDocument, "Must have a document");
NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
NS_PRECONDITION(aRequest, "Null out param");
if (!sImgLoader) {
@ -2136,6 +2145,9 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
// 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 */

View File

@ -533,6 +533,15 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
// sure to notify if it does.
AutoStateChanger changer(this, aNotify);
// Use the principal of aDocument to avoid having to QI |this| an extra time.
// It should be the same as the principal of this node in any case.
#ifdef DEBUG
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
NS_ASSERTION(thisContent &&
thisContent->NodePrincipal() == aDocument->NodePrincipal(),
"Principal mismatch?");
#endif
// If we'll be loading a new image, we want to cancel our existing
// requests; the question is what reason to pass in. If everything
// is going smoothly, that reason should be
@ -543,6 +552,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
PRInt16 newImageStatus;
PRBool loadImage = nsContentUtils::CanLoadImage(aNewURI, this, aDocument,
aDocument->NodePrincipal(),
&newImageStatus);
NS_ASSERTION(loadImage || !NS_CP_ACCEPTED(newImageStatus),
"CanLoadImage lied");
@ -569,6 +579,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
nsCOMPtr<imgIRequest> & req = mCurrentRequest ? mPendingRequest : mCurrentRequest;
rv = nsContentUtils::LoadImage(aNewURI, aDocument,
aDocument->NodePrincipal(),
aDocument->GetDocumentURI(),
this, aLoadFlags,
getter_AddRefs(req));

View File

@ -122,7 +122,7 @@ nsXBLResourceLoader::LoadResources(PRBool* aResult)
continue;
if (curr->mType == nsGkAtoms::image) {
if (!nsContentUtils::CanLoadImage(url, doc, doc)) {
if (!nsContentUtils::CanLoadImage(url, doc, doc, doc->NodePrincipal())) {
// We're not permitted to load this image, move on...
continue;
}
@ -131,7 +131,7 @@ nsXBLResourceLoader::LoadResources(PRBool* aResult)
// Passing NULL for pretty much everything -- cause we don't care!
// XXX: initialDocumentURI is NULL!
nsCOMPtr<imgIRequest> req;
nsContentUtils::LoadImage(url, doc, docURL, nsnull,
nsContentUtils::LoadImage(url, doc, doc->NodePrincipal(), docURL, nsnull,
nsIRequest::LOAD_BACKGROUND,
getter_AddRefs(req));
}

View File

@ -1138,7 +1138,7 @@ NS_IMETHODIMP
nsCSSStyleSheet::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const
{
// Important: If this function is ever made scriptable, we must add
// a security check here. See GetCSSRules below for an example.
// a security check here. See GetCssRules below for an example.
aRule = mInner->mOrderedRules.SafeObjectAt(aIndex);
if (aRule) {
NS_ADDREF(aRule);
@ -1321,6 +1321,35 @@ nsCSSStyleSheet::DidDirty()
mDirty = PR_TRUE;
}
nsresult
nsCSSStyleSheet::SubjectSubsumesInnerPrincipal() const
{
// Get the security manager and do the subsumes check
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
nsCOMPtr<nsIPrincipal> subjectPrincipal;
securityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
if (!subjectPrincipal) {
return NS_OK;
}
PRBool subsumes;
nsresult rv = subjectPrincipal->Subsumes(mInner->mPrincipal, &subsumes);
NS_ENSURE_SUCCESS(rv, rv);
if (subsumes) {
return NS_OK;
}
if (!nsContentUtils::IsCallerTrustedForWrite()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
return NS_OK;
}
NS_IMETHODIMP
nsCSSStyleSheet::IsModified(PRBool* aSheetModified) const
{
@ -1454,27 +1483,8 @@ nsCSSStyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules)
//-- Security check: Only scripts whose principal subsumes that of the
// style sheet can access rule collections.
// Get the security manager and do the subsumes check
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
nsCOMPtr<nsIPrincipal> subjectPrincipal;
securityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
nsresult rv = NS_OK;
if (subjectPrincipal) {
PRBool subsumes;
rv = subjectPrincipal->Subsumes(mInner->mPrincipal, &subsumes);
if (NS_SUCCEEDED(rv) && !subsumes &&
!nsContentUtils::IsCallerTrustedForRead()) {
rv = NS_ERROR_DOM_SECURITY_ERR;
}
if (NS_FAILED(rv)) {
return rv;
}
}
nsresult rv = SubjectSubsumesInnerPrincipal();
NS_ENSURE_SUCCESS(rv, rv);
// OK, security check passed, so get the rule collection
if (nsnull == mRuleCollection) {
@ -1503,6 +1513,11 @@ nsCSSStyleSheet::InsertRule(const nsAString& aRule,
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
//-- Security check: Only scripts whose principal subsumes that of the
// style sheet can modify rule collections.
nsresult rv = SubjectSubsumesInnerPrincipal();
NS_ENSURE_SUCCESS(rv, rv);
if (aRule.IsEmpty()) {
// Nothing to do here
return NS_OK;
@ -1673,6 +1688,11 @@ nsCSSStyleSheet::DeleteRule(PRUint32 aIndex)
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
//-- Security check: Only scripts whose principal subsumes that of the
// style sheet can modify rule collections.
nsresult rv = SubjectSubsumesInnerPrincipal();
NS_ENSURE_SUCCESS(rv, rv);
// XXX TBI: handle @rule types
mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE);

View File

@ -186,6 +186,11 @@ protected:
nsresult WillDirty();
void DidDirty();
// Return success if the subject principal subsumes the principal of our
// inner, error otherwise. This will also succeed if the subject has
// UniversalBrowserWrite.
nsresult SubjectSubsumesInnerPrincipal() const;
protected:
nsString mTitle;
nsCOMPtr<nsMediaList> mMedia;

View File

@ -435,9 +435,10 @@ nsCSSValue::Image::Image(nsIURI* aURI, nsStringBuffer* aString,
MOZ_COUNT_CTOR(nsCSSValue::Image);
if (mURI &&
nsContentUtils::CanLoadImage(mURI, aDocument, aDocument)) {
nsContentUtils::LoadImage(mURI, aDocument, aReferrer, nsnull,
nsIRequest::LOAD_NORMAL,
nsContentUtils::CanLoadImage(mURI, aDocument, aDocument,
aOriginPrincipal)) {
nsContentUtils::LoadImage(mURI, aDocument, aOriginPrincipal, aReferrer,
nsnull, nsIRequest::LOAD_NORMAL,
getter_AddRefs(mRequest));
}
}

View File

@ -265,9 +265,10 @@ nsImageBoxFrame::UpdateImage()
doc,
baseURI);
if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc)) {
nsContentUtils::LoadImage(uri, doc, doc->GetDocumentURI(),
mListener, mLoadFlags,
if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc,
mContent->NodePrincipal())) {
nsContentUtils::LoadImage(uri, doc, mContent->NodePrincipal(),
doc->GetDocumentURI(), mListener, mLoadFlags,
getter_AddRefs(mImageRequest));
}
} else {

View File

@ -2125,9 +2125,13 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIndex, nsTreeColumn* aCol, PRBool aUseCont
if (!srcURI)
return NS_ERROR_FAILURE;
if (nsContentUtils::CanLoadImage(srcURI, mContent, doc)) {
// XXXbz what's the origin principal for this stuff that comes from our
// view? I guess we should assume that it's the node's principal...
if (nsContentUtils::CanLoadImage(srcURI, mContent, doc,
mContent->NodePrincipal())) {
nsresult rv = nsContentUtils::LoadImage(srcURI,
doc,
mContent->NodePrincipal(),
doc->GetDocumentURI(),
imgDecoderObserver,
nsIRequest::LOAD_NORMAL,