1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 #include "gtest/gtest.h"
5 #include "mozilla/BasePrincipal.h"
6 #include "mozilla/ContentPrincipal.h"
7 #include "mozilla/NullPrincipal.h"
8 #include "mozilla/SystemPrincipal.h"
9 #include "mozilla/ExpandedPrincipal.h"
10
11 using mozilla::BasePrincipal;
12 using mozilla::ContentPrincipal;
13 using mozilla::NullPrincipal;
14 using mozilla::SystemPrincipal;
15
16 // None of these tests work in debug due to assert guards
17 #ifndef MOZ_DEBUG
18
19 // calling toJson() twice with the same string arg
20 // (ensure that we truncate correctly where needed)
TEST(PrincipalSerialization,ReusedJSONArgument)21 TEST(PrincipalSerialization, ReusedJSONArgument)
22 {
23 nsCOMPtr<nsIScriptSecurityManager> ssm =
24 nsScriptSecurityManager::GetScriptSecurityManager();
25
26 nsAutoCString spec("https://mozilla.com");
27 nsCOMPtr<nsIPrincipal> principal;
28 nsresult rv =
29 ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal));
30 ASSERT_EQ(rv, NS_OK);
31
32 nsAutoCString JSON;
33 rv = BasePrincipal::Cast(principal)->ToJSON(JSON);
34 ASSERT_EQ(rv, NS_OK);
35 ASSERT_TRUE(JSON.EqualsLiteral("{\"1\":{\"0\":\"https://mozilla.com/\"}}"));
36
37 nsAutoCString spec2("https://example.com");
38 nsCOMPtr<nsIPrincipal> principal2;
39 rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2));
40 ASSERT_EQ(rv, NS_OK);
41
42 // Reuse JSON without truncation to check the code is doing this
43 rv = BasePrincipal::Cast(principal2)->ToJSON(JSON);
44 ASSERT_EQ(rv, NS_OK);
45 ASSERT_TRUE(JSON.EqualsLiteral("{\"1\":{\"0\":\"https://example.com/\"}}"));
46 }
47
48 // Assure that calling FromProperties() with an empty array list always returns
49 // a nullptr The exception here is SystemPrincipal which doesn't have fields but
50 // it also doesn't implement FromProperties These are overly cautious checks
51 // that we don't try to create a principal in reality FromProperties is only
52 // called with a populated array.
TEST(PrincipalSerialization,FromPropertiesEmpty)53 TEST(PrincipalSerialization, FromPropertiesEmpty)
54 {
55 nsTArray<ContentPrincipal::KeyVal> resContent;
56 nsCOMPtr<nsIPrincipal> contentPrincipal =
57 ContentPrincipal::FromProperties(resContent);
58 ASSERT_EQ(nullptr, contentPrincipal);
59
60 nsTArray<ExpandedPrincipal::KeyVal> resExpanded;
61 nsCOMPtr<nsIPrincipal> expandedPrincipal =
62 ExpandedPrincipal::FromProperties(resExpanded);
63 ASSERT_EQ(nullptr, expandedPrincipal);
64
65 nsTArray<NullPrincipal::KeyVal> resNull;
66 nsCOMPtr<nsIPrincipal> nullprincipal = NullPrincipal::FromProperties(resNull);
67 ASSERT_EQ(nullptr, nullprincipal);
68 }
69
70 // Double check that if we have two valid principals in a serialized JSON that
71 // nullptr is returned
TEST(PrincipalSerialization,TwoKeys)72 TEST(PrincipalSerialization, TwoKeys)
73 {
74 // Sanity check that this returns a system principal
75 nsCOMPtr<nsIPrincipal> systemPrincipal =
76 BasePrincipal::FromJSON("{\"3\":{}}"_ns);
77 ASSERT_EQ(BasePrincipal::Cast(systemPrincipal)->Kind(),
78 BasePrincipal::eSystemPrincipal);
79
80 // Sanity check that this returns a content principal
81 nsCOMPtr<nsIPrincipal> contentPrincipal =
82 BasePrincipal::FromJSON("{\"1\":{\"0\":\"https://mozilla.com\"}}"_ns);
83 ASSERT_EQ(BasePrincipal::Cast(contentPrincipal)->Kind(),
84 BasePrincipal::eContentPrincipal);
85
86 // Check both combined don't return a principal
87 nsCOMPtr<nsIPrincipal> combinedPrincipal = BasePrincipal::FromJSON(
88 "{\"1\":{\"0\":\"https://mozilla.com\"},\"3\":{}}"_ns);
89 ASSERT_EQ(nullptr, combinedPrincipal);
90 }
91
92 #endif // ifndef MOZ_DEBUG
93
TEST(PrincipalSerialization,ExpandedPrincipal)94 TEST(PrincipalSerialization, ExpandedPrincipal)
95 {
96 // Check basic Expandedprincipal works without OA
97 nsCOMPtr<nsIScriptSecurityManager> ssm =
98 nsScriptSecurityManager::GetScriptSecurityManager();
99
100 uint32_t length = 2;
101 nsTArray<nsCOMPtr<nsIPrincipal> > allowedDomains(length);
102 allowedDomains.SetLength(length);
103
104 nsAutoCString spec("https://mozilla.com");
105 nsCOMPtr<nsIPrincipal> principal;
106 nsresult rv =
107 ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal));
108 ASSERT_EQ(rv, NS_OK);
109 ASSERT_EQ(BasePrincipal::Cast(principal)->Kind(),
110 BasePrincipal::eContentPrincipal);
111 allowedDomains[0] = principal;
112
113 nsAutoCString spec2("https://mozilla.org");
114 nsCOMPtr<nsIPrincipal> principal2;
115 rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2));
116 ASSERT_EQ(rv, NS_OK);
117 ASSERT_EQ(BasePrincipal::Cast(principal2)->Kind(),
118 BasePrincipal::eContentPrincipal);
119 allowedDomains[1] = principal2;
120
121 OriginAttributes attrs;
122 RefPtr<ExpandedPrincipal> result =
123 ExpandedPrincipal::Create(allowedDomains, attrs);
124 ASSERT_EQ(BasePrincipal::Cast(result)->Kind(),
125 BasePrincipal::eExpandedPrincipal);
126
127 nsAutoCString JSON;
128 rv = BasePrincipal::Cast(result)->ToJSON(JSON);
129 ASSERT_EQ(rv, NS_OK);
130 ASSERT_STREQ(
131 JSON.get(),
132 "{\"2\":{\"0\":\"eyIxIjp7IjAiOiJodHRwczovL21vemlsbGEuY29tLyJ9fQ==,"
133 "eyIxIjp7IjAiOiJodHRwczovL21vemlsbGEub3JnLyJ9fQ==\"}}");
134
135 nsCOMPtr<nsIPrincipal> returnedPrincipal = BasePrincipal::FromJSON(JSON);
136 auto outPrincipal = BasePrincipal::Cast(returnedPrincipal);
137 ASSERT_EQ(outPrincipal->Kind(), BasePrincipal::eExpandedPrincipal);
138
139 ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal));
140 ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal2));
141
142 nsAutoCString specDev("https://mozilla.dev");
143 nsCOMPtr<nsIPrincipal> principalDev;
144 rv = ssm->CreateContentPrincipalFromOrigin(specDev,
145 getter_AddRefs(principalDev));
146 ASSERT_EQ(rv, NS_OK);
147 ASSERT_EQ(BasePrincipal::Cast(principalDev)->Kind(),
148 BasePrincipal::eContentPrincipal);
149
150 ASSERT_FALSE(outPrincipal->FastSubsumesIgnoringFPD(principalDev));
151 }
152
TEST(PrincipalSerialization,ExpandedPrincipalOA)153 TEST(PrincipalSerialization, ExpandedPrincipalOA)
154 {
155 // Check Expandedprincipal works with top level OA
156 nsCOMPtr<nsIScriptSecurityManager> ssm =
157 nsScriptSecurityManager::GetScriptSecurityManager();
158
159 uint32_t length = 2;
160 nsTArray<nsCOMPtr<nsIPrincipal> > allowedDomains(length);
161 allowedDomains.SetLength(length);
162
163 nsAutoCString spec("https://mozilla.com");
164 nsCOMPtr<nsIPrincipal> principal;
165 nsresult rv =
166 ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal));
167 ASSERT_EQ(rv, NS_OK);
168 ASSERT_EQ(BasePrincipal::Cast(principal)->Kind(),
169 BasePrincipal::eContentPrincipal);
170 allowedDomains[0] = principal;
171
172 nsAutoCString spec2("https://mozilla.org");
173 nsCOMPtr<nsIPrincipal> principal2;
174 rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2));
175 ASSERT_EQ(rv, NS_OK);
176 ASSERT_EQ(BasePrincipal::Cast(principal2)->Kind(),
177 BasePrincipal::eContentPrincipal);
178 allowedDomains[1] = principal2;
179
180 OriginAttributes attrs;
181 nsAutoCString suffix("^userContextId=1");
182 bool ok = attrs.PopulateFromSuffix(suffix);
183 ASSERT_TRUE(ok);
184
185 RefPtr<ExpandedPrincipal> result =
186 ExpandedPrincipal::Create(allowedDomains, attrs);
187 ASSERT_EQ(BasePrincipal::Cast(result)->Kind(),
188 BasePrincipal::eExpandedPrincipal);
189
190 nsAutoCString JSON;
191 rv = BasePrincipal::Cast(result)->ToJSON(JSON);
192 ASSERT_EQ(rv, NS_OK);
193 ASSERT_STREQ(
194 JSON.get(),
195 "{\"2\":{\"0\":\"eyIxIjp7IjAiOiJodHRwczovL21vemlsbGEuY29tLyJ9fQ==,"
196 "eyIxIjp7IjAiOiJodHRwczovL21vemlsbGEub3JnLyJ9fQ==\",\"1\":\"^"
197 "userContextId=1\"}}");
198
199 nsCOMPtr<nsIPrincipal> returnedPrincipal = BasePrincipal::FromJSON(JSON);
200 auto outPrincipal = BasePrincipal::Cast(returnedPrincipal);
201 ASSERT_EQ(outPrincipal->Kind(), BasePrincipal::eExpandedPrincipal);
202
203 ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal));
204 ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal2));
205
206 nsAutoCString specDev("https://mozilla.dev");
207 nsCOMPtr<nsIPrincipal> principalDev;
208 rv = ssm->CreateContentPrincipalFromOrigin(specDev,
209 getter_AddRefs(principalDev));
210 ASSERT_EQ(rv, NS_OK);
211 ASSERT_EQ(BasePrincipal::Cast(principalDev)->Kind(),
212 BasePrincipal::eContentPrincipal);
213
214 ASSERT_FALSE(outPrincipal->FastSubsumesIgnoringFPD(principalDev));
215 }
216