summaryrefslogtreecommitdiffstats
path: root/docshell/base/nsDocShell.cpp
diff options
context:
space:
mode:
authorMoonchild <mcwerewolf@gmail.com>2018-04-23 11:46:21 +0200
committerGitHub <noreply@github.com>2018-04-23 11:46:21 +0200
commit8ed46f424e1a8a09bad7147882b83c9b2aad17c6 (patch)
tree5c6953fd44fddb74891ddd96613f1ef949c85fd7 /docshell/base/nsDocShell.cpp
parent8ffac11aa6eb32be75ff049787191e12476586d3 (diff)
parentccbd5ecf57fcd53ac8b28ddf7466b6c930f764df (diff)
downloadUXP-8ed46f424e1a8a09bad7147882b83c9b2aad17c6.tar
UXP-8ed46f424e1a8a09bad7147882b83c9b2aad17c6.tar.gz
UXP-8ed46f424e1a8a09bad7147882b83c9b2aad17c6.tar.lz
UXP-8ed46f424e1a8a09bad7147882b83c9b2aad17c6.tar.xz
UXP-8ed46f424e1a8a09bad7147882b83c9b2aad17c6.zip
Merge pull request #231 from janekptacijarabaci/security_blocking_data_1
moebius#223, #224, #226, #230: DOM - consider blocking top level window data: URIs
Diffstat (limited to 'docshell/base/nsDocShell.cpp')
-rw-r--r--docshell/base/nsDocShell.cpp111
1 files changed, 78 insertions, 33 deletions
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 58c182cbb..bd2a8a433 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -42,6 +42,7 @@
#include "nsArray.h"
#include "nsArrayUtils.h"
+#include "nsContentSecurityManager.h"
#include "nsICaptivePortalService.h"
#include "nsIDOMStorage.h"
#include "nsIContentViewer.h"
@@ -138,6 +139,7 @@
#include "nsISiteSecurityService.h"
#include "nsStructuredCloneContainer.h"
#include "nsIStructuredCloneContainer.h"
+#include "nsISupportsPrimitives.h"
#ifdef MOZ_PLACES
#include "nsIFaviconService.h"
#include "mozIPlacesPendingOperation.h"
@@ -1272,6 +1274,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
nsCOMPtr<nsISHEntry> shEntry;
nsXPIDLString target;
nsAutoString srcdoc;
+ bool forceAllowDataURI = false;
nsCOMPtr<nsIDocShell> sourceDocShell;
nsCOMPtr<nsIURI> baseURI;
@@ -1307,6 +1310,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
aLoadInfo->GetSrcdocData(srcdoc);
aLoadInfo->GetSourceDocShell(getter_AddRefs(sourceDocShell));
aLoadInfo->GetBaseURI(getter_AddRefs(baseURI));
+ aLoadInfo->GetForceAllowDataURI(&forceAllowDataURI);
}
#if defined(DEBUG)
@@ -1560,6 +1564,10 @@ nsDocShell::LoadURI(nsIURI* aURI,
flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
}
+ if (forceAllowDataURI) {
+ flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
+ }
+
return InternalLoad(aURI,
originalURI,
loadReplace,
@@ -4821,6 +4829,9 @@ nsDocShell::LoadURIWithOptions(const char16_t* aURI,
}
nsAutoPopupStatePusher statePusher(popupState);
+ bool forceAllowDataURI =
+ aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
+
// Don't pass certain flags that aren't needed and end up confusing
// ConvertLoadTypeToDocShellLoadInfo. We do need to ensure that they are
// passed to LoadURI though, since it uses them.
@@ -4850,6 +4861,7 @@ nsDocShell::LoadURIWithOptions(const char16_t* aURI,
loadInfo->SetReferrerPolicy(aReferrerPolicy);
loadInfo->SetHeadersStream(aHeaderStream);
loadInfo->SetBaseURI(aBaseURI);
+ loadInfo->SetForceAllowDataURI(forceAllowDataURI);
if (fixupInfo) {
nsAutoString searchProvider, keyword;
@@ -9884,49 +9896,49 @@ nsDocShell::InternalLoad(nsIURI* aURI,
contentType = nsIContentPolicy::TYPE_DOCUMENT;
}
- // If there's no targetDocShell, that means we are about to create a new window,
- // perform a content policy check before creating the window.
- if (!targetDocShell) {
- nsCOMPtr<Element> requestingElement;
+ // If there's no targetDocShell, that means we are about to create a new
+ // window (or aWindowTarget is empty). Perform a content policy check before
+ // creating the window. Please note for all other docshell loads
+ // content policy checks are performed within the contentSecurityManager
+ // when the channel is about to be openend.
+ if (!targetDocShell && !aWindowTarget.IsEmpty()) {
+ MOZ_ASSERT(contentType == nsIContentPolicy::TYPE_DOCUMENT,
+ "opening a new window requires type to be TYPE_DOCUMENT");
+
nsISupports* requestingContext = nullptr;
- if (contentType == nsIContentPolicy::TYPE_DOCUMENT) {
- if (XRE_IsContentProcess()) {
- // In e10s the child process doesn't have access to the element that
- // contains the browsing context (because that element is in the chrome
- // process). So we just pass mScriptGlobal.
- requestingContext = ToSupports(mScriptGlobal);
- } else {
- // This is for loading non-e10s tabs and toplevel windows of various
- // sorts.
- // For the toplevel window cases, requestingElement will be null.
- requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal();
- requestingContext = requestingElement;
- }
+ if (XRE_IsContentProcess()) {
+ // In e10s the child process doesn't have access to the element that
+ // contains the browsing context (because that element is in the chrome
+ // process). So we just pass mScriptGlobal.
+ requestingContext = ToSupports(mScriptGlobal);
} else {
- requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal();
+ // This is for loading non-e10s tabs and toplevel windows of various
+ // sorts.
+ // For the toplevel window cases, requestingElement will be null.
+ nsCOMPtr<Element> requestingElement =
+ mScriptGlobal->AsOuter()->GetFrameElementInternal();
requestingContext = requestingElement;
-
-#ifdef DEBUG
- if (requestingElement) {
- // Get the docshell type for requestingElement.
- nsCOMPtr<nsIDocument> requestingDoc = requestingElement->OwnerDoc();
- nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
-
- // requestingElement docshell type = current docshell type.
- MOZ_ASSERT(mItemType == elementDocShell->ItemType(),
- "subframes should have the same docshell type as their parent");
- }
-#endif
}
+ // Since Content Policy checks are performed within docShell as well as
+ // the ContentSecurityManager we need a reliable way to let certain
+ // nsIContentPolicy consumers ignore duplicate calls. Let's use the 'extra'
+ // argument to pass a specific identifier.
+ nsCOMPtr<nsISupportsString> extraStr =
+ do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ NS_NAMED_LITERAL_STRING(msg, "conPolCheckFromDocShell");
+ rv = extraStr->SetData(msg);
+ NS_ENSURE_SUCCESS(rv, rv);
+
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(contentType,
aURI,
aTriggeringPrincipal,
requestingContext,
EmptyCString(), // mime guess
- nullptr, // extra
+ extraStr, // extra
&shouldLoad);
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
@@ -10082,6 +10094,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
// principal to inherit is: it should be aTriggeringPrincipal.
loadInfo->SetPrincipalIsExplicit(true);
loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(LOAD_LINK));
+ loadInfo->SetForceAllowDataURI(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
rv = win->Open(NS_ConvertUTF8toUTF16(spec),
aWindowTarget, // window name
@@ -10232,8 +10245,11 @@ nsDocShell::InternalLoad(nsIURI* aURI,
}
}
+ bool loadFromExternal = false;
+
// Before going any further vet loads initiated by external programs.
if (aLoadType == LOAD_NORMAL_EXTERNAL) {
+ loadFromExternal = true;
// Disallow external chrome: loads targetted at content windows
bool isChrome = false;
if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) {
@@ -10724,7 +10740,9 @@ nsDocShell::InternalLoad(nsIURI* aURI,
nsINetworkPredictor::PREDICT_LOAD, this, nullptr);
nsCOMPtr<nsIRequest> req;
- rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, aReferrer,
+ rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, loadFromExternal,
+ (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI),
+ aReferrer,
!(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
aReferrerPolicy,
aTriggeringPrincipal, principalToInherit, aTypeHint,
@@ -10804,6 +10822,8 @@ nsresult
nsDocShell::DoURILoad(nsIURI* aURI,
nsIURI* aOriginalURI,
bool aLoadReplace,
+ bool aLoadFromExternal,
+ bool aForceAllowDataURI,
nsIURI* aReferrerURI,
bool aSendReferrer,
uint32_t aReferrerPolicy,
@@ -10880,17 +10900,40 @@ nsDocShell::DoURILoad(nsIURI* aURI,
nsCOMPtr<nsINode> loadingNode;
nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
nsCOMPtr<nsIPrincipal> loadingPrincipal;
+ nsCOMPtr<nsISupports> topLevelLoadingContext;
if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
loadingNode = nullptr;
loadingPrincipal = nullptr;
loadingWindow = mScriptGlobal->AsOuter();
+ if (XRE_IsContentProcess()) {
+ // In e10s the child process doesn't have access to the element that
+ // contains the browsing context (because that element is in the chrome
+ // process).
+ nsCOMPtr<nsITabChild> tabChild = GetTabChild();
+ topLevelLoadingContext = ToSupports(tabChild);
+ } else {
+ // This is for loading non-e10s tabs and toplevel windows of various
+ // sorts.
+ // For the toplevel window cases, requestingElement will be null.
+ nsCOMPtr<Element> requestingElement =
+ loadingWindow->GetFrameElementInternal();
+ topLevelLoadingContext = requestingElement;
+ }
} else {
loadingWindow = nullptr;
loadingNode = mScriptGlobal->AsOuter()->GetFrameElementInternal();
if (loadingNode) {
// If we have a loading node, then use that as our loadingPrincipal.
loadingPrincipal = loadingNode->NodePrincipal();
+#ifdef DEBUG
+ // Get the docshell type for requestingElement.
+ nsCOMPtr<nsIDocument> requestingDoc = loadingNode->OwnerDoc();
+ nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
+ // requestingElement docshell type = current docshell type.
+ MOZ_ASSERT(mItemType == elementDocShell->ItemType(),
+ "subframes should have the same docshell type as their parent");
+#endif
} else {
// If this isn't a top-level load and mScriptGlobal's frame element is
// null, then the element got removed from the DOM while we were trying
@@ -10940,7 +10983,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
nsCOMPtr<nsILoadInfo> loadInfo =
(aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ?
- new LoadInfo(loadingWindow, aTriggeringPrincipal,
+ new LoadInfo(loadingWindow, aTriggeringPrincipal, topLevelLoadingContext,
securityFlags) :
new LoadInfo(loadingPrincipal, aTriggeringPrincipal, loadingNode,
securityFlags, aContentPolicyType);
@@ -10948,6 +10991,8 @@ nsDocShell::DoURILoad(nsIURI* aURI,
if (aPrincipalToInherit) {
loadInfo->SetPrincipalToInherit(aPrincipalToInherit);
}
+ loadInfo->SetLoadTriggeredFromExternal(aLoadFromExternal);
+ loadInfo->SetForceAllowDataURI(aForceAllowDataURI);
// We have to do this in case our OriginAttributes are different from the
// OriginAttributes of the parent document. Or in case there isn't a