diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /caps/tests/gtest | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream/115.8.0esr.tar.xz firefox-esr-upstream/115.8.0esr.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'caps/tests/gtest')
-rw-r--r-- | caps/tests/gtest/TestBackgroundThreadPrincipal.cpp | 94 | ||||
-rw-r--r-- | caps/tests/gtest/TestNullPrincipalPrecursor.cpp | 56 | ||||
-rw-r--r-- | caps/tests/gtest/TestOriginAttributes.cpp | 118 | ||||
-rw-r--r-- | caps/tests/gtest/TestPrincipalAttributes.cpp | 39 | ||||
-rw-r--r-- | caps/tests/gtest/TestPrincipalSerialization.cpp | 214 | ||||
-rw-r--r-- | caps/tests/gtest/TestRedirectChainURITruncation.cpp | 231 | ||||
-rw-r--r-- | caps/tests/gtest/moz.build | 18 |
7 files changed, 770 insertions, 0 deletions
diff --git a/caps/tests/gtest/TestBackgroundThreadPrincipal.cpp b/caps/tests/gtest/TestBackgroundThreadPrincipal.cpp new file mode 100644 index 0000000000..82c7b15757 --- /dev/null +++ b/caps/tests/gtest/TestBackgroundThreadPrincipal.cpp @@ -0,0 +1,94 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "gtest/gtest.h" +#include "mozilla/gtest/MozAssertions.h" +#include "mozilla/BasePrincipal.h" +#include "mozilla/ContentPrincipal.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/ipc/BackgroundUtils.h" +#include "mozilla/ipc/PBackgroundSharedTypes.h" +#include "nsIEventTarget.h" +#include "nsISerialEventTarget.h" +#include "nsIURIMutator.h" +#include "nsNetUtil.h" +#include "nsPrintfCString.h" +#include "nsThreadUtils.h" + +namespace mozilla { + +template <typename F> +void RunOnBackgroundThread(F&& aFunction) { + nsCOMPtr<nsISerialEventTarget> backgroundQueue; + ASSERT_NS_SUCCEEDED(NS_CreateBackgroundTaskQueue( + "RunOnBackgroundThread", getter_AddRefs(backgroundQueue))); + ASSERT_NS_SUCCEEDED(NS_DispatchAndSpinEventLoopUntilComplete( + "RunOnBackgroundThread"_ns, backgroundQueue, + NS_NewRunnableFunction("RunOnBackgroundThread", + std::forward<F>(aFunction)))); +} + +TEST(BackgroundThreadPrincipal, CreateContent) +{ + RunOnBackgroundThread([] { + nsCOMPtr<nsIURI> contentURI; + ASSERT_NS_SUCCEEDED(NS_NewURI(getter_AddRefs(contentURI), + "http://subdomain.example.com:8000"_ns)); + RefPtr<BasePrincipal> contentPrincipal = + BasePrincipal::CreateContentPrincipal(contentURI, OriginAttributes()); + EXPECT_TRUE(contentPrincipal->Is<ContentPrincipal>()); + + nsCString origin; + ASSERT_NS_SUCCEEDED(contentPrincipal->GetOrigin(origin)); + EXPECT_EQ(origin, "http://subdomain.example.com:8000"_ns); + + nsCString siteOrigin; + ASSERT_NS_SUCCEEDED(contentPrincipal->GetSiteOrigin(siteOrigin)); + EXPECT_EQ(siteOrigin, "http://example.com"_ns); + }); +} + +TEST(BackgroundThreadPrincipal, CreateNull) +{ + RunOnBackgroundThread([] { + nsCOMPtr<nsIURI> contentURI; + ASSERT_NS_SUCCEEDED(NS_NewURI(getter_AddRefs(contentURI), + "data:text/plain,hello world"_ns)); + RefPtr<BasePrincipal> principal = + BasePrincipal::CreateContentPrincipal(contentURI, OriginAttributes()); + EXPECT_TRUE(principal->Is<NullPrincipal>()); + + nsCString origin; + ASSERT_NS_SUCCEEDED(principal->GetOrigin(origin)); + EXPECT_TRUE(StringBeginsWith(origin, "moz-nullprincipal:"_ns)); + }); +} + +TEST(BackgroundThreadPrincipal, PrincipalInfoConversions) +{ + RunOnBackgroundThread([] { + nsCOMPtr<nsIURI> contentURI; + ASSERT_NS_SUCCEEDED(NS_NewURI(getter_AddRefs(contentURI), + "http://subdomain.example.com:8000"_ns)); + RefPtr<BasePrincipal> contentPrincipal = + BasePrincipal::CreateContentPrincipal(contentURI, OriginAttributes()); + EXPECT_TRUE(contentPrincipal->Is<ContentPrincipal>()); + + ipc::PrincipalInfo info; + ASSERT_NS_SUCCEEDED(ipc::PrincipalToPrincipalInfo(contentPrincipal, &info)); + + EXPECT_TRUE(info.type() == ipc::PrincipalInfo::TContentPrincipalInfo); + EXPECT_EQ(info.get_ContentPrincipalInfo().spec(), + "http://subdomain.example.com:8000/"_ns); + EXPECT_EQ(info.get_ContentPrincipalInfo().baseDomain(), "example.com"_ns); + + auto result = PrincipalInfoToPrincipal(info); + ASSERT_TRUE(result.isOk()); + nsCOMPtr<nsIPrincipal> deserialized = result.unwrap(); + EXPECT_TRUE(deserialized->GetIsContentPrincipal()); + + EXPECT_TRUE(deserialized->Equals(contentPrincipal)); + }); +} + +} // namespace mozilla diff --git a/caps/tests/gtest/TestNullPrincipalPrecursor.cpp b/caps/tests/gtest/TestNullPrincipalPrecursor.cpp new file mode 100644 index 0000000000..96db5aeffd --- /dev/null +++ b/caps/tests/gtest/TestNullPrincipalPrecursor.cpp @@ -0,0 +1,56 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "gtest/gtest.h" +#include "mozilla/gtest/MozAssertions.h" +#include "mozilla/NullPrincipal.h" +#include "nsIURIMutator.h" +#include "nsPrintfCString.h" + +namespace mozilla { + +TEST(NullPrincipalPrecursor, EscapingRoundTrips) +{ + nsTArray<nsCString> inputs; + + inputs.AppendElements(mozilla::Span(std::array{ + "mailbox:///dev/shm/tmp5wkt9ff_.mozrunner/Mail/Local%20Folders/secure-mail?number=5"_ns, + })); + + // Add a string for every ASCII byte both escaped and unescaped. + for (uint8_t c = 0; c < 128; ++c) { + inputs.AppendElement(nsPrintfCString("%02X: %c", c, (char)c)); + inputs.AppendElement(nsPrintfCString("%02X: %%%02X", c, c)); + } + + nsID dummyID{0xddf15eaf, + 0x3837, + 0x4678, + {0x80, 0x3b, 0x86, 0x86, 0xe8, 0x17, 0x66, 0x71}}; + nsCOMPtr<nsIURI> baseURI = NullPrincipal::CreateURI(nullptr, &dummyID); + ASSERT_TRUE(baseURI); + + for (auto& input : inputs) { + // First build an escaped version of the input string using + // `EscapePrecursorQuery`. + nsCString escaped(input); + NullPrincipal::EscapePrecursorQuery(escaped); + + // Make sure that this escaped URI round-trips through a `moz-nullprincipal` + // URI's query without any additional escapes. + nsCOMPtr<nsIURI> clone; + EXPECT_NS_SUCCEEDED( + NS_MutateURI(baseURI).SetQuery(escaped).Finalize(clone)); + nsCString query; + EXPECT_NS_SUCCEEDED(clone->GetQuery(query)); + EXPECT_EQ(escaped, query); + + // Try to unescape our escaped URI and make sure we recover the input + // string. + nsCString unescaped(escaped); + NullPrincipal::UnescapePrecursorQuery(unescaped); + EXPECT_EQ(input, unescaped); + } +} + +} // namespace mozilla diff --git a/caps/tests/gtest/TestOriginAttributes.cpp b/caps/tests/gtest/TestOriginAttributes.cpp new file mode 100644 index 0000000000..fa759f80d5 --- /dev/null +++ b/caps/tests/gtest/TestOriginAttributes.cpp @@ -0,0 +1,118 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "gtest/gtest.h" +#include "mozilla/BasePrincipal.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/Preferences.h" +#include "nsNetUtil.h" + +using mozilla::OriginAttributes; +using mozilla::Preferences; + +#define FPI_PREF "privacy.firstparty.isolate" +#define SITE_PREF "privacy.firstparty.isolate.use_site" + +#define TEST_FPD(_spec, _expected) \ + TestFPD(nsLiteralString(_spec), nsLiteralString(_expected)) + +namespace mozilla { + +static void TestSuffix(const OriginAttributes& attrs) { + nsAutoCString suffix; + attrs.CreateSuffix(suffix); + + OriginAttributes attrsFromSuffix; + bool success = attrsFromSuffix.PopulateFromSuffix(suffix); + EXPECT_TRUE(success); + + EXPECT_EQ(attrs, attrsFromSuffix); +} + +static void TestFPD(const nsAString& spec, const nsAString& expected) { + OriginAttributes attrs; + nsCOMPtr<nsIURI> url; + ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK); + attrs.SetFirstPartyDomain(true, url); + EXPECT_TRUE(attrs.mFirstPartyDomain.Equals(expected)); + + TestSuffix(attrs); +} + +TEST(OriginAttributes, Suffix_default) +{ + OriginAttributes attrs; + TestSuffix(attrs); +} + +TEST(OriginAttributes, Suffix_inIsolatedMozBrowser) +{ + OriginAttributes attrs(true); + TestSuffix(attrs); +} + +TEST(OriginAttributes, FirstPartyDomain_default) +{ + bool oldFpiPref = Preferences::GetBool(FPI_PREF); + Preferences::SetBool(FPI_PREF, true); + bool oldSitePref = Preferences::GetBool(SITE_PREF); + Preferences::SetBool(SITE_PREF, false); + + TEST_FPD(u"http://www.example.com", u"example.com"); + TEST_FPD(u"http://www.example.com:80", u"example.com"); + TEST_FPD(u"http://www.example.com:8080", u"example.com"); + TEST_FPD(u"http://s3.amazonaws.com", u"s3.amazonaws.com"); + TEST_FPD(u"http://com", u"com"); + TEST_FPD(u"http://com.", u"com."); + TEST_FPD(u"http://com:8080", u"com"); + TEST_FPD(u"http://.com", u""); + TEST_FPD(u"http://..com", u""); + TEST_FPD(u"http://127.0.0.1", u"127.0.0.1"); + TEST_FPD(u"http://[::1]", u"[::1]"); + TEST_FPD(u"about:config", + u"about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla"); + TEST_FPD(u"moz-extension://f5b6ca10-5bd4-4ed6-9baf-820dc5152bc1", u""); + TEST_FPD(u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}", + u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"); + TEST_FPD( + u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}" + u"?https://www.example.com", + u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"); + + Preferences::SetBool(FPI_PREF, oldFpiPref); + Preferences::SetBool(SITE_PREF, oldSitePref); +} + +TEST(OriginAttributes, FirstPartyDomain_site) +{ + bool oldFpiPref = Preferences::GetBool(FPI_PREF); + Preferences::SetBool(FPI_PREF, true); + bool oldSitePref = Preferences::GetBool(SITE_PREF); + Preferences::SetBool(SITE_PREF, true); + + TEST_FPD(u"http://www.example.com", u"(http,example.com)"); + TEST_FPD(u"http://www.example.com:80", u"(http,example.com)"); + TEST_FPD(u"http://www.example.com:8080", u"(http,example.com)"); + TEST_FPD(u"http://s3.amazonaws.com", u"(http,s3.amazonaws.com)"); + TEST_FPD(u"http://com", u"(http,com)"); + TEST_FPD(u"http://com.", u"(http,com.)"); + TEST_FPD(u"http://com:8080", u"(http,com,8080)"); + TEST_FPD(u"http://.com", u"(http,.com)"); + TEST_FPD(u"http://..com", u"(http,..com)"); + TEST_FPD(u"http://127.0.0.1", u"(http,127.0.0.1)"); + TEST_FPD(u"http://[::1]", u"(http,[::1])"); + TEST_FPD(u"about:config", + u"(about,about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla)"); + TEST_FPD(u"moz-extension://f5b6ca10-5bd4-4ed6-9baf-820dc5152bc1", u""); + TEST_FPD(u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}", + u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"); + TEST_FPD( + u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}" + u"?https://www.example.com", + u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"); + + Preferences::SetBool(FPI_PREF, oldFpiPref); + Preferences::SetBool(SITE_PREF, oldSitePref); +} + +} // namespace mozilla diff --git a/caps/tests/gtest/TestPrincipalAttributes.cpp b/caps/tests/gtest/TestPrincipalAttributes.cpp new file mode 100644 index 0000000000..bc0bff90f6 --- /dev/null +++ b/caps/tests/gtest/TestPrincipalAttributes.cpp @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "gtest/gtest.h" +#include "mozilla/BasePrincipal.h" +#include "nsScriptSecurityManager.h" + +using namespace mozilla; + +class PrincipalAttributesParam { + public: + nsAutoCString spec; + bool expectIsIpAddress; +}; + +class PrincipalAttributesTest + : public ::testing::TestWithParam<PrincipalAttributesParam> {}; + +TEST_P(PrincipalAttributesTest, PrincipalAttributesTest) { + nsCOMPtr<nsIScriptSecurityManager> ssm = + nsScriptSecurityManager::GetScriptSecurityManager(); + + nsAutoCString spec(GetParam().spec); + nsCOMPtr<nsIPrincipal> principal; + nsresult rv = + ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal)); + ASSERT_EQ(rv, NS_OK); + + ASSERT_EQ(principal->GetIsIpAddress(), GetParam().expectIsIpAddress); +} + +static const PrincipalAttributesParam kAttributes[] = { + {nsAutoCString("https://mozilla.com"), false}, + {nsAutoCString("https://127.0.0.1"), true}, + {nsAutoCString("https://[::1]"), true}, +}; + +INSTANTIATE_TEST_SUITE_P(TestPrincipalAttributes, PrincipalAttributesTest, + ::testing::ValuesIn(kAttributes)); diff --git a/caps/tests/gtest/TestPrincipalSerialization.cpp b/caps/tests/gtest/TestPrincipalSerialization.cpp new file mode 100644 index 0000000000..159cf1c269 --- /dev/null +++ b/caps/tests/gtest/TestPrincipalSerialization.cpp @@ -0,0 +1,214 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "gtest/gtest.h" +#include "mozilla/Base64.h" +#include "mozilla/BasePrincipal.h" +#include "mozilla/ContentPrincipal.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/SystemPrincipal.h" +#include "mozilla/ExpandedPrincipal.h" + +using mozilla::BasePrincipal; +using mozilla::ContentPrincipal; +using mozilla::NullPrincipal; +using mozilla::SystemPrincipal; + +// None of these tests work in debug due to assert guards +#ifndef MOZ_DEBUG + +// calling toJson() twice with the same string arg +// (ensure that we truncate correctly where needed) +TEST(PrincipalSerialization, ReusedJSONArgument) +{ + nsCOMPtr<nsIScriptSecurityManager> ssm = + nsScriptSecurityManager::GetScriptSecurityManager(); + + nsAutoCString spec("https://mozilla.com"); + nsCOMPtr<nsIPrincipal> principal; + nsresult rv = + ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal)); + ASSERT_EQ(rv, NS_OK); + + nsAutoCString JSON; + rv = BasePrincipal::Cast(principal)->ToJSON(JSON); + ASSERT_EQ(rv, NS_OK); + ASSERT_TRUE(JSON.EqualsLiteral("{\"1\":{\"0\":\"https://mozilla.com/\"}}")); + + nsAutoCString spec2("https://example.com"); + nsCOMPtr<nsIPrincipal> principal2; + rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2)); + ASSERT_EQ(rv, NS_OK); + + // Reuse JSON without truncation to check the code is doing this + rv = BasePrincipal::Cast(principal2)->ToJSON(JSON); + ASSERT_EQ(rv, NS_OK); + ASSERT_TRUE(JSON.EqualsLiteral("{\"1\":{\"0\":\"https://example.com/\"}}")); +} + +// Assure that calling FromProperties() with an empty array list always returns +// a nullptr The exception here is SystemPrincipal which doesn't have fields but +// it also doesn't implement FromProperties These are overly cautious checks +// that we don't try to create a principal in reality FromProperties is only +// called with a populated array. +TEST(PrincipalSerialization, FromPropertiesEmpty) +{ + nsTArray<ContentPrincipal::KeyVal> resContent; + nsCOMPtr<nsIPrincipal> contentPrincipal = + ContentPrincipal::FromProperties(resContent); + ASSERT_EQ(nullptr, contentPrincipal); + + nsTArray<ExpandedPrincipal::KeyVal> resExpanded; + nsCOMPtr<nsIPrincipal> expandedPrincipal = + ExpandedPrincipal::FromProperties(resExpanded); + ASSERT_EQ(nullptr, expandedPrincipal); + + nsTArray<NullPrincipal::KeyVal> resNull; + nsCOMPtr<nsIPrincipal> nullprincipal = NullPrincipal::FromProperties(resNull); + ASSERT_EQ(nullptr, nullprincipal); +} + +// Double check that if we have two valid principals in a serialized JSON that +// nullptr is returned +TEST(PrincipalSerialization, TwoKeys) +{ + // Sanity check that this returns a system principal + nsCOMPtr<nsIPrincipal> systemPrincipal = + BasePrincipal::FromJSON("{\"3\":{}}"_ns); + ASSERT_EQ(BasePrincipal::Cast(systemPrincipal)->Kind(), + BasePrincipal::eSystemPrincipal); + + // Sanity check that this returns a content principal + nsCOMPtr<nsIPrincipal> contentPrincipal = + BasePrincipal::FromJSON("{\"1\":{\"0\":\"https://mozilla.com\"}}"_ns); + ASSERT_EQ(BasePrincipal::Cast(contentPrincipal)->Kind(), + BasePrincipal::eContentPrincipal); + + // Check both combined don't return a principal + nsCOMPtr<nsIPrincipal> combinedPrincipal = BasePrincipal::FromJSON( + "{\"1\":{\"0\":\"https://mozilla.com\"},\"3\":{}}"_ns); + ASSERT_EQ(nullptr, combinedPrincipal); +} + +#endif // ifndef MOZ_DEBUG + +TEST(PrincipalSerialization, ExpandedPrincipal) +{ + // Check basic Expandedprincipal works without OA + nsCOMPtr<nsIScriptSecurityManager> ssm = + nsScriptSecurityManager::GetScriptSecurityManager(); + + uint32_t length = 2; + nsTArray<nsCOMPtr<nsIPrincipal> > allowedDomains(length); + allowedDomains.SetLength(length); + + nsAutoCString spec("https://mozilla.com"); + nsCOMPtr<nsIPrincipal> principal; + nsresult rv = + ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principal)->Kind(), + BasePrincipal::eContentPrincipal); + allowedDomains[0] = principal; + + nsAutoCString spec2("https://mozilla.org"); + nsCOMPtr<nsIPrincipal> principal2; + rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principal2)->Kind(), + BasePrincipal::eContentPrincipal); + allowedDomains[1] = principal2; + + mozilla::OriginAttributes attrs; + RefPtr<ExpandedPrincipal> result = + ExpandedPrincipal::Create(allowedDomains, attrs); + ASSERT_EQ(BasePrincipal::Cast(result)->Kind(), + BasePrincipal::eExpandedPrincipal); + + nsAutoCString JSON; + rv = BasePrincipal::Cast(result)->ToJSON(JSON); + ASSERT_EQ(rv, NS_OK); + ASSERT_STREQ(JSON.get(), + "{\"2\":{\"0\":[{\"1\":{\"0\":\"https://mozilla.com/" + "\"}},{\"1\":{\"0\":\"https://mozilla.org/\"}}]}}"); + + nsCOMPtr<nsIPrincipal> returnedPrincipal = BasePrincipal::FromJSON(JSON); + auto outPrincipal = BasePrincipal::Cast(returnedPrincipal); + ASSERT_EQ(outPrincipal->Kind(), BasePrincipal::eExpandedPrincipal); + + ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal)); + ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal2)); + + nsAutoCString specDev("https://mozilla.dev"); + nsCOMPtr<nsIPrincipal> principalDev; + rv = ssm->CreateContentPrincipalFromOrigin(specDev, + getter_AddRefs(principalDev)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principalDev)->Kind(), + BasePrincipal::eContentPrincipal); + + ASSERT_FALSE(outPrincipal->FastSubsumesIgnoringFPD(principalDev)); +} + +TEST(PrincipalSerialization, ExpandedPrincipalOA) +{ + // Check Expandedprincipal works with top level OA + nsCOMPtr<nsIScriptSecurityManager> ssm = + nsScriptSecurityManager::GetScriptSecurityManager(); + + uint32_t length = 2; + nsTArray<nsCOMPtr<nsIPrincipal> > allowedDomains(length); + allowedDomains.SetLength(length); + + nsAutoCString spec("https://mozilla.com"); + nsCOMPtr<nsIPrincipal> principal; + nsresult rv = + ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principal)->Kind(), + BasePrincipal::eContentPrincipal); + allowedDomains[0] = principal; + + nsAutoCString spec2("https://mozilla.org"); + nsCOMPtr<nsIPrincipal> principal2; + rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principal2)->Kind(), + BasePrincipal::eContentPrincipal); + allowedDomains[1] = principal2; + + mozilla::OriginAttributes attrs; + nsAutoCString suffix("^userContextId=1"); + bool ok = attrs.PopulateFromSuffix(suffix); + ASSERT_TRUE(ok); + + RefPtr<ExpandedPrincipal> result = + ExpandedPrincipal::Create(allowedDomains, attrs); + ASSERT_EQ(BasePrincipal::Cast(result)->Kind(), + BasePrincipal::eExpandedPrincipal); + + nsAutoCString JSON; + rv = BasePrincipal::Cast(result)->ToJSON(JSON); + ASSERT_EQ(rv, NS_OK); + ASSERT_STREQ(JSON.get(), + "{\"2\":{\"0\":[{\"1\":{\"0\":\"https://mozilla.com/" + "\"}},{\"1\":{\"0\":\"https://mozilla.org/" + "\"}}],\"1\":\"^userContextId=1\"}}"); + + nsCOMPtr<nsIPrincipal> returnedPrincipal = BasePrincipal::FromJSON(JSON); + auto outPrincipal = BasePrincipal::Cast(returnedPrincipal); + ASSERT_EQ(outPrincipal->Kind(), BasePrincipal::eExpandedPrincipal); + + ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal)); + ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal2)); + + nsAutoCString specDev("https://mozilla.dev"); + nsCOMPtr<nsIPrincipal> principalDev; + rv = ssm->CreateContentPrincipalFromOrigin(specDev, + getter_AddRefs(principalDev)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principalDev)->Kind(), + BasePrincipal::eContentPrincipal); + + ASSERT_FALSE(outPrincipal->FastSubsumesIgnoringFPD(principalDev)); +} diff --git a/caps/tests/gtest/TestRedirectChainURITruncation.cpp b/caps/tests/gtest/TestRedirectChainURITruncation.cpp new file mode 100644 index 0000000000..34c633499c --- /dev/null +++ b/caps/tests/gtest/TestRedirectChainURITruncation.cpp @@ -0,0 +1,231 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "gtest/gtest.h" +#include "mozilla/BasePrincipal.h" +#include "mozilla/ContentPrincipal.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/SystemPrincipal.h" +#include "mozilla/ExpandedPrincipal.h" +#include "nsContentUtils.h" +#include "mozilla/LoadInfo.h" + +namespace mozilla { + +void checkPrincipalTruncation(nsIPrincipal* aPrincipal, + const nsACString& aExpectedSpec = ""_ns, + const nsTArray<nsCString>& aExpectedSpecs = {}) { + nsCOMPtr<nsIPrincipal> truncatedPrincipal = + net::CreateTruncatedPrincipal(aPrincipal); + ASSERT_TRUE(truncatedPrincipal); + + if (aPrincipal->IsSystemPrincipal()) { + ASSERT_TRUE(truncatedPrincipal->IsSystemPrincipal()); + return; + } + + if (aPrincipal->GetIsNullPrincipal()) { + nsCOMPtr<nsIPrincipal> precursorPrincipal = + aPrincipal->GetPrecursorPrincipal(); + + nsAutoCString principalSpecEnding("}"); + nsAutoCString expectedTestSpec(aExpectedSpec); + if (!aExpectedSpec.IsEmpty()) { + principalSpecEnding += "?"_ns; + expectedTestSpec += "/"_ns; + } + + if (precursorPrincipal) { + nsAutoCString precursorSpec; + precursorPrincipal->GetAsciiSpec(precursorSpec); + ASSERT_TRUE(precursorSpec.Equals(expectedTestSpec)); + } + + // NullPrincipals have UUIDs as part of their scheme i.e. + // moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42} + // To avoid having to know the UUID beforehand we check the principal's spec + // before and after the UUID + nsAutoCString principalSpec; + truncatedPrincipal->GetAsciiSpec(principalSpec); + ASSERT_TRUE(StringBeginsWith(principalSpec, "moz-nullprincipal:{"_ns)); + ASSERT_TRUE( + StringEndsWith(principalSpec, principalSpecEnding + aExpectedSpec)); + return; + } + + if (aPrincipal->GetIsExpandedPrincipal()) { + const nsTArray<nsCOMPtr<nsIPrincipal>>& truncatedAllowList = + BasePrincipal::Cast(truncatedPrincipal) + ->As<ExpandedPrincipal>() + ->AllowList(); + + for (size_t i = 0; i < aExpectedSpecs.Length(); ++i) { + nsAutoCString principalSpec; + truncatedAllowList[i]->GetAsciiSpec(principalSpec); + ASSERT_TRUE(principalSpec.Equals(aExpectedSpecs[i])); + } + return; + } + + if (aPrincipal->GetIsContentPrincipal()) { + nsAutoCString principalSpec; + truncatedPrincipal->GetAsciiSpec(principalSpec); + ASSERT_TRUE(principalSpec.Equals(aExpectedSpec)); + return; + } + + // Tests should not reach this point + ADD_FAILURE(); +} + +void checkPrincipalTruncation(nsIPrincipal* aPrincipal, + const nsTArray<nsCString>& aExpectedSpecs = {}) { + checkPrincipalTruncation(aPrincipal, ""_ns, aExpectedSpecs); +} + +TEST(RedirectChainURITruncation, ContentPrincipal) +{ + // ======================= HTTP Scheme ======================= + nsAutoCString httpSpec( + "http://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + nsCOMPtr<nsIURI> uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), httpSpec); + ASSERT_EQ(rv, NS_OK); + + nsCOMPtr<nsIPrincipal> principal; + OriginAttributes attrs; + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, + "http://www.example.com:200/foo/bar/baz.html"_ns); + + // ======================= HTTPS Scheme ======================= + nsAutoCString httpsSpec( + "https://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + rv = NS_NewURI(getter_AddRefs(uri), httpsSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, + "https://www.example.com:200/foo/bar/baz.html"_ns); + + // ======================= View Source Scheme ======================= + nsAutoCString viewSourceSpec( + "view-source:https://root:toor@www.example.com:200/foo/bar/" + "baz.html?qux#thud"); + rv = NS_NewURI(getter_AddRefs(uri), viewSourceSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation( + principal, "view-source:https://www.example.com:200/foo/bar/baz.html"_ns); + + // ======================= About Scheme ======================= + nsAutoCString aboutSpec("about:config"); + rv = NS_NewURI(getter_AddRefs(uri), aboutSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, "about:config"_ns); + + // ======================= Resource Scheme ======================= + nsAutoCString resourceSpec("resource://testing/"); + rv = NS_NewURI(getter_AddRefs(uri), resourceSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, "resource://testing/"_ns); + + // ======================= Chrome Scheme ======================= + nsAutoCString chromeSpec("chrome://foo/content/bar.xul"); + rv = NS_NewURI(getter_AddRefs(uri), chromeSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, "chrome://foo/content/bar.xul"_ns); +} + +TEST(RedirectChainURITruncation, NullPrincipal) +{ + // ======================= NullPrincipal ======================= + nsCOMPtr<nsIPrincipal> principal = + NullPrincipal::CreateWithoutOriginAttributes(); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, ""_ns); + + // ======================= NullPrincipal & Precursor ======================= + nsAutoCString precursorSpec( + "https://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + + nsCOMPtr<nsIURI> precursorURI; + nsresult rv = NS_NewURI(getter_AddRefs(precursorURI), precursorSpec); + ASSERT_EQ(rv, NS_OK); + + OriginAttributes attrs; + nsCOMPtr<nsIPrincipal> precursorPrincipal = + BasePrincipal::CreateContentPrincipal(precursorURI, attrs); + principal = NullPrincipal::CreateWithInheritedAttributes(precursorPrincipal); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, "https://www.example.com:200"_ns); +} + +TEST(RedirectChainURITruncation, SystemPrincipal) +{ + nsCOMPtr<nsIPrincipal> principal = nsContentUtils::GetSystemPrincipal(); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, ""_ns); +} + +TEST(RedirectChainURITruncation, ExtendedPrincipal) +{ + // ======================= HTTP Scheme ======================= + nsAutoCString httpSpec( + "http://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + nsCOMPtr<nsIURI> uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), httpSpec); + ASSERT_EQ(rv, NS_OK); + + nsCOMPtr<nsIPrincipal> firstContentPrincipal; + OriginAttributes attrs; + firstContentPrincipal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(firstContentPrincipal); + + // ======================= HTTPS Scheme ======================= + nsCOMPtr<nsIPrincipal> secondContentPrincipal; + nsAutoCString httpsSpec( + "https://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + rv = NS_NewURI(getter_AddRefs(uri), httpsSpec); + ASSERT_EQ(rv, NS_OK); + + secondContentPrincipal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(secondContentPrincipal); + + // ======================= ExpandedPrincipal ======================= + const nsTArray<nsCString>& expectedSpecs = { + "http://www.example.com:200/foo/bar/baz.html"_ns, + "https://www.example.com:200/foo/bar/baz.html"_ns, + }; + nsTArray<nsCOMPtr<nsIPrincipal>> allowList = {firstContentPrincipal, + secondContentPrincipal}; + nsCOMPtr<nsIPrincipal> principal = + ExpandedPrincipal::Create(allowList, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, expectedSpecs); +} + +} // namespace mozilla diff --git a/caps/tests/gtest/moz.build b/caps/tests/gtest/moz.build new file mode 100644 index 0000000000..10b1a66f3b --- /dev/null +++ b/caps/tests/gtest/moz.build @@ -0,0 +1,18 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +UNIFIED_SOURCES += [ + "TestBackgroundThreadPrincipal.cpp", + "TestNullPrincipalPrecursor.cpp", + "TestOriginAttributes.cpp", + "TestPrincipalAttributes.cpp", + "TestPrincipalSerialization.cpp", + "TestRedirectChainURITruncation.cpp", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul-gtest" |