diff options
-rw-r--r-- | dom/security/nsContentSecurityManager.cpp | 81 | ||||
-rw-r--r-- | netwerk/base/nsNetUtil.cpp | 14 |
2 files changed, 68 insertions, 27 deletions
diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 0cc4933fe..70e574445 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -10,6 +10,9 @@ #include "nsIStreamListener.h" #include "nsIDocument.h" #include "nsMixedContentBlocker.h" +#include "nsCDefaultURIFixup.h" +#include "nsIURIFixup.h" +#include "nsINestedURI.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/TabChild.h" @@ -244,10 +247,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 +254,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 +305,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 +479,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 +652,30 @@ 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) { + // query the nested URI for security checks like in the case of view-source + nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(uri); + if (nestedURI) { + nestedURI->GetInnerURI(getter_AddRefs(uri)); + } + + // 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) { diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp index 8ff3e788f..bc9bcf88a 100644 --- a/netwerk/base/nsNetUtil.cpp +++ b/netwerk/base/nsNetUtil.cpp @@ -1285,16 +1285,10 @@ NS_HasBeenCrossOrigin(nsIChannel* aChannel, bool aReport) nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); MOZ_RELEASE_ASSERT(loadInfo, "Origin tracking only works for channels created with a loadinfo"); -#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 - - MOZ_ASSERT(skipContentTypeCheck || - loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT, - "calling NS_HasBeenCrossOrigin on a top level load"); + // TYPE_DOCUMENT loads have a null LoadingPrincipal and can not be cross origin. + if (!loadInfo->LoadingPrincipal()) { + return false; + } // Always treat tainted channels as cross-origin. if (loadInfo->GetTainting() != LoadTainting::Basic) { |