mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1406278: Part 4 - Use subject principal as triggering principal in <iframe>/<frame> "src" attribute r=bz
MozReview-Commit-ID: AgxZmfRvfTR --HG-- extra : rebase_source : 5663f54ae3d03870d38107e1703902df5ade4b10
This commit is contained in:
parent
0641eb51a8
commit
154e5011a0
@ -57,6 +57,7 @@
|
||||
#include "nsBaseWidget.h"
|
||||
#include "GroupedSHistory.h"
|
||||
#include "PartialSHistory.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsIURL.h"
|
||||
@ -85,6 +86,7 @@
|
||||
#include "mozilla/dom/FrameLoaderBinding.h"
|
||||
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
||||
#include "mozilla/layout/RenderFrameParent.h"
|
||||
#include "nsGenericHTMLFrameElement.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
@ -246,6 +248,7 @@ nsFrameLoader::LoadFrame()
|
||||
NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsAutoString src;
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
|
||||
bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
|
||||
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
|
||||
@ -253,7 +256,7 @@ nsFrameLoader::LoadFrame()
|
||||
src.AssignLiteral("about:srcdoc");
|
||||
}
|
||||
else {
|
||||
GetURL(src);
|
||||
GetURL(src, getter_AddRefs(principal));
|
||||
|
||||
src.Trim(" \t\n\r");
|
||||
|
||||
@ -293,7 +296,7 @@ nsFrameLoader::LoadFrame()
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = LoadURI(uri);
|
||||
rv = LoadURI(uri, principal);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -329,6 +332,12 @@ nsFrameLoader::LoadURI(nsIURI* aURI, ErrorResult& aRv)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::LoadURI(nsIURI* aURI)
|
||||
{
|
||||
return LoadURI(aURI, nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal)
|
||||
{
|
||||
if (!aURI)
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
@ -342,14 +351,16 @@ nsFrameLoader::LoadURI(nsIURI* aURI)
|
||||
// that's under our control. We will already have done the security checks for
|
||||
// loading the plugin content itself in the object/embed loading code.
|
||||
if (!IsForJSPlugin()) {
|
||||
rv = CheckURILoad(aURI);
|
||||
rv = CheckURILoad(aURI, aTriggeringPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
mURIToLoad = aURI;
|
||||
mTriggeringPrincipal = aTriggeringPrincipal;
|
||||
rv = doc->InitializeFrameLoader(this);
|
||||
if (NS_FAILED(rv)) {
|
||||
mURIToLoad = nullptr;
|
||||
mTriggeringPrincipal = nullptr;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -904,7 +915,7 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
"MaybeCreateDocShell succeeded with a null mDocShell");
|
||||
|
||||
// Just to be safe, recheck uri.
|
||||
rv = CheckURILoad(mURIToLoad);
|
||||
rv = CheckURILoad(mURIToLoad, mTriggeringPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
|
||||
@ -918,7 +929,11 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
// We'll use our principal, not that of the document loaded inside us. This
|
||||
// is very important; needed to prevent XSS attacks on documents loaded in
|
||||
// subframes!
|
||||
loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
|
||||
if (mTriggeringPrincipal) {
|
||||
loadInfo->SetTriggeringPrincipal(mTriggeringPrincipal);
|
||||
} else {
|
||||
loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
|
||||
@ -989,7 +1004,7 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::CheckURILoad(nsIURI* aURI)
|
||||
nsFrameLoader::CheckURILoad(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal)
|
||||
{
|
||||
// Check for security. The fun part is trying to figure out what principals
|
||||
// to use. The way I figure it, if we're doing a LoadFrame() accidentally
|
||||
@ -1008,7 +1023,9 @@ nsFrameLoader::CheckURILoad(nsIURI* aURI)
|
||||
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
|
||||
|
||||
// Get our principal
|
||||
nsIPrincipal* principal = mOwnerContent->NodePrincipal();
|
||||
nsIPrincipal* principal = (aTriggeringPrincipal
|
||||
? aTriggeringPrincipal
|
||||
: mOwnerContent->NodePrincipal());
|
||||
|
||||
// Check if we are allowed to load absURL
|
||||
nsresult rv =
|
||||
@ -2732,7 +2749,7 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::GetURL(nsString& aURI)
|
||||
nsFrameLoader::GetURL(nsString& aURI, nsIPrincipal** aTriggeringPrincipal)
|
||||
{
|
||||
aURI.Truncate();
|
||||
|
||||
@ -2740,6 +2757,10 @@ nsFrameLoader::GetURL(nsString& aURI)
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, aURI);
|
||||
} else {
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, aURI);
|
||||
if (RefPtr<nsGenericHTMLFrameElement> frame = do_QueryObject(mOwnerContent)) {
|
||||
nsCOMPtr<nsIPrincipal> prin = frame->GetSrcTriggeringPrincipal();
|
||||
prin.forget(aTriggeringPrincipal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,16 @@ public:
|
||||
|
||||
void LoadURI(nsIURI* aURI, mozilla::ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Triggers a load of the given URI.
|
||||
*
|
||||
* @param aURI The URI to load.
|
||||
* @param aTriggeringPrincipal The triggering principal for the load. May be
|
||||
* null, in which case the node principal of the owner content will be
|
||||
* used.
|
||||
*/
|
||||
nsresult LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal);
|
||||
|
||||
void SetIsPrerendered(mozilla::ErrorResult& aRv);
|
||||
|
||||
void MakePrerenderedLoaderActive(mozilla::ErrorResult& aRv);
|
||||
@ -324,7 +334,7 @@ public:
|
||||
*/
|
||||
void ApplySandboxFlags(uint32_t sandboxFlags);
|
||||
|
||||
void GetURL(nsString& aURL);
|
||||
void GetURL(nsString& aURL, nsIPrincipal** aTriggeringPrincipal);
|
||||
|
||||
// Properly retrieves documentSize of any subdocument type.
|
||||
nsresult GetWindowDimensions(nsIntRect& aRect);
|
||||
@ -384,7 +394,16 @@ private:
|
||||
// Updates the subdocument position and size. This gets called only
|
||||
// when we have our own in-process DocShell.
|
||||
void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);
|
||||
nsresult CheckURILoad(nsIURI* aURI);
|
||||
|
||||
/**
|
||||
* Checks whether a load of the given URI should be allowed, and returns an
|
||||
* error result if it should not.
|
||||
*
|
||||
* @param aURI The URI to check.
|
||||
* @param aTriggeringPrincipal The triggering principal for the load. May be
|
||||
* null, in which case the node principal of the owner content is used.
|
||||
*/
|
||||
nsresult CheckURILoad(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal);
|
||||
void FireErrorEvent();
|
||||
nsresult ReallyStartLoadingInternal();
|
||||
|
||||
@ -430,6 +449,7 @@ private:
|
||||
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
nsCOMPtr<nsIURI> mURIToLoad;
|
||||
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
|
||||
mozilla::dom::Element* mOwnerContent; // WEAK
|
||||
|
||||
// After the frameloader has been removed from the DOM but before all of the
|
||||
|
@ -42,7 +42,7 @@ function runTest2() {
|
||||
wrappedFrame.addEventListener("mozbrowserloadend", function onloadend(e) {
|
||||
ok(wrappedFrame.contentWindow.document.location.href.endsWith(HTTP_URI),
|
||||
"http: URI navigation should be allowed");
|
||||
wrappedFrame.src = DATA_URI
|
||||
frame.src = DATA_URI
|
||||
|
||||
// wait for 1000ms and check that the data: URI did not load
|
||||
setTimeout(function () {
|
||||
@ -51,7 +51,7 @@ function runTest2() {
|
||||
"data: URI navigation should be blocked");
|
||||
SimpleTest.finish();
|
||||
}, 1000);
|
||||
});
|
||||
}, {once: true});
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest1);
|
||||
|
@ -99,13 +99,13 @@ public:
|
||||
SetHTMLAttr(nsGkAtoms::scrolling, aScrolling, aError);
|
||||
}
|
||||
|
||||
void GetSrc(nsAString& aSrc) const
|
||||
void GetSrc(nsString& aSrc, nsIPrincipal&)
|
||||
{
|
||||
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
|
||||
}
|
||||
void SetSrc(const nsAString& aSrc, ErrorResult& aError)
|
||||
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
|
||||
{
|
||||
SetAttrHelper(nsGkAtoms::src, aSrc);
|
||||
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
|
||||
}
|
||||
|
||||
using nsGenericHTMLFrameElement::GetContentDocument;
|
||||
|
@ -45,13 +45,13 @@ public:
|
||||
uint32_t GetSandboxFlags();
|
||||
|
||||
// Web IDL binding methods
|
||||
void GetSrc(nsAString& aSrc) const
|
||||
void GetSrc(nsString& aSrc, nsIPrincipal&) const
|
||||
{
|
||||
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
|
||||
}
|
||||
void SetSrc(const nsAString& aSrc, ErrorResult& aError)
|
||||
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
|
||||
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
|
||||
}
|
||||
void GetSrcdoc(DOMString& aSrcdoc)
|
||||
{
|
||||
|
@ -53,7 +53,8 @@ NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(nsGenericHTMLFrameElement,
|
||||
nsGenericHTMLElement,
|
||||
nsIFrameLoaderOwner,
|
||||
nsIDOMMozBrowserFrame,
|
||||
nsIMozBrowserFrame)
|
||||
nsIMozBrowserFrame,
|
||||
nsGenericHTMLFrameElement)
|
||||
|
||||
NS_IMPL_BOOL_ATTR(nsGenericHTMLFrameElement, Mozbrowser, mozbrowser)
|
||||
|
||||
@ -332,14 +333,14 @@ PrincipalAllowsBrowserFrame(nsIPrincipal* aPrincipal)
|
||||
nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
const nsAttrValue* aOldValue,
|
||||
nsIPrincipal* aSubjectPrincipal,
|
||||
nsIPrincipal* aMaybeScriptedPrincipal,
|
||||
bool aNotify)
|
||||
{
|
||||
if (aValue) {
|
||||
nsAttrValueOrString value(aValue);
|
||||
AfterMaybeChangeAttr(aNameSpaceID, aName, &value, aNotify);
|
||||
AfterMaybeChangeAttr(aNameSpaceID, aName, &value, aMaybeScriptedPrincipal, aNotify);
|
||||
} else {
|
||||
AfterMaybeChangeAttr(aNameSpaceID, aName, nullptr, aNotify);
|
||||
AfterMaybeChangeAttr(aNameSpaceID, aName, nullptr, aMaybeScriptedPrincipal, aNotify);
|
||||
}
|
||||
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
@ -372,7 +373,7 @@ nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
|
||||
aOldValue, aSubjectPrincipal, aNotify);
|
||||
aOldValue, aMaybeScriptedPrincipal, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -381,7 +382,7 @@ nsGenericHTMLFrameElement::OnAttrSetButNotChanged(int32_t aNamespaceID,
|
||||
const nsAttrValueOrString& aValue,
|
||||
bool aNotify)
|
||||
{
|
||||
AfterMaybeChangeAttr(aNamespaceID, aName, &aValue, aNotify);
|
||||
AfterMaybeChangeAttr(aNamespaceID, aName, &aValue, nullptr, aNotify);
|
||||
|
||||
return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName,
|
||||
aValue, aNotify);
|
||||
@ -391,10 +392,13 @@ void
|
||||
nsGenericHTMLFrameElement::AfterMaybeChangeAttr(int32_t aNamespaceID,
|
||||
nsAtom* aName,
|
||||
const nsAttrValueOrString* aValue,
|
||||
nsIPrincipal* aMaybeScriptedPrincipal,
|
||||
bool aNotify)
|
||||
{
|
||||
if (aNamespaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::src) {
|
||||
mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
|
||||
this, aValue ? aValue->String() : EmptyString(), aMaybeScriptedPrincipal);
|
||||
if (aValue && (!IsHTMLElement(nsGkAtoms::iframe) ||
|
||||
!HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc))) {
|
||||
// Don't propagate error here. The attribute was successfully set,
|
||||
|
@ -19,6 +19,10 @@
|
||||
|
||||
class nsXULElement;
|
||||
|
||||
#define NS_GENERICHTMLFRAMEELEMENT_IID \
|
||||
{ 0x8190db72, 0xdab0, 0x4d72, \
|
||||
{ 0x94, 0x26, 0x87, 0x5f, 0x5a, 0x8a, 0x2a, 0xe5 } }
|
||||
|
||||
/**
|
||||
* A helper class for frame elements
|
||||
*/
|
||||
@ -46,6 +50,8 @@ public:
|
||||
NS_DECL_NSIDOMMOZBROWSERFRAME
|
||||
NS_DECL_NSIMOZBROWSERFRAME
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_GENERICHTMLFRAMEELEMENT_IID)
|
||||
|
||||
// nsIContent
|
||||
virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
@ -89,6 +95,11 @@ public:
|
||||
*/
|
||||
static int32_t MapScrollingAttribute(const nsAttrValue* aValue);
|
||||
|
||||
nsIPrincipal* GetSrcTriggeringPrincipal() const
|
||||
{
|
||||
return mSrcTriggeringPrincipal;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~nsGenericHTMLFrameElement();
|
||||
|
||||
@ -112,6 +123,8 @@ protected:
|
||||
RefPtr<nsFrameLoader> mFrameLoader;
|
||||
nsCOMPtr<nsPIDOMWindowOuter> mOpenerWindow;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
|
||||
|
||||
/**
|
||||
* True when the element is created by the parser using the
|
||||
* NS_FROM_PARSER_NETWORK flag.
|
||||
@ -142,7 +155,12 @@ private:
|
||||
* @param aNotify Whether we plan to notify document observers.
|
||||
*/
|
||||
void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName,
|
||||
const nsAttrValueOrString* aValue, bool aNotify);
|
||||
const nsAttrValueOrString* aValue,
|
||||
nsIPrincipal* aMaybeScriptedPrincipal,
|
||||
bool aNotify);
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsGenericHTMLFrameElement,
|
||||
NS_GENERICHTMLFRAMEELEMENT_IID)
|
||||
|
||||
#endif // nsGenericHTMLFrameElement_h
|
||||
|
@ -17,7 +17,7 @@ interface HTMLFrameElement : HTMLElement {
|
||||
attribute DOMString name;
|
||||
[CEReactions, SetterThrows]
|
||||
attribute DOMString scrolling;
|
||||
[CEReactions, SetterThrows]
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows]
|
||||
attribute DOMString src;
|
||||
[CEReactions, SetterThrows]
|
||||
attribute DOMString frameBorder;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
[HTMLConstructor]
|
||||
interface HTMLIFrameElement : HTMLElement {
|
||||
[CEReactions, SetterThrows, Pure]
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows, Pure]
|
||||
attribute DOMString src;
|
||||
[CEReactions, SetterThrows, Pure]
|
||||
attribute DOMString srcdoc;
|
||||
|
@ -112,7 +112,9 @@ add_task(async function test_web_accessible_resources() {
|
||||
browser.runtime.onMessage.addListener(([msg, url], sender, respond) => {
|
||||
if (msg == "load-iframe") {
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("src", url);
|
||||
// Set the src via wrappedJSObject so the load is triggered with the
|
||||
// content page's principal rather than ours.
|
||||
iframe.wrappedJSObject.setAttribute("src", url);
|
||||
iframe.addEventListener("load", () => { respond(true); });
|
||||
iframe.addEventListener("error", () => { respond(false); });
|
||||
document.body.appendChild(iframe);
|
||||
|
@ -433,6 +433,11 @@ add_task(async function test_contentscript_triggeringPrincipals() {
|
||||
* {@see getElementData}.
|
||||
*/
|
||||
const TESTS = [
|
||||
// TODO: <frame> element, which requires a frameset document.
|
||||
{
|
||||
element: ["iframe", {}],
|
||||
src: "iframe.html",
|
||||
},
|
||||
{
|
||||
element: ["img", {}],
|
||||
src: "img.png",
|
||||
|
Loading…
Reference in New Issue
Block a user