summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
Diffstat (limited to 'dom')
-rw-r--r--dom/base/nsContentUtils.cpp8
-rw-r--r--dom/base/nsGlobalWindow.cpp9
-rw-r--r--dom/base/test/file_simplecontentpolicy.js1
-rw-r--r--dom/jsurl/nsJSProtocolHandler.cpp49
-rw-r--r--dom/plugins/base/nsPluginInstanceOwner.cpp25
-rw-r--r--dom/plugins/test/mochitest/test_bug813906.html22
-rw-r--r--dom/security/nsContentSecurityManager.cpp74
7 files changed, 119 insertions, 69 deletions
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index bc8cea35a..34c7d23b8 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -5104,7 +5104,7 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
handler->OnLinkClick(aContent, aLinkURI,
fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
- fileName, nullptr, nullptr, aIsTrusted);
+ fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
}
}
@@ -9776,9 +9776,13 @@ nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
rv = aChannel->GetReferrer(getter_AddRefs(referrer));
NS_ENSURE_SUCCESS(rv, false);
+ nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
+ nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal();
+
// Actually perform the cross process load
bool reloadSucceeded = false;
- rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer, &reloadSucceeded);
+ rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer,
+ triggeringPrincipal, &reloadSucceeded);
NS_ENSURE_SUCCESS(rv, false);
return reloadSucceeded;
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index 738703ef1..4ffccde9d 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2521,8 +2521,13 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument)
return false;
}
- NS_ASSERTION(NS_IsAboutBlank(mDoc->GetDocumentURI()),
- "How'd this happen?");
+#ifdef DEBUG
+{
+ nsCOMPtr<nsIURI> uri;
+ mDoc->GetDocumentURI()->CloneIgnoringRef(getter_AddRefs(uri));
+ NS_ASSERTION(NS_IsAboutBlank(uri), "How'd this happen?");
+}
+#endif
// Great, we're the original document, check for one of the other
// conditions.
diff --git a/dom/base/test/file_simplecontentpolicy.js b/dom/base/test/file_simplecontentpolicy.js
index 1f9606c49..2727b9530 100644
--- a/dom/base/test/file_simplecontentpolicy.js
+++ b/dom/base/test/file_simplecontentpolicy.js
@@ -39,7 +39,6 @@ var policy = {
{
// Remember last content type seen for the test url
if (contentLocation.spec.endsWith(urlSuffix)) {
- assert.ok(frame === browserElement, "correct <browser> element");
sendAsyncMessage("shouldLoad", {contentType: contentType, isTopLevel: isTopLevel});
return Ci.nsIContentPolicy.REJECT_REQUEST;
}
diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp
index cdb63f890..90171db10 100644
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -36,7 +36,6 @@
#include "nsIContentViewer.h"
#include "nsIXPConnect.h"
#include "nsContentUtils.h"
-#include "nsNullPrincipal.h"
#include "nsJSUtils.h"
#include "nsThreadUtils.h"
#include "nsIScriptChannel.h"
@@ -336,7 +335,7 @@ public:
NS_FORWARD_SAFE_NSIPROPERTYBAG(mPropertyBag)
NS_FORWARD_SAFE_NSIPROPERTYBAG2(mPropertyBag)
- nsresult Init(nsIURI *aURI);
+ nsresult Init(nsIURI *aURI, nsILoadInfo* aLoadInfo);
// Actually evaluate the script.
void EvaluateScript();
@@ -354,17 +353,16 @@ protected:
nsCOMPtr<nsIChannel> mStreamChannel;
nsCOMPtr<nsIPropertyBag2> mPropertyBag;
nsCOMPtr<nsIStreamListener> mListener; // Our final listener
- nsCOMPtr<nsISupports> mContext; // The context passed to AsyncOpen
nsCOMPtr<nsPIDOMWindowInner> mOriginalInnerWindow; // The inner window our load
// started against.
- // If we blocked onload on a document in AsyncOpen, this is the document we
+ // If we blocked onload on a document in AsyncOpen2, this is the document we
// did it on.
nsCOMPtr<nsIDocument> mDocumentOnloadBlockedOn;
nsresult mStatus; // Our status
nsLoadFlags mLoadFlags;
- nsLoadFlags mActualLoadFlags; // See AsyncOpen
+ nsLoadFlags mActualLoadFlags; // See AsyncOpen2
RefPtr<nsJSThunk> mIOThunk;
PopupControlState mPopupState;
@@ -404,7 +402,7 @@ nsresult nsJSChannel::StopAll()
return rv;
}
-nsresult nsJSChannel::Init(nsIURI *aURI)
+nsresult nsJSChannel::Init(nsIURI* aURI, nsILoadInfo* aLoadInfo)
{
RefPtr<nsJSURI> jsURI;
nsresult rv = aURI->QueryInterface(kJSURICID,
@@ -418,21 +416,13 @@ nsresult nsJSChannel::Init(nsIURI *aURI)
// Remember, until AsyncOpen is called, the script will not be evaluated
// and the underlying Input Stream will not be created...
nsCOMPtr<nsIChannel> channel;
-
- nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();
-
- // If the resultant script evaluation actually does return a value, we
- // treat it as html.
- // The following channel is never openend, so it does not matter what
- // securityFlags we pass; let's follow the principle of least privilege.
- rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
- aURI,
- mIOThunk,
- nullPrincipal,
- nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
- nsIContentPolicy::TYPE_OTHER,
- NS_LITERAL_CSTRING("text/html"));
- if (NS_FAILED(rv)) return rv;
+ rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
+ aURI,
+ mIOThunk,
+ NS_LITERAL_CSTRING("text/html"),
+ EmptyCString(),
+ aLoadInfo);
+ NS_ENSURE_SUCCESS(rv, rv);
rv = mIOThunk->Init(aURI);
if (NS_SUCCEEDED(rv)) {
@@ -563,6 +553,7 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
"security flags in loadInfo but asyncOpen2() not called");
}
#endif
+ MOZ_RELEASE_ASSERT(!aContext, "please call AsyncOpen2()");
NS_ENSURE_ARG(aListener);
@@ -584,7 +575,6 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
}
mListener = aListener;
- mContext = aContext;
mIsActive = true;
@@ -655,7 +645,7 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
return mStatus;
}
- // We're returning success from asyncOpen(), but we didn't open a
+ // We're returning success from asyncOpen2(), but we didn't open a
// stream channel. We'll have to notify ourselves, but make sure to do
// it asynchronously.
method = &nsJSChannel::NotifyListener;
@@ -772,7 +762,7 @@ nsJSChannel::EvaluateScript()
return;
}
- mStatus = mStreamChannel->AsyncOpen(this, mContext);
+ mStatus = mStreamChannel->AsyncOpen2(this);
if (NS_SUCCEEDED(mStatus)) {
// mStreamChannel will call OnStartRequest and OnStopRequest on
// us, so we'll be sure to call them on our listener.
@@ -800,8 +790,8 @@ nsJSChannel::EvaluateScript()
void
nsJSChannel::NotifyListener()
{
- mListener->OnStartRequest(this, mContext);
- mListener->OnStopRequest(this, mContext, mStatus);
+ mListener->OnStartRequest(this, nullptr);
+ mListener->OnStopRequest(this, nullptr, mStatus);
CleanupStrongRefs();
}
@@ -810,7 +800,6 @@ void
nsJSChannel::CleanupStrongRefs()
{
mListener = nullptr;
- mContext = nullptr;
mOriginalInnerWindow = nullptr;
if (mDocumentOnloadBlockedOn) {
mDocumentOnloadBlockedOn->UnblockOnload(false);
@@ -1240,11 +1229,7 @@ nsJSProtocolHandler::NewChannel2(nsIURI* uri,
return NS_ERROR_OUT_OF_MEMORY;
}
- rv = channel->Init(uri);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // set the loadInfo on the new channel
- rv = channel->SetLoadInfo(aLoadInfo);
+ rv = channel->Init(uri, aLoadInfo);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_SUCCEEDED(rv)) {
diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp
index 291ae576d..d5b1eb9ea 100644
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -535,16 +535,6 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- if (aDoCheckLoadURIChecks) {
- nsCOMPtr<nsIScriptSecurityManager> secMan(
- do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
- NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
-
- rv = secMan->CheckLoadURIWithPrincipal(content->NodePrincipal(), uri,
- nsIScriptSecurityManager::STANDARD);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
nsCOMPtr<nsIInputStream> headersDataStream;
if (aPostStream && aHeadersData) {
if (!aHeadersDataLen)
@@ -563,8 +553,21 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
Preferences::GetInt("privacy.popups.disable_from_plugins");
nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
+
+ // if security checks (in particular CheckLoadURIWithPrincipal) needs
+ // to be skipped we are creating a codebasePrincipal to make sure
+ // that security check succeeds. Please note that we do not want to
+ // fall back to using the systemPrincipal, because that would also
+ // bypass ContentPolicy checks which should still be enforced.
+ nsCOMPtr<nsIPrincipal> triggeringPrincipal;
+ if (!aDoCheckLoadURIChecks) {
+ mozilla::PrincipalOriginAttributes attrs =
+ BasePrincipal::Cast(content->NodePrincipal())->OriginAttributesRef();
+ triggeringPrincipal = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
+ }
+
rv = lh->OnLinkClick(content, uri, unitarget.get(), NullString(),
- aPostStream, headersDataStream, true);
+ aPostStream, headersDataStream, true, triggeringPrincipal);
return rv;
}
diff --git a/dom/plugins/test/mochitest/test_bug813906.html b/dom/plugins/test/mochitest/test_bug813906.html
index 04c34daaf..d18dbbff2 100644
--- a/dom/plugins/test/mochitest/test_bug813906.html
+++ b/dom/plugins/test/mochitest/test_bug813906.html
@@ -18,21 +18,35 @@ function f() {
</script>
<script type="application/javascript">
+SimpleTest.requestFlakyTimeout(
+ "Blocking an iframe does not cause the onerror event to be fired");
+
SimpleTest.waitForExplicitFinish();
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
var frameLoadCount = 0;
+
+function frameNavBlocked() {
+ isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'),
+ 0, 'plugin shouldnt be able to cause navigation to chrome URLs');
+ SimpleTest.finish();
+}
+
function frameLoaded() {
frameLoadCount++;
if (frameLoadCount == 1) {
document.getElementsByTagName("object")[0].type = "application/x-test";
document.getElementsByTagName("use")[0].setAttributeNS("http://www.w3.org/1999/xlink", "href", location.href + "#a");
- } else if (frameLoadCount == 2) {
- isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'),
- 0, 'plugin shouldnt be able to cause navigation to chrome URLs');
- SimpleTest.finish();
+
+ // wait two seconds and verify that frame navigation did not succeed
+ setTimeout(frameNavBlocked, 2000);
+ return;
}
+ // we should never get here, but just in case, make sure the test fails in that case.
+ ok(false, "onload() event should not fire for blocked navigation");
+ SimpleTest.finish();
}
+
</script>
<!-- Note that <svg:use> ends up creating an anonymous subtree, which means that the plugin
diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp
index 0cc4933fe..c6558fc93 100644
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -10,6 +10,8 @@
#include "nsIStreamListener.h"
#include "nsIDocument.h"
#include "nsMixedContentBlocker.h"
+#include "nsCDefaultURIFixup.h"
+#include "nsIURIFixup.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabChild.h"
@@ -244,10 +246,6 @@ DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
static nsresult
DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
{
- nsCOMPtr<nsIURI> uri;
- nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
- NS_ENSURE_SUCCESS(rv, rv);
-
nsContentPolicyType contentPolicyType =
aLoadInfo->GetExternalContentPolicyType();
nsContentPolicyType internalContentPolicyType =
@@ -255,12 +253,24 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
nsCString mimeTypeGuess;
nsCOMPtr<nsISupports> requestingContext = nullptr;
-#ifdef DEBUG
- // Don't enforce TYPE_DOCUMENT assertions for loads
- // initiated by javascript tests.
- bool skipContentTypeCheck = false;
- skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion");
-#endif
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+ contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
+ // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
+ // be wyciwyg:// channels. Let's fix up the URI so we can
+ // perform proper security checks.
+ nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
+ if (NS_SUCCEEDED(rv) && urifixup) {
+ nsCOMPtr<nsIURI> fixedURI;
+ rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
+ if (NS_SUCCEEDED(rv)) {
+ uri = fixedURI;
+ }
+ }
+ }
switch(contentPolicyType) {
case nsIContentPolicy::TYPE_OTHER: {
@@ -294,16 +304,14 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
}
case nsIContentPolicy::TYPE_DOCUMENT: {
- MOZ_ASSERT(skipContentTypeCheck || false, "contentPolicyType not supported yet");
+ mimeTypeGuess = EmptyCString();
+ requestingContext = aLoadInfo->LoadingNode();
break;
}
case nsIContentPolicy::TYPE_SUBDOCUMENT: {
mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
requestingContext = aLoadInfo->LoadingNode();
- MOZ_ASSERT(!requestingContext ||
- requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
- "type_subdocument requires requestingContext of type Document");
break;
}
@@ -470,18 +478,32 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
MOZ_ASSERT(false, "can not perform security check without a valid contentType");
}
+ // For document loads we use the triggeringPrincipal as the originPrincipal.
+ // Note the the loadingPrincipal for loads of TYPE_DOCUMENT is a nullptr.
+ nsCOMPtr<nsIPrincipal> principal =
+ (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+ contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)
+ ? aLoadInfo->TriggeringPrincipal()
+ : aLoadInfo->LoadingPrincipal();
+
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
uri,
- aLoadInfo->LoadingPrincipal(),
+ principal,
requestingContext,
mimeTypeGuess,
nullptr, //extra,
&shouldLoad,
nsContentUtils::GetContentPolicy(),
nsContentUtils::GetSecurityManager());
- NS_ENSURE_SUCCESS(rv, rv);
- if (NS_CP_REJECTED(shouldLoad)) {
+
+ if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
+ if ((NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) &&
+ (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+ contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)) {
+ // for docshell loads we might have to return SHOW_ALT.
+ return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
+ }
return NS_ERROR_CONTENT_BLOCKED;
}
@@ -629,6 +651,24 @@ nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
+ nsContentPolicyType contentPolicyType =
+ loadInfo->GetExternalContentPolicyType();
+
+ if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
+ contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
+ // TYPE_DOCUMENT and TYPE_SUBDOCUMENT loads might potentially
+ // be wyciwyg:// channels. Let's fix up the URI so we can
+ // perform proper security checks.
+ nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
+ if (NS_SUCCEEDED(rv) && urifixup) {
+ nsCOMPtr<nsIURI> fixedURI;
+ rv = urifixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
+ if (NS_SUCCEEDED(rv)) {
+ uri = fixedURI;
+ }
+ }
+ }
+
// Handle cookie policies
uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {