• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/base/network_isolation_key.h"
11 
12 #include <optional>
13 
14 #include "base/test/scoped_feature_list.h"
15 #include "base/unguessable_token.h"
16 #include "base/values.h"
17 #include "net/base/features.h"
18 #include "net/base/schemeful_site.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "url/gurl.h"
21 #include "url/url_util.h"
22 
23 namespace net {
24 
25 namespace {
26 const char kDataUrl[] = "data:text/html,<body>Hello World</body>";
27 
TEST(NetworkIsolationKeyTest,EmptyKey)28 TEST(NetworkIsolationKeyTest, EmptyKey) {
29   NetworkIsolationKey key;
30   EXPECT_FALSE(key.IsFullyPopulated());
31   EXPECT_EQ(std::nullopt, key.ToCacheKeyString());
32   EXPECT_TRUE(key.IsTransient());
33   EXPECT_EQ("null null", key.ToDebugString());
34 }
35 
TEST(NetworkIsolationKeyTest,NonEmptySameSiteKey)36 TEST(NetworkIsolationKeyTest, NonEmptySameSiteKey) {
37   SchemefulSite site1 = SchemefulSite(GURL("http://a.test/"));
38   NetworkIsolationKey key(site1, site1);
39   EXPECT_TRUE(key.IsFullyPopulated());
40   EXPECT_EQ(site1.Serialize() + " " + site1.Serialize(),
41             key.ToCacheKeyString());
42   EXPECT_EQ(site1.GetDebugString() + " " + site1.GetDebugString(),
43             key.ToDebugString());
44   EXPECT_FALSE(key.IsTransient());
45 }
46 
TEST(NetworkIsolationKeyTest,NonEmptyCrossSiteKey)47 TEST(NetworkIsolationKeyTest, NonEmptyCrossSiteKey) {
48   SchemefulSite site1 = SchemefulSite(GURL("http://a.test/"));
49   SchemefulSite site2 = SchemefulSite(GURL("http://b.test/"));
50   NetworkIsolationKey key(site1, site2);
51   EXPECT_TRUE(key.IsFullyPopulated());
52   EXPECT_EQ(site1.Serialize() + " " + site2.Serialize(),
53             key.ToCacheKeyString());
54   EXPECT_EQ(site1.GetDebugString() + " " + site2.GetDebugString(),
55             key.ToDebugString());
56   EXPECT_FALSE(key.IsTransient());
57 }
58 
TEST(NetworkIsolationKeyTest,KeyWithNonce)59 TEST(NetworkIsolationKeyTest, KeyWithNonce) {
60   SchemefulSite site1 = SchemefulSite(GURL("http://a.test/"));
61   SchemefulSite site2 = SchemefulSite(GURL("http://b.test/"));
62   base::UnguessableToken nonce = base::UnguessableToken::Create();
63   NetworkIsolationKey key(site1, site2, nonce);
64   EXPECT_TRUE(key.IsFullyPopulated());
65   EXPECT_EQ(std::nullopt, key.ToCacheKeyString());
66   EXPECT_TRUE(key.IsTransient());
67   EXPECT_EQ(site1.GetDebugString() + " " + site2.GetDebugString() +
68                 " (with nonce " + nonce.ToString() + ")",
69             key.ToDebugString());
70 
71   // Create another NetworkIsolationKey with the same input parameters, and
72   // check that it is equal.
73   NetworkIsolationKey same_key(site1, site2, nonce);
74   EXPECT_EQ(key, same_key);
75 
76   // Create another NetworkIsolationKey with a different nonce and check that
77   // it's different.
78   base::UnguessableToken nonce2 = base::UnguessableToken::Create();
79   NetworkIsolationKey key2(site1, site2, nonce2);
80   EXPECT_NE(key, key2);
81   EXPECT_NE(key.ToDebugString(), key2.ToDebugString());
82 }
83 
TEST(NetworkIsolationKeyTest,OpaqueOriginKey)84 TEST(NetworkIsolationKeyTest, OpaqueOriginKey) {
85   SchemefulSite site_data = SchemefulSite(GURL(kDataUrl));
86   NetworkIsolationKey key(site_data, site_data);
87   EXPECT_TRUE(key.IsFullyPopulated());
88   EXPECT_EQ(std::nullopt, key.ToCacheKeyString());
89   EXPECT_TRUE(key.IsTransient());
90   EXPECT_EQ(site_data.GetDebugString() + " " + site_data.GetDebugString(),
91             key.ToDebugString());
92 
93   // Create another site with an opaque origin, and make sure it's different and
94   // has a different debug string.
95   SchemefulSite other_site = SchemefulSite(GURL(kDataUrl));
96   NetworkIsolationKey other_key(other_site, other_site);
97   EXPECT_NE(key, other_key);
98   EXPECT_NE(key.ToDebugString(), other_key.ToDebugString());
99   EXPECT_EQ(other_site.GetDebugString() + " " + other_site.GetDebugString(),
100             other_key.ToDebugString());
101 }
102 
TEST(NetworkIsolationKeyTest,OpaqueOriginTopLevelSiteKey)103 TEST(NetworkIsolationKeyTest, OpaqueOriginTopLevelSiteKey) {
104   SchemefulSite site1 = SchemefulSite(GURL("http://a.test/"));
105   SchemefulSite site_data = SchemefulSite(GURL(kDataUrl));
106   NetworkIsolationKey key(site_data, site1);
107   EXPECT_TRUE(key.IsFullyPopulated());
108   EXPECT_EQ(std::nullopt, key.ToCacheKeyString());
109   EXPECT_TRUE(key.IsTransient());
110   EXPECT_EQ(site_data.GetDebugString() + " " + site1.GetDebugString(),
111             key.ToDebugString());
112 
113   // Create another site with an opaque origin, and make sure it's different and
114   // has a different debug string.
115   SchemefulSite other_site = SchemefulSite(GURL(kDataUrl));
116   NetworkIsolationKey other_key(other_site, site1);
117   EXPECT_NE(key, other_key);
118   EXPECT_NE(key.ToDebugString(), other_key.ToDebugString());
119   EXPECT_EQ(other_site.GetDebugString() + " " + site1.GetDebugString(),
120             other_key.ToDebugString());
121 }
122 
TEST(NetworkIsolationKeyTest,OpaqueOriginIframeKey)123 TEST(NetworkIsolationKeyTest, OpaqueOriginIframeKey) {
124   SchemefulSite site1 = SchemefulSite(GURL("http://a.test/"));
125   SchemefulSite site_data = SchemefulSite(GURL(kDataUrl));
126   NetworkIsolationKey key(site1, site_data);
127   EXPECT_TRUE(key.IsFullyPopulated());
128   EXPECT_EQ(std::nullopt, key.ToCacheKeyString());
129   EXPECT_TRUE(key.IsTransient());
130   EXPECT_EQ(site1.GetDebugString() + " " + site_data.GetDebugString(),
131             key.ToDebugString());
132 
133   // Create another site with an opaque origin iframe, and make sure it's
134   // different and has a different debug string when the frame site is in use.
135   SchemefulSite other_site = SchemefulSite(GURL(kDataUrl));
136   NetworkIsolationKey other_key(site1, other_site);
137   EXPECT_NE(key, other_key);
138   EXPECT_NE(key.ToDebugString(), other_key.ToDebugString());
139   EXPECT_EQ(site1.GetDebugString() + " " + other_site.GetDebugString(),
140             other_key.ToDebugString());
141 }
142 
TEST(NetworkIsolationKeyTest,Operators)143 TEST(NetworkIsolationKeyTest, Operators) {
144   base::UnguessableToken nonce1 = base::UnguessableToken::Create();
145   base::UnguessableToken nonce2 = base::UnguessableToken::Create();
146   if (nonce2 < nonce1)
147     std::swap(nonce1, nonce2);
148   // These are in ascending order.
149   const NetworkIsolationKey kKeys[] = {
150       NetworkIsolationKey(),
151       // Site with unique origins are still sorted by scheme, so data is before
152       // file, and file before http.
153       NetworkIsolationKey(SchemefulSite(GURL(kDataUrl)),
154                           SchemefulSite(GURL(kDataUrl))),
155       NetworkIsolationKey(SchemefulSite(GURL("file:///foo")),
156                           SchemefulSite(GURL("file:///foo"))),
157       NetworkIsolationKey(SchemefulSite(GURL("http://a.test/")),
158                           SchemefulSite(GURL("http://a.test/"))),
159       NetworkIsolationKey(SchemefulSite(GURL("http://b.test/")),
160                           SchemefulSite(GURL("http://b.test/"))),
161       NetworkIsolationKey(SchemefulSite(GURL("https://a.test/")),
162                           SchemefulSite(GURL("https://a.test/"))),
163       NetworkIsolationKey(SchemefulSite(GURL("https://a.test/")),
164                           SchemefulSite(GURL("https://a.test/")), nonce1),
165       NetworkIsolationKey(SchemefulSite(GURL("https://a.test/")),
166                           SchemefulSite(GURL("https://a.test/")), nonce2),
167   };
168 
169   for (size_t first = 0; first < std::size(kKeys); ++first) {
170     NetworkIsolationKey key1 = kKeys[first];
171     SCOPED_TRACE(key1.ToDebugString());
172 
173     EXPECT_TRUE(key1 == key1);
174     EXPECT_FALSE(key1 != key1);
175     EXPECT_FALSE(key1 < key1);
176 
177     // Make sure that copying a key doesn't change the results of any operation.
178     // This check is a bit more interesting with unique origins.
179     NetworkIsolationKey key1_copy = key1;
180     EXPECT_TRUE(key1 == key1_copy);
181     EXPECT_FALSE(key1 < key1_copy);
182     EXPECT_FALSE(key1_copy < key1);
183 
184     for (size_t second = first + 1; second < std::size(kKeys); ++second) {
185       NetworkIsolationKey key2 = kKeys[second];
186       SCOPED_TRACE(key2.ToDebugString());
187 
188       EXPECT_TRUE(key1 < key2);
189       EXPECT_FALSE(key2 < key1);
190       EXPECT_FALSE(key1 == key2);
191       EXPECT_FALSE(key2 == key1);
192     }
193   }
194 }
195 
TEST(NetworkIsolationKeyTest,UniqueOriginOperators)196 TEST(NetworkIsolationKeyTest, UniqueOriginOperators) {
197   const auto kSite1 = SchemefulSite(GURL(kDataUrl));
198   const auto kSite2 = SchemefulSite(GURL(kDataUrl));
199   NetworkIsolationKey key1(kSite1, kSite1);
200   NetworkIsolationKey key2(kSite2, kSite2);
201 
202   EXPECT_TRUE(key1 == key1);
203   EXPECT_TRUE(key2 == key2);
204 
205   // Creating copies shouldn't affect comparison result.
206   EXPECT_TRUE(NetworkIsolationKey(key1) == NetworkIsolationKey(key1));
207   EXPECT_TRUE(NetworkIsolationKey(key2) == NetworkIsolationKey(key2));
208 
209   EXPECT_FALSE(key1 == key2);
210   EXPECT_FALSE(key2 == key1);
211 
212   // Order of Nonces isn't predictable, but they should have an ordering.
213   EXPECT_TRUE(key1 < key2 || key2 < key1);
214   EXPECT_TRUE(!(key1 < key2) || !(key2 < key1));
215 }
216 
TEST(NetworkIsolationKeyTest,OpaqueSiteKeyBoth)217 TEST(NetworkIsolationKeyTest, OpaqueSiteKeyBoth) {
218   SchemefulSite site_data_1 = SchemefulSite(GURL(kDataUrl));
219   SchemefulSite site_data_2 = SchemefulSite(GURL(kDataUrl));
220   SchemefulSite site_data_3 = SchemefulSite(GURL(kDataUrl));
221 
222   NetworkIsolationKey key1(site_data_1, site_data_2);
223   NetworkIsolationKey key2(site_data_1, site_data_2);
224   NetworkIsolationKey key3(site_data_1, site_data_3);
225 
226   // All the keys should be fully populated and transient.
227   EXPECT_TRUE(key1.IsFullyPopulated());
228   EXPECT_TRUE(key2.IsFullyPopulated());
229   EXPECT_TRUE(key3.IsFullyPopulated());
230   EXPECT_TRUE(key1.IsTransient());
231   EXPECT_TRUE(key2.IsTransient());
232   EXPECT_TRUE(key3.IsTransient());
233 
234   // Test the equality/comparisons of the various keys
235   EXPECT_TRUE(key1 == key2);
236   EXPECT_FALSE(key1 < key2 || key2 < key1);
237   EXPECT_FALSE(key1 == key3);
238   EXPECT_TRUE(key1 < key3 || key3 < key1);
239   EXPECT_NE(key1.ToDebugString(), key3.ToDebugString());
240 
241   // Test the ToString and ToDebugString
242   EXPECT_EQ(key1.ToDebugString(), key2.ToDebugString());
243   EXPECT_EQ(std::nullopt, key1.ToCacheKeyString());
244   EXPECT_EQ(std::nullopt, key2.ToCacheKeyString());
245   EXPECT_EQ(std::nullopt, key3.ToCacheKeyString());
246 }
247 
248 // Make sure that the logic to extract the registerable domain from an origin
249 // does not affect the host when using a non-standard scheme.
TEST(NetworkIsolationKeyTest,NonStandardScheme)250 TEST(NetworkIsolationKeyTest, NonStandardScheme) {
251   // Have to register the scheme, or SchemefulSite() will return an opaque
252   // origin.
253   url::ScopedSchemeRegistryForTests scoped_registry;
254   url::AddStandardScheme("foo", url::SCHEME_WITH_HOST);
255 
256   SchemefulSite site = SchemefulSite(GURL("foo://a.foo.com"));
257   NetworkIsolationKey key(site, site);
258   EXPECT_FALSE(key.GetTopFrameSite()->opaque());
259   EXPECT_EQ("foo://a.foo.com foo://a.foo.com", key.ToCacheKeyString());
260 }
261 
TEST(NetworkIsolationKeyTest,CreateWithNewFrameSite)262 TEST(NetworkIsolationKeyTest, CreateWithNewFrameSite) {
263   SchemefulSite site_a = SchemefulSite(GURL("http://a.com"));
264   SchemefulSite site_b = SchemefulSite(GURL("http://b.com"));
265   SchemefulSite site_c = SchemefulSite(GURL("http://c.com"));
266 
267   NetworkIsolationKey key(site_a, site_b);
268   NetworkIsolationKey key_c = key.CreateWithNewFrameSite(site_c);
269   EXPECT_EQ(site_c, key_c.GetFrameSiteForTesting());
270   EXPECT_NE(key_c, key);
271   EXPECT_EQ(site_a, key_c.GetTopFrameSite());
272 
273   // Ensure that `CreateWithNewFrameSite()` preserves the nonce if one exists.
274   base::UnguessableToken nonce = base::UnguessableToken::Create();
275   NetworkIsolationKey key_with_nonce(site_a, site_b, nonce);
276   NetworkIsolationKey key_with_nonce_c =
277       key_with_nonce.CreateWithNewFrameSite(site_c);
278   EXPECT_EQ(key_with_nonce.GetNonce(), key_with_nonce_c.GetNonce());
279   EXPECT_TRUE(key_with_nonce_c.IsTransient());
280 }
281 
TEST(NetworkIsolationKeyTest,CreateTransientForTesting)282 TEST(NetworkIsolationKeyTest, CreateTransientForTesting) {
283   NetworkIsolationKey transient_key =
284       NetworkIsolationKey::CreateTransientForTesting();
285   EXPECT_TRUE(transient_key.IsFullyPopulated());
286   EXPECT_TRUE(transient_key.IsTransient());
287   EXPECT_FALSE(transient_key.IsEmpty());
288   EXPECT_EQ(transient_key, transient_key);
289 
290   // Make sure that subsequent calls don't return the same NIK.
291   for (int i = 0; i < 1000; ++i) {
292     EXPECT_NE(transient_key, NetworkIsolationKey::CreateTransientForTesting());
293   }
294 }
295 
296 }  // namespace
297 
298 }  // namespace net
299