From 1b4c4256ee7705724b02919b4d432b2a391bcd04 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 18:51:38 +0200 Subject: moebius#223: Consider blocking top level window data: URIs (part 1/3 without tests) https://github.com/MoonchildProductions/moebius/pull/223 --- .../en-US/chrome/security/security.properties | 3 + dom/security/nsContentSecurityManager.cpp | 84 ++++++++++++++++++++ dom/security/nsContentSecurityManager.h | 5 ++ dom/security/test/general/browser.ini | 5 ++ .../browser_test_toplevel_data_navigations.js | 54 +++++++++++++ .../file_block_toplevel_data_navigation.html | 14 ++++ .../file_block_toplevel_data_navigation2.html | 29 +++++++ .../file_block_toplevel_data_navigation3.html | 13 ++++ .../general/file_block_toplevel_data_redirect.sjs | 14 ++++ .../general/file_toplevel_data_meta_redirect.html | 10 +++ .../general/file_toplevel_data_navigations.sjs | 14 ++++ dom/security/test/general/mochitest.ini | 12 +++ .../test/general/test_allow_opening_data_json.html | 39 ++++++++++ .../test/general/test_allow_opening_data_pdf.html | 41 ++++++++++ .../test_block_toplevel_data_img_navigation.html | 51 ++++++++++++ .../test_block_toplevel_data_navigation.html | 90 ++++++++++++++++++++++ dom/security/test/moz.build | 1 + 17 files changed, 479 insertions(+) create mode 100644 dom/security/test/general/browser.ini create mode 100644 dom/security/test/general/browser_test_toplevel_data_navigations.js create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation.html create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation2.html create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation3.html create mode 100644 dom/security/test/general/file_block_toplevel_data_redirect.sjs create mode 100644 dom/security/test/general/file_toplevel_data_meta_redirect.html create mode 100644 dom/security/test/general/file_toplevel_data_navigations.sjs create mode 100644 dom/security/test/general/test_allow_opening_data_json.html create mode 100644 dom/security/test/general/test_allow_opening_data_pdf.html create mode 100644 dom/security/test/general/test_block_toplevel_data_img_navigation.html create mode 100644 dom/security/test/general/test_block_toplevel_data_navigation.html (limited to 'dom') diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties index 8b66cc265..c0b80996c 100644 --- a/dom/locales/en-US/chrome/security/security.properties +++ b/dom/locales/en-US/chrome/security/security.properties @@ -81,3 +81,6 @@ MimeTypeMismatch=The resource from “%1$S” was blocked due to MIME type misma XCTOHeaderValueMissing=X-Content-Type-Options header warning: value was “%1$S”; did you mean to send “nosniff”? BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a disallowed MIME type. + +# LOCALIZATION NOTE: Do not translate "data: URI". +BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”) diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index c4e1ed8e1..069e7d6a7 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -1,13 +1,16 @@ #include "nsContentSecurityManager.h" +#include "nsEscape.h" #include "nsIChannel.h" #include "nsIHttpChannelInternal.h" #include "nsIStreamListener.h" #include "nsILoadInfo.h" +#include "nsIOService.h" #include "nsContentUtils.h" #include "nsCORSListenerProxy.h" #include "nsIStreamListener.h" #include "nsIDocument.h" #include "nsMixedContentBlocker.h" +#include "nsNullPrincipal.h" #include "mozilla/dom/Element.h" @@ -15,6 +18,66 @@ NS_IMPL_ISUPPORTS(nsContentSecurityManager, nsIContentSecurityManager, nsIChannelEventSink) +/* static */ bool +nsContentSecurityManager::AllowTopLevelNavigationToDataURI( + nsIURI* aURI, + nsContentPolicyType aContentPolicyType, + nsIPrincipal* aTriggeringPrincipal, + bool aLoadFromExternal) +{ + // Let's block all toplevel document navigations to a data: URI. + // In all cases where the toplevel document is navigated to a + // data: URI the triggeringPrincipal is a codeBasePrincipal, or + // a NullPrincipal. In other cases, e.g. typing a data: URL into + // the URL-Bar, the triggeringPrincipal is a SystemPrincipal; + // we don't want to block those loads. Only exception, loads coming + // from an external applicaton (e.g. Thunderbird) don't load + // using a codeBasePrincipal, but we want to block those loads. + if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) { + return true; + } + if (aContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) { + return true; + } + bool isDataURI = + (NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI); + if (!isDataURI) { + return true; + } + // Whitelist data: images as long as they are not SVGs + nsAutoCString filePath; + aURI->GetFilePath(filePath); + if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) && + !StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) { + return true; + } + // Whitelist data: PDFs and JSON + if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/pdf")) || + StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/json"))) { + return true; + } + if (!aLoadFromExternal && + nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) { + return true; + } + nsAutoCString dataSpec; + aURI->GetSpec(dataSpec); + if (dataSpec.Length() > 50) { + dataSpec.Truncate(50); + dataSpec.AppendLiteral("..."); + } + NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec)); + const char16_t* params[] = { specUTF16.get() }; + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("DATA_URI_BLOCKED"), + // no doc available, log to browser console + nullptr, + nsContentUtils::eSECURITY_PROPERTIES, + "BlockTopLevelDataURINavigation", + params, ArrayLength(params)); + return false; +} + static nsresult ValidateSecurityFlags(nsILoadInfo* aLoadInfo) { @@ -478,6 +541,27 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel, } } + // Redirecting to a toplevel data: URI is not allowed, hence we pass + // a NullPrincipal as the TriggeringPrincipal to + // AllowTopLevelNavigationToDataURI() which definitely blocks any + // data: URI load. + nsCOMPtr newLoadInfo = aNewChannel->GetLoadInfo(); + if (newLoadInfo) { + nsCOMPtr uri; + nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr nullTriggeringPrincipal = nsNullPrincipal::Create(); + if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI( + uri, + newLoadInfo->GetExternalContentPolicyType(), + nullTriggeringPrincipal, + false)) { + // logging to console happens within AllowTopLevelNavigationToDataURI + aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI); + return NS_ERROR_DOM_BAD_URI; + } + } + // Also verify that the redirecting server is allowed to redirect to the // given URI nsCOMPtr oldPrincipal; diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h index 912c0e89f..09b6c86aa 100644 --- a/dom/security/nsContentSecurityManager.h +++ b/dom/security/nsContentSecurityManager.h @@ -32,6 +32,11 @@ public: static nsresult doContentSecurityCheck(nsIChannel* aChannel, nsCOMPtr& aInAndOutListener); + static bool AllowTopLevelNavigationToDataURI(nsIURI* aURI, + nsContentPolicyType aContentPolicyType, + nsIPrincipal* aTriggeringPrincipal, + bool aLoadFromExternal); + private: static nsresult CheckChannel(nsIChannel* aChannel); diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini new file mode 100644 index 000000000..97ddae3bf --- /dev/null +++ b/dom/security/test/general/browser.ini @@ -0,0 +1,5 @@ +[DEFAULT] +[browser_test_toplevel_data_navigations.js] +support-files = + file_toplevel_data_navigations.sjs + file_toplevel_data_meta_redirect.html diff --git a/dom/security/test/general/browser_test_toplevel_data_navigations.js b/dom/security/test/general/browser_test_toplevel_data_navigations.js new file mode 100644 index 000000000..a13a6350e --- /dev/null +++ b/dom/security/test/general/browser_test_toplevel_data_navigations.js @@ -0,0 +1,54 @@ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ + +"use strict"; + +const kDataBody = "toplevel navigation to data: URI allowed"; +const kDataURI = "data:text/html," + kDataBody + ""; +const kTestPath = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content", "http://example.com") +const kRedirectURI = kTestPath + "file_toplevel_data_navigations.sjs"; +const kMetaRedirectURI = kTestPath + "file_toplevel_data_meta_redirect.html"; + +add_task(async function test_nav_data_uri() { + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]], + }); + await BrowserTestUtils.withNewTab(kDataURI, async function(browser) { + await ContentTask.spawn(gBrowser.selectedBrowser, {kDataBody}, async function({kDataBody}) { // eslint-disable-line + is(content.document.body.innerHTML, kDataBody, + "data: URI navigation from system should be allowed"); + }); + }); +}); + +add_task(async function test_nav_data_uri_redirect() { + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]], + }); + let tab = BrowserTestUtils.addTab(gBrowser, kRedirectURI); + registerCleanupFunction(async function() { + await BrowserTestUtils.removeTab(tab); + }); + // wait to make sure data: URI did not load before checking that it got blocked + await new Promise(resolve => setTimeout(resolve, 500)); + await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { + is(content.document.body.innerHTML, "", + "data: URI navigation after server redirect should be blocked"); + }); +}); + +add_task(async function test_nav_data_uri_meta_redirect() { + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]], + }); + let tab = BrowserTestUtils.addTab(gBrowser, kMetaRedirectURI); + registerCleanupFunction(async function() { + await BrowserTestUtils.removeTab(tab); + }); + // wait to make sure data: URI did not load before checking that it got blocked + await new Promise(resolve => setTimeout(resolve, 500)); + await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { + is(content.document.body.innerHTML, "", + "data: URI navigation after meta redirect should be blocked"); + }); +}); diff --git a/dom/security/test/general/file_block_toplevel_data_navigation.html b/dom/security/test/general/file_block_toplevel_data_navigation.html new file mode 100644 index 000000000..5fbfdfdef --- /dev/null +++ b/dom/security/test/general/file_block_toplevel_data_navigation.html @@ -0,0 +1,14 @@ + + + + + Toplevel data navigation + + +test1: clicking data: URI tries to navigate window
+click me + + + diff --git a/dom/security/test/general/file_block_toplevel_data_navigation2.html b/dom/security/test/general/file_block_toplevel_data_navigation2.html new file mode 100644 index 000000000..e0308e1ae --- /dev/null +++ b/dom/security/test/general/file_block_toplevel_data_navigation2.html @@ -0,0 +1,29 @@ + + + + + Toplevel data navigation + + +test2: data: URI in iframe tries to window.open(data:, _blank);
+ + + + diff --git a/dom/security/test/general/file_block_toplevel_data_navigation3.html b/dom/security/test/general/file_block_toplevel_data_navigation3.html new file mode 100644 index 000000000..34aeddab3 --- /dev/null +++ b/dom/security/test/general/file_block_toplevel_data_navigation3.html @@ -0,0 +1,13 @@ + + + + + Toplevel data navigation + + +test3: performing data: URI navigation through win.loc.href
+ + + diff --git a/dom/security/test/general/file_block_toplevel_data_redirect.sjs b/dom/security/test/general/file_block_toplevel_data_redirect.sjs new file mode 100644 index 000000000..64e294cab --- /dev/null +++ b/dom/security/test/general/file_block_toplevel_data_redirect.sjs @@ -0,0 +1,14 @@ +// Custom *.sjs file specifically for the needs of Bug: +// Bug 1394554 - Block toplevel data: URI navigations after redirect + +var DATA_URI = + "toplevel data: URI navigations after redirect should be blocked"; + +function handleRequest(request, response) +{ + // avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", "data:text/html," + escape(DATA_URI), false); +} diff --git a/dom/security/test/general/file_toplevel_data_meta_redirect.html b/dom/security/test/general/file_toplevel_data_meta_redirect.html new file mode 100644 index 000000000..f4f5deb52 --- /dev/null +++ b/dom/security/test/general/file_toplevel_data_meta_redirect.html @@ -0,0 +1,10 @@ + + + + + + +Meta Redirect to data: URI + + diff --git a/dom/security/test/general/file_toplevel_data_navigations.sjs b/dom/security/test/general/file_toplevel_data_navigations.sjs new file mode 100644 index 000000000..501b833e5 --- /dev/null +++ b/dom/security/test/general/file_toplevel_data_navigations.sjs @@ -0,0 +1,14 @@ +// Custom *.sjs file specifically for the needs of Bug: +// Bug 1394554 - Block toplevel data: URI navigations after redirect + +var DATA_URI = + "data:text/html,toplevel data: URI navigations after redirect should be blocked"; + +function handleRequest(request, response) +{ + // avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", DATA_URI, false); +} diff --git a/dom/security/test/general/mochitest.ini b/dom/security/test/general/mochitest.ini index 70c0c9fb6..f3bcca072 100644 --- a/dom/security/test/general/mochitest.ini +++ b/dom/security/test/general/mochitest.ini @@ -3,7 +3,19 @@ support-files = file_contentpolicytype_targeted_link_iframe.sjs file_nosniff_testserver.sjs file_block_script_wrong_mime_server.sjs + file_block_toplevel_data_navigation.html + file_block_toplevel_data_navigation2.html + file_block_toplevel_data_navigation3.html + file_block_toplevel_data_redirect.sjs [test_contentpolicytype_targeted_link_iframe.html] [test_nosniff.html] [test_block_script_wrong_mime.html] +[test_block_toplevel_data_navigation.html] +skip-if = toolkit == 'android' # intermittent failure +[test_block_toplevel_data_img_navigation.html] +skip-if = toolkit == 'android' # intermittent failure +[test_allow_opening_data_pdf.html] +skip-if = toolkit == 'android' +[test_allow_opening_data_json.html] +skip-if = toolkit == 'android' diff --git a/dom/security/test/general/test_allow_opening_data_json.html b/dom/security/test/general/test_allow_opening_data_json.html new file mode 100644 index 000000000..1530a24e8 --- /dev/null +++ b/dom/security/test/general/test_allow_opening_data_json.html @@ -0,0 +1,39 @@ + + + + + Bug 1403814: Allow toplevel data URI navigation data:application/json + + + + + + + diff --git a/dom/security/test/general/test_allow_opening_data_pdf.html b/dom/security/test/general/test_allow_opening_data_pdf.html new file mode 100644 index 000000000..6b51fe57b --- /dev/null +++ b/dom/security/test/general/test_allow_opening_data_pdf.html @@ -0,0 +1,41 @@ + + + + + Bug 1398692: Allow toplevel navigation to a data:application/pdf + + + + + + + diff --git a/dom/security/test/general/test_block_toplevel_data_img_navigation.html b/dom/security/test/general/test_block_toplevel_data_img_navigation.html new file mode 100644 index 000000000..2b8f62760 --- /dev/null +++ b/dom/security/test/general/test_block_toplevel_data_img_navigation.html @@ -0,0 +1,51 @@ + + + + + Bug 1396798: Do not block toplevel data: navigation to image (except svgs) + + + + + + + diff --git a/dom/security/test/general/test_block_toplevel_data_navigation.html b/dom/security/test/general/test_block_toplevel_data_navigation.html new file mode 100644 index 000000000..fc91f2ec0 --- /dev/null +++ b/dom/security/test/general/test_block_toplevel_data_navigation.html @@ -0,0 +1,90 @@ + + + + + Bug 1331351 - Block top level window data: URI navigations + + + + + + + + diff --git a/dom/security/test/moz.build b/dom/security/test/moz.build index ddb4e9b89..946959dee 100644 --- a/dom/security/test/moz.build +++ b/dom/security/test/moz.build @@ -27,5 +27,6 @@ MOCHITEST_CHROME_MANIFESTS += [ BROWSER_CHROME_MANIFESTS += [ 'contentverifier/browser.ini', 'csp/browser.ini', + 'general/browser.ini', 'hsts/browser.ini', ] -- cgit v1.2.3 From f1e5578718ea8883438cfea06d3c55d25f5c0278 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 19:03:22 +0200 Subject: moebius#226: Consider blocking top level window data: URIs (part 2/2 without tests) https://github.com/MoonchildProductions/moebius/pull/226 --- dom/security/nsContentSecurityManager.cpp | 59 +++++++++------------- dom/security/nsContentSecurityManager.h | 5 +- dom/security/test/general/browser.ini | 6 +++ .../test/general/browser_test_data_download.js | 37 ++++++++++++++ .../test/general/browser_test_data_text_csv.js | 37 ++++++++++++++ dom/security/test/general/file_data_download.html | 14 +++++ dom/security/test/general/file_data_text_csv.html | 14 +++++ .../test_block_toplevel_data_img_navigation.html | 18 ++++--- .../test_block_toplevel_data_navigation.html | 16 +++--- 9 files changed, 149 insertions(+), 57 deletions(-) create mode 100644 dom/security/test/general/browser_test_data_download.js create mode 100644 dom/security/test/general/browser_test_data_text_csv.js create mode 100644 dom/security/test/general/file_data_download.html create mode 100644 dom/security/test/general/file_data_text_csv.html (limited to 'dom') diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 069e7d6a7..c987fed67 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -10,20 +10,16 @@ #include "nsIStreamListener.h" #include "nsIDocument.h" #include "nsMixedContentBlocker.h" -#include "nsNullPrincipal.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/TabChild.h" NS_IMPL_ISUPPORTS(nsContentSecurityManager, nsIContentSecurityManager, nsIChannelEventSink) /* static */ bool -nsContentSecurityManager::AllowTopLevelNavigationToDataURI( - nsIURI* aURI, - nsContentPolicyType aContentPolicyType, - nsIPrincipal* aTriggeringPrincipal, - bool aLoadFromExternal) +nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel) { // Let's block all toplevel document navigations to a data: URI. // In all cases where the toplevel document is navigated to a @@ -36,17 +32,24 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI( if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) { return true; } - if (aContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) { + nsCOMPtr loadInfo = aChannel->GetLoadInfo(); + if (!loadInfo) { + return true; + } + if (loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) { return true; } + nsCOMPtr uri; + nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, true); bool isDataURI = - (NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI); + (NS_SUCCEEDED(uri->SchemeIs("data", &isDataURI)) && isDataURI); if (!isDataURI) { return true; } // Whitelist data: images as long as they are not SVGs nsAutoCString filePath; - aURI->GetFilePath(filePath); + uri->GetFilePath(filePath); if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) && !StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) { return true; @@ -56,22 +59,29 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI( StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/json"))) { return true; } - if (!aLoadFromExternal && - nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) { + // Redirecting to a toplevel data: URI is not allowed, hence we make + // sure the RedirectChain is empty. + if (!loadInfo->GetLoadTriggeredFromExternal() && + nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal()) && + loadInfo->RedirectChain().IsEmpty()) { return true; } nsAutoCString dataSpec; - aURI->GetSpec(dataSpec); + uri->GetSpec(dataSpec); if (dataSpec.Length() > 50) { dataSpec.Truncate(50); dataSpec.AppendLiteral("..."); } + nsCOMPtr tabChild = do_QueryInterface(loadInfo->ContextForTopLevelLoad()); + nsCOMPtr doc; + if (tabChild) { + doc = static_cast(tabChild.get())->GetDocument(); + } NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec)); const char16_t* params[] = { specUTF16.get() }; nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DATA_URI_BLOCKED"), - // no doc available, log to browser console - nullptr, + doc, nsContentUtils::eSECURITY_PROPERTIES, "BlockTopLevelDataURINavigation", params, ArrayLength(params)); @@ -541,27 +551,6 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel, } } - // Redirecting to a toplevel data: URI is not allowed, hence we pass - // a NullPrincipal as the TriggeringPrincipal to - // AllowTopLevelNavigationToDataURI() which definitely blocks any - // data: URI load. - nsCOMPtr newLoadInfo = aNewChannel->GetLoadInfo(); - if (newLoadInfo) { - nsCOMPtr uri; - nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr nullTriggeringPrincipal = nsNullPrincipal::Create(); - if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI( - uri, - newLoadInfo->GetExternalContentPolicyType(), - nullTriggeringPrincipal, - false)) { - // logging to console happens within AllowTopLevelNavigationToDataURI - aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI); - return NS_ERROR_DOM_BAD_URI; - } - } - // Also verify that the redirecting server is allowed to redirect to the // given URI nsCOMPtr oldPrincipal; diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h index 09b6c86aa..bab847743 100644 --- a/dom/security/nsContentSecurityManager.h +++ b/dom/security/nsContentSecurityManager.h @@ -32,10 +32,7 @@ public: static nsresult doContentSecurityCheck(nsIChannel* aChannel, nsCOMPtr& aInAndOutListener); - static bool AllowTopLevelNavigationToDataURI(nsIURI* aURI, - nsContentPolicyType aContentPolicyType, - nsIPrincipal* aTriggeringPrincipal, - bool aLoadFromExternal); + static bool AllowTopLevelNavigationToDataURI(nsIChannel* aChannel); private: static nsresult CheckChannel(nsIChannel* aChannel); diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini index 97ddae3bf..73ae72ddd 100644 --- a/dom/security/test/general/browser.ini +++ b/dom/security/test/general/browser.ini @@ -3,3 +3,9 @@ support-files = file_toplevel_data_navigations.sjs file_toplevel_data_meta_redirect.html +[browser_test_data_download.js] +support-files = + file_data_download.html +[browser_test_data_text_csv.js] +support-files = + file_data_text_csv.html diff --git a/dom/security/test/general/browser_test_data_download.js b/dom/security/test/general/browser_test_data_download.js new file mode 100644 index 000000000..1ee8d5844 --- /dev/null +++ b/dom/security/test/general/browser_test_data_download.js @@ -0,0 +1,37 @@ +"use strict"; + +const kTestPath = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content", "http://example.com") +const kTestURI = kTestPath + "file_data_download.html"; + +function addWindowListener(aURL, aCallback) { + Services.wm.addListener({ + onOpenWindow(aXULWindow) { + info("window opened, waiting for focus"); + Services.wm.removeListener(this); + var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); + waitForFocus(function() { + is(domwindow.document.location.href, aURL, "should have seen the right window open"); + aCallback(domwindow); + }, domwindow); + }, + onCloseWindow(aXULWindow) { }, + onWindowTitleChange(aXULWindow, aNewTitle) { } + }); +} + +function test() { + waitForExplicitFinish(); + Services.prefs.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true); + registerCleanupFunction(function() { + Services.prefs.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations"); + }); + addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function(win) { + is(win.document.getElementById("location").value, "data-foo.html", + "file name of download should match"); + win.close(); + finish(); + }); + gBrowser.loadURI(kTestURI); +} diff --git a/dom/security/test/general/browser_test_data_text_csv.js b/dom/security/test/general/browser_test_data_text_csv.js new file mode 100644 index 000000000..c45e40cc2 --- /dev/null +++ b/dom/security/test/general/browser_test_data_text_csv.js @@ -0,0 +1,37 @@ +"use strict"; + +const kTestPath = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content", "http://example.com") +const kTestURI = kTestPath + "file_data_text_csv.html"; + +function addWindowListener(aURL, aCallback) { + Services.wm.addListener({ + onOpenWindow(aXULWindow) { + info("window opened, waiting for focus"); + Services.wm.removeListener(this); + var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); + waitForFocus(function() { + is(domwindow.document.location.href, aURL, "should have seen the right window open"); + aCallback(domwindow); + }, domwindow); + }, + onCloseWindow(aXULWindow) { }, + onWindowTitleChange(aXULWindow, aNewTitle) { } + }); +} + +function test() { + waitForExplicitFinish(); + Services.prefs.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true); + registerCleanupFunction(function() { + Services.prefs.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations"); + }); + addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function(win) { + is(win.document.getElementById("location").value, "text/csv;foo,bar,foobar", + "file name of download should match"); + win.close(); + finish(); + }); + gBrowser.loadURI(kTestURI); +} diff --git a/dom/security/test/general/file_data_download.html b/dom/security/test/general/file_data_download.html new file mode 100644 index 000000000..4cc92fe8f --- /dev/null +++ b/dom/security/test/general/file_data_download.html @@ -0,0 +1,14 @@ + + + + Test download attribute for data: URI + + + download data + + + diff --git a/dom/security/test/general/file_data_text_csv.html b/dom/security/test/general/file_data_text_csv.html new file mode 100644 index 000000000..a9ac369d1 --- /dev/null +++ b/dom/security/test/general/file_data_text_csv.html @@ -0,0 +1,14 @@ + + + + Test open data:text/csv + + + test text/csv + + + diff --git a/dom/security/test/general/test_block_toplevel_data_img_navigation.html b/dom/security/test/general/test_block_toplevel_data_img_navigation.html index 2b8f62760..7f8dfc748 100644 --- a/dom/security/test/general/test_block_toplevel_data_img_navigation.html +++ b/dom/security/test/general/test_block_toplevel_data_img_navigation.html @@ -34,15 +34,17 @@ function test_toplevel_data_image_svg() { const DATA_SVG = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg=="; let win2 = window.open(DATA_SVG); - let wrappedWin2 = SpecialPowers.wrap(win2); - setTimeout(function () { - isnot(wrappedWin2.document.documentElement.localName, "svg", - "Loading data:image/svg+xml should be blocked"); - wrappedWin2.close(); - SimpleTest.finish(); - }, 1000); + // Unfortunately we can't detect whether the window was closed using some event, + // hence we are constantly polling till we see that win == null. + // Test times out on failure. + var win2Closed = setInterval(function() { + if (win2 == null || win2.closed) { + clearInterval(win2Closed); + ok(true, "Loading data:image/svg+xml should be blocked"); + SimpleTest.finish(); + } + }, 200); } - // fire up the tests test_toplevel_data_image(); diff --git a/dom/security/test/general/test_block_toplevel_data_navigation.html b/dom/security/test/general/test_block_toplevel_data_navigation.html index fc91f2ec0..cef232b65 100644 --- a/dom/security/test/general/test_block_toplevel_data_navigation.html +++ b/dom/security/test/general/test_block_toplevel_data_navigation.html @@ -21,16 +21,12 @@ function test1() { // simple data: URI click navigation should be prevented let TEST_FILE = "file_block_toplevel_data_navigation.html"; let win1 = window.open(TEST_FILE); - var readyStateCheckInterval = setInterval(function() { - let state = win1.document.readyState; - if (state === "interactive" || state === "complete") { - clearInterval(readyStateCheckInterval); - ok(win1.document.body.innerHTML.indexOf("test1:") !== -1, - "toplevel data: URI navigation through click() should be blocked"); - win1.close(); - test2(); - } - }, 200); + setTimeout(function () { + ok(SpecialPowers.wrap(win1).document.body.innerHTML.indexOf("test1:") !== -1, + "toplevel data: URI navigation through click() should be blocked"); + win1.close(); + test2(); + }, 1000); } function test2() { -- cgit v1.2.3 From 660d01438a6a29ebd43f592ac7d6df2dad6a6962 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 20:28:18 +0200 Subject: moebius#230: Consider blocking top level window data: URIs (part 3/3 without tests) https://github.com/MoonchildProductions/moebius/pull/230 --- dom/security/nsContentSecurityManager.cpp | 4 +++ dom/security/test/general/browser.ini | 3 +++ .../browser_test_view_image_data_navigation.js | 30 ++++++++++++++++++++++ .../general/file_view_image_data_navigation.html | 12 +++++++++ 4 files changed, 49 insertions(+) create mode 100644 dom/security/test/general/browser_test_view_image_data_navigation.js create mode 100644 dom/security/test/general/file_view_image_data_navigation.html (limited to 'dom') diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index c987fed67..9329c558a 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -39,6 +39,10 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel) if (loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) { return true; } + if (loadInfo->GetForceAllowDataURI()) { + // if the loadinfo explicitly allows the data URI navigation, let's allow it now + return true; + } nsCOMPtr uri; nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, true); diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini index 73ae72ddd..b00baa95d 100644 --- a/dom/security/test/general/browser.ini +++ b/dom/security/test/general/browser.ini @@ -9,3 +9,6 @@ support-files = [browser_test_data_text_csv.js] support-files = file_data_text_csv.html +[browser_test_view_image_data_navigation.js] +support-files = + file_view_image_data_navigation.html diff --git a/dom/security/test/general/browser_test_view_image_data_navigation.js b/dom/security/test/general/browser_test_view_image_data_navigation.js new file mode 100644 index 000000000..22de35894 --- /dev/null +++ b/dom/security/test/general/browser_test_view_image_data_navigation.js @@ -0,0 +1,30 @@ +"use strict"; + +const TEST_PAGE = getRootDirectory(gTestPath) + "file_view_image_data_navigation.html"; + +add_task(async function test_principal_right_click_open_link_in_new_tab() { + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]], + }); + + await BrowserTestUtils.withNewTab(TEST_PAGE, async function(browser) { + let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, true); + + // simulate right-click->view-image + BrowserTestUtils.waitForEvent(document, "popupshown", false, event => { + // These are operations that must be executed synchronously with the event. + document.getElementById("context-viewimage").doCommand(); + event.target.hidePopup(); + return true; + }); + BrowserTestUtils.synthesizeMouseAtCenter("#testimage", + { type: "contextmenu", button: 2 }, + gBrowser.selectedBrowser); + await loadPromise; + + await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { + ok(content.document.location.toString().startsWith("data:image/svg+xml;"), + "data:image/svg navigation allowed through right-click view-image") + }); + }); +}); diff --git a/dom/security/test/general/file_view_image_data_navigation.html b/dom/security/test/general/file_view_image_data_navigation.html new file mode 100644 index 000000000..a3f9acfb4 --- /dev/null +++ b/dom/security/test/general/file_view_image_data_navigation.html @@ -0,0 +1,12 @@ + + + + + Bug 1407891: Test navigation for right-click view-image on data:image/svg + + + + + + + -- cgit v1.2.3 From a38e87d455f6ad3637deeae20d2ddc57430b498d Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 20:37:09 +0200 Subject: Bug 1329288 - Test ContentPolicy blocks opening a new window --- .../test/general/test_contentpolicytype_targeted_link_iframe.html | 1 + 1 file changed, 1 insertion(+) (limited to 'dom') diff --git a/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html b/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html index 7b1ab72dc..3ef243824 100644 --- a/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html +++ b/dom/security/test/general/test_contentpolicytype_targeted_link_iframe.html @@ -61,6 +61,7 @@ var policy = { "content policy type should TYPESUBDOCUMENT"); categoryManager.deleteCategoryEntry("content-policy", POLICYNAME, false); SimpleTest.finish(); + return Ci.nsIContentPolicy.REJECT_REQUEST; } return Ci.nsIContentPolicy.ACCEPT; }, -- cgit v1.2.3 From 95c46082414632687e3ddd52435d476ab9dc320f Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 20:38:02 +0200 Subject: Bug 1329288: Allow content policy consumers to identify contentPolicy checks from docshell --- dom/security/nsCSPContext.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'dom') diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index a7517f65e..979bd915f 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -171,9 +171,10 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, } } - // aExtra is only non-null if the channel got redirected. - bool wasRedirected = (aExtra != nullptr); + // aExtra holds the original URI of the channel if the + // channel got redirected (until we fix Bug 1332422). nsCOMPtr originalURI = do_QueryInterface(aExtra); + bool wasRedirected = originalURI; bool permitted = permitsInternal(dir, aContentLocation, -- cgit v1.2.3 From 8af1b0c22a9c449746479b8a82494e43d60af573 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 21:00:39 +0200 Subject: Bug 1329570 - Restore missing error check in mozilla::dom::Location::GetPathname native in moebius --- dom/base/Location.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'dom') diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index e3b614931..b17e733d5 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -577,9 +577,10 @@ Location::GetPathname(nsAString& aPathname) aPathname.Truncate(); nsCOMPtr uri; - nsresult result = NS_OK; - - result = GetURI(getter_AddRefs(uri)); + nsresult result = GetURI(getter_AddRefs(uri)); + if (NS_FAILED(result) || !uri) { + return result; + } nsCOMPtr url(do_QueryInterface(uri)); if (url) { -- cgit v1.2.3 From dbfad99a51062e663da19266219191c0dc3521be Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 21:20:53 +0200 Subject: Bug 1323683 - Fold nsIURIWithQuery into nsIURI native in moebius --- dom/base/Location.cpp | 14 +++++--------- dom/url/URL.cpp | 40 ++++++++-------------------------------- 2 files changed, 13 insertions(+), 41 deletions(-) (limited to 'dom') diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index b17e733d5..b6b95aaa6 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -582,15 +582,12 @@ Location::GetPathname(nsAString& aPathname) return result; } - nsCOMPtr url(do_QueryInterface(uri)); - if (url) { - nsAutoCString file; + nsAutoCString file; - result = url->GetFilePath(file); + result = uri->GetFilePath(file); - if (NS_SUCCEEDED(result)) { - AppendUTF8toUTF16(file, aPathname); - } + if (NS_SUCCEEDED(result)) { + AppendUTF8toUTF16(file, aPathname); } return result; @@ -605,8 +602,7 @@ Location::SetPathname(const nsAString& aPathname) return rv; } - nsCOMPtr url(do_QueryInterface(uri)); - if (url && NS_SUCCEEDED(url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) { + if (NS_SUCCEEDED(uri->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) { return SetURI(uri); } diff --git a/dom/url/URL.cpp b/dom/url/URL.cpp index 1f15e1151..c8724c359 100644 --- a/dom/url/URL.cpp +++ b/dom/url/URL.cpp @@ -17,7 +17,6 @@ #include "nsEscape.h" #include "nsHostObjectProtocolHandler.h" #include "nsIIOService.h" -#include "nsIURIWithQuery.h" #include "nsIURL.h" #include "nsNetCID.h" #include "nsNetUtil.h" @@ -525,21 +524,10 @@ URLMainThread::GetPathname(nsAString& aPathname, ErrorResult& aRv) const // Do not throw! Not having a valid URI or URL should result in an empty // string. - nsCOMPtr url(do_QueryInterface(mURI)); - if (url) { - nsAutoCString file; - nsresult rv = url->GetFilePath(file); - if (NS_SUCCEEDED(rv)) { - CopyUTF8toUTF16(file, aPathname); - } - - return; - } - - nsAutoCString path; - nsresult rv = mURI->GetPath(path); + nsAutoCString file; + nsresult rv = mURI->GetFilePath(file); if (NS_SUCCEEDED(rv)) { - CopyUTF8toUTF16(path, aPathname); + CopyUTF8toUTF16(file, aPathname); } } @@ -548,11 +536,7 @@ URLMainThread::SetPathname(const nsAString& aPathname, ErrorResult& aRv) { // Do not throw! - nsCOMPtr url(do_QueryInterface(mURI)); - if (url) { - url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)); - return; - } + mURI->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)); } void @@ -566,13 +550,9 @@ URLMainThread::GetSearch(nsAString& aSearch, ErrorResult& aRv) const nsAutoCString search; nsresult rv; - nsCOMPtr url(do_QueryInterface(mURI)); - if (url) { - rv = url->GetQuery(search); - if (NS_SUCCEEDED(rv) && !search.IsEmpty()) { - CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch); - } - return; + rv = mURI->GetQuery(search); + if (NS_SUCCEEDED(rv) && !search.IsEmpty()) { + CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch); } } @@ -603,11 +583,7 @@ URLMainThread::SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv) { // Ignore failures to be compatible with NS4. - nsCOMPtr uriWithQuery(do_QueryInterface(mURI)); - if (uriWithQuery) { - uriWithQuery->SetQuery(NS_ConvertUTF16toUTF8(aSearch)); - return; - } + mURI->SetQuery(NS_ConvertUTF16toUTF8(aSearch)); } } // anonymous namespace -- cgit v1.2.3 From 29bd11c3cd6ff41f7167530f9bbcd9d195b7c427 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 21:47:27 +0200 Subject: Bug 1182569: Use AsyncOpen2 for docshell loads native in moebius --- dom/jsurl/nsJSProtocolHandler.cpp | 49 ++++++++++++++------------------------- 1 file changed, 17 insertions(+), 32 deletions(-) (limited to 'dom') 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 mStreamChannel; nsCOMPtr mPropertyBag; nsCOMPtr mListener; // Our final listener - nsCOMPtr mContext; // The context passed to AsyncOpen nsCOMPtr 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 mDocumentOnloadBlockedOn; nsresult mStatus; // Our status nsLoadFlags mLoadFlags; - nsLoadFlags mActualLoadFlags; // See AsyncOpen + nsLoadFlags mActualLoadFlags; // See AsyncOpen2 RefPtr 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 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 channel; - - nsCOMPtr 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)) { -- cgit v1.2.3 From 2e33335820b2816bee111e78588ac82e401c86ae Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 21:51:49 +0200 Subject: Bug 1182569: Update ContentSecurityManager to handle docshell loads native in moebius --- dom/security/nsContentSecurityManager.cpp | 81 ++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 17 deletions(-) (limited to 'dom') diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 9329c558a..458f41144 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 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 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 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 urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv)); + if (NS_SUCCEEDED(rv) && urifixup) { + nsCOMPtr 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; } @@ -447,18 +456,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 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; } @@ -606,6 +629,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 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 urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv)); + if (NS_SUCCEEDED(rv) && urifixup) { + nsCOMPtr 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) { -- cgit v1.2.3 From 5b0f4649b3fee771379af60ec04d43b8a525cf80 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 21:59:46 +0200 Subject: Bug 1182569 - Skip security check for plugins using newstream attribute native in moebius --- dom/base/nsContentUtils.cpp | 2 +- dom/plugins/base/nsPluginInstanceOwner.cpp | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'dom') diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index ef87a250e..c3ff2b4d8 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -5100,7 +5100,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()); } } diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index b7651be1a..7de6c2b73 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 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 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 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; } -- cgit v1.2.3 From b73225e886f84182384a2b5b09f83e51501bdc38 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 22:02:20 +0200 Subject: Bug 1182569: Update tests when converting docshell loads to use AynscOpen2 native in moebius --- dom/base/test/file_simplecontentpolicy.js | 1 - dom/plugins/test/mochitest/test_bug813906.html | 22 ++++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) (limited to 'dom') 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 element"); sendAsyncMessage("shouldLoad", {contentType: contentType, isTopLevel: isTopLevel}); return Ci.nsIContentPolicy.REJECT_REQUEST; } 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() {