1 // Copyright 2011 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 #include <string>
6
7 #include "base/strings/string_util.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/simple_test_clock.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "base/time/time.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/network_anonymization_key.h"
15 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
16 #include "net/base/schemeful_site.h"
17 #include "net/http/http_auth_cache.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "url/gurl.h"
20 #include "url/scheme_host_port.h"
21
22 using base::ASCIIToUTF16;
23
24 namespace net {
25
26 namespace {
27
28 const char kRealm1[] = "Realm1";
29 const char kRealm2[] = "Realm2";
30 const char kRealm3[] = "Realm3";
31 const char kRealm4[] = "Realm4";
32 const char kRealm5[] = "Realm5";
33 const std::u16string k123(u"123");
34 const std::u16string k1234(u"1234");
35 const std::u16string k12345(u"12345");
36 const std::u16string kAdmin(u"admin");
37 const std::u16string kAlice(u"alice");
38 const std::u16string kAlice2(u"alice2");
39 const std::u16string kAlice3(u"alice3");
40 const std::u16string kPassword(u"password");
41 const std::u16string kRoot(u"root");
42 const std::u16string kUsername(u"username");
43 const std::u16string kWileCoyote(u"wilecoyote");
44
CreateASCIICredentials(const char * username,const char * password)45 AuthCredentials CreateASCIICredentials(const char* username,
46 const char* password) {
47 return AuthCredentials(ASCIIToUTF16(username), ASCIIToUTF16(password));
48 }
49
DoesUrlMatchFilter(const std::set<std::string> & domains,const GURL & url)50 bool DoesUrlMatchFilter(const std::set<std::string>& domains, const GURL& url) {
51 std::string url_registerable_domain =
52 net::registry_controlled_domains::GetDomainAndRegistry(
53 url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
54 bool found_domain = (domains.find(url_registerable_domain != ""
55 ? url_registerable_domain
56 : url.host()) != domains.end());
57
58 return found_domain;
59 }
60
61 } // namespace
62
63 // Test adding and looking-up cache entries (both by realm and by path).
TEST(HttpAuthCacheTest,Basic)64 TEST(HttpAuthCacheTest, Basic) {
65 url::SchemeHostPort scheme_host_port(GURL("http://www.google.com"));
66 url::SchemeHostPort scheme_host_port2(GURL("http://www.foobar.com"));
67 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
68 HttpAuthCache::Entry* entry;
69
70 // Add cache entries for 4 realms: "Realm1", "Realm2", "Realm3" and
71 // "Realm4"
72
73 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
74 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
75 "Basic realm=Realm1",
76 CreateASCIICredentials("realm1-user", "realm1-password"),
77 "/foo/bar/index.html");
78
79 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
80 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
81 "Basic realm=Realm2",
82 CreateASCIICredentials("realm2-user", "realm2-password"),
83 "/foo2/index.html");
84
85 cache.Add(
86 scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
87 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
88 "Basic realm=Realm3",
89 CreateASCIICredentials("realm3-basic-user", "realm3-basic-password"),
90 std::string());
91
92 cache.Add(
93 scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
94 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey(),
95 "Digest realm=Realm3",
96 CreateASCIICredentials("realm3-digest-user", "realm3-digest-password"),
97 "/baz/index.html");
98
99 cache.Add(
100 scheme_host_port, HttpAuth::AUTH_SERVER, kRealm4,
101 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
102 "Basic realm=Realm4",
103 CreateASCIICredentials("realm4-basic-user", "realm4-basic-password"),
104 "/");
105
106 cache.Add(scheme_host_port2, HttpAuth::AUTH_SERVER, kRealm5,
107 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
108 "Basic realm=Realm5",
109 CreateASCIICredentials("realm5-user", "realm5-password"), "/");
110 cache.Add(
111 scheme_host_port2, HttpAuth::AUTH_SERVER, kRealm3,
112 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
113 "Basic realm=Realm3",
114 CreateASCIICredentials("realm3-basic-user", "realm3-basic-password"),
115 std::string());
116
117 // There is no Realm5 in `scheme_host_port`.
118 entry = cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm5,
119 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
120 EXPECT_FALSE(entry);
121
122 // While Realm3 does exist, the scheme is wrong.
123 entry = cache.Lookup(url::SchemeHostPort(GURL("https://www.google.com")),
124 HttpAuth::AUTH_SERVER, kRealm3,
125 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
126 EXPECT_FALSE(entry);
127
128 // Realm, scheme ok, authentication scheme wrong
129 entry = cache.Lookup(url::SchemeHostPort(GURL("https://www.google.com")),
130 HttpAuth::AUTH_SERVER, kRealm1,
131 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey());
132 EXPECT_FALSE(entry);
133
134 // Valid lookup by SchemeHostPort, realm, scheme.
135 entry = cache.Lookup(url::SchemeHostPort(GURL("http://www.google.com:80")),
136 HttpAuth::AUTH_SERVER, kRealm3,
137 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
138 ASSERT_TRUE(entry);
139 EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
140 EXPECT_EQ(kRealm3, entry->realm());
141 EXPECT_EQ("Basic realm=Realm3", entry->auth_challenge());
142 EXPECT_EQ(u"realm3-basic-user", entry->credentials().username());
143 EXPECT_EQ(u"realm3-basic-password", entry->credentials().password());
144
145 // Same realm, scheme with different SchemeHostPorts.
146 HttpAuthCache::Entry* entry2 =
147 cache.Lookup(url::SchemeHostPort(GURL("http://www.foobar.com:80")),
148 HttpAuth::AUTH_SERVER, kRealm3, HttpAuth::AUTH_SCHEME_BASIC,
149 NetworkAnonymizationKey());
150 ASSERT_TRUE(entry2);
151 EXPECT_NE(entry, entry2);
152
153 // Valid lookup by SchemeHostPort, realm, scheme when there's a duplicate
154 // SchemeHostPort, realm in the cache.
155 entry = cache.Lookup(url::SchemeHostPort(GURL("http://www.google.com:80")),
156 HttpAuth::AUTH_SERVER, kRealm3,
157 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey());
158 ASSERT_TRUE(entry);
159 EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, entry->scheme());
160 EXPECT_EQ(kRealm3, entry->realm());
161 EXPECT_EQ("Digest realm=Realm3", entry->auth_challenge());
162 EXPECT_EQ(u"realm3-digest-user", entry->credentials().username());
163 EXPECT_EQ(u"realm3-digest-password", entry->credentials().password());
164
165 // Valid lookup by realm.
166 entry = cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
167 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
168 ASSERT_TRUE(entry);
169 EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
170 EXPECT_EQ(kRealm2, entry->realm());
171 EXPECT_EQ("Basic realm=Realm2", entry->auth_challenge());
172 EXPECT_EQ(u"realm2-user", entry->credentials().username());
173 EXPECT_EQ(u"realm2-password", entry->credentials().password());
174
175 // Check that subpaths are recognized.
176 HttpAuthCache::Entry* p_realm2_entry =
177 cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
178 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
179 HttpAuthCache::Entry* p_realm4_entry =
180 cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm4,
181 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
182 EXPECT_TRUE(p_realm2_entry);
183 EXPECT_TRUE(p_realm4_entry);
184 HttpAuthCache::Entry realm2_entry = *p_realm2_entry;
185 HttpAuthCache::Entry realm4_entry = *p_realm4_entry;
186 // Realm4 applies to '/' and Realm2 applies to '/foo2/'.
187 // LookupByPath() should return the closest enclosing path.
188 // Positive tests:
189 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
190 NetworkAnonymizationKey(), "/foo2/index.html");
191 EXPECT_TRUE(realm2_entry.IsEqualForTesting(*entry));
192 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
193 NetworkAnonymizationKey(), "/foo2/foobar.html");
194 EXPECT_TRUE(realm2_entry.IsEqualForTesting(*entry));
195 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
196 NetworkAnonymizationKey(), "/foo2/bar/index.html");
197 EXPECT_TRUE(realm2_entry.IsEqualForTesting(*entry));
198 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
199 NetworkAnonymizationKey(), "/foo2/");
200 EXPECT_TRUE(realm2_entry.IsEqualForTesting(*entry));
201 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
202 NetworkAnonymizationKey(), "/foo2");
203 EXPECT_TRUE(realm4_entry.IsEqualForTesting(*entry));
204 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
205 NetworkAnonymizationKey(), "/");
206 EXPECT_TRUE(realm4_entry.IsEqualForTesting(*entry));
207
208 // Negative tests:
209 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
210 NetworkAnonymizationKey(), "/foo3/index.html");
211 EXPECT_FALSE(realm2_entry.IsEqualForTesting(*entry));
212 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
213 NetworkAnonymizationKey(), std::string());
214 EXPECT_FALSE(realm2_entry.IsEqualForTesting(*entry));
215
216 // Confirm we find the same realm, different auth scheme by path lookup
217 HttpAuthCache::Entry* p_realm3_digest_entry =
218 cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
219 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey());
220 EXPECT_TRUE(p_realm3_digest_entry);
221 HttpAuthCache::Entry realm3_digest_entry = *p_realm3_digest_entry;
222 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
223 NetworkAnonymizationKey(), "/baz/index.html");
224 EXPECT_TRUE(realm3_digest_entry.IsEqualForTesting(*entry));
225 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
226 NetworkAnonymizationKey(), "/baz/");
227 EXPECT_TRUE(realm3_digest_entry.IsEqualForTesting(*entry));
228 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
229 NetworkAnonymizationKey(), "/baz");
230 EXPECT_FALSE(realm3_digest_entry.IsEqualForTesting(*entry));
231
232 // Confirm we find the same realm, different auth scheme by path lookup
233 HttpAuthCache::Entry* p_realm3DigestEntry =
234 cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
235 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey());
236 EXPECT_TRUE(p_realm3DigestEntry);
237 HttpAuthCache::Entry realm3DigestEntry = *p_realm3DigestEntry;
238 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
239 NetworkAnonymizationKey(), "/baz/index.html");
240 EXPECT_TRUE(realm3DigestEntry.IsEqualForTesting(*entry));
241 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
242 NetworkAnonymizationKey(), "/baz/");
243 EXPECT_TRUE(realm3DigestEntry.IsEqualForTesting(*entry));
244 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
245 NetworkAnonymizationKey(), "/baz");
246 EXPECT_FALSE(realm3DigestEntry.IsEqualForTesting(*entry));
247
248 // Lookup using empty path (may be used for proxy).
249 entry = cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
250 NetworkAnonymizationKey(), std::string());
251 EXPECT_TRUE(entry);
252 EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, entry->scheme());
253 EXPECT_EQ(kRealm3, entry->realm());
254 }
255
256 // Make sure server and proxy credentials are treated separately.
TEST(HttpAuthCacheTest,SeparateByTarget)257 TEST(HttpAuthCacheTest, SeparateByTarget) {
258 const std::u16string kServerUser = u"server_user";
259 const std::u16string kServerPass = u"server_pass";
260 const std::u16string kProxyUser = u"proxy_user";
261 const std::u16string kProxyPass = u"proxy_pass";
262
263 const char kServerPath[] = "/foo/bar/index.html";
264
265 url::SchemeHostPort scheme_host_port(GURL("http://www.google.com"));
266 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
267 HttpAuthCache::Entry* entry;
268
269 // Add AUTH_SERVER entry.
270 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
271 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
272 "Basic realm=Realm1", AuthCredentials(kServerUser, kServerPass),
273 kServerPath);
274
275 // Make sure credentials are only accessible with AUTH_SERVER target.
276 entry = cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
277 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
278 ASSERT_TRUE(entry);
279 EXPECT_EQ(entry->credentials().username(), kServerUser);
280 EXPECT_EQ(entry->credentials().password(), kServerPass);
281 EXPECT_EQ(entry, cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
282 NetworkAnonymizationKey(), kServerPath));
283 EXPECT_FALSE(cache.Lookup(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm1,
284 HttpAuth::AUTH_SCHEME_BASIC,
285 NetworkAnonymizationKey()));
286 EXPECT_FALSE(cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_PROXY,
287 NetworkAnonymizationKey(), kServerPath));
288
289 // Add AUTH_PROXY entry with same SchemeHostPort and realm but different
290 // credentials.
291 cache.Add(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm1,
292 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
293 "Basic realm=Realm1", AuthCredentials(kProxyUser, kProxyPass), "/");
294
295 // Make sure credentials are only accessible with the corresponding target.
296 entry = cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
297 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
298 ASSERT_TRUE(entry);
299 EXPECT_EQ(entry->credentials().username(), kServerUser);
300 EXPECT_EQ(entry->credentials().password(), kServerPass);
301 EXPECT_EQ(entry, cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
302 NetworkAnonymizationKey(), kServerPath));
303 entry = cache.Lookup(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm1,
304 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
305 ASSERT_TRUE(entry);
306 EXPECT_EQ(entry->credentials().username(), kProxyUser);
307 EXPECT_EQ(entry->credentials().password(), kProxyPass);
308 EXPECT_EQ(entry, cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_PROXY,
309 NetworkAnonymizationKey(), "/"));
310
311 // Remove the AUTH_SERVER entry.
312 EXPECT_TRUE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
313 HttpAuth::AUTH_SCHEME_BASIC,
314 NetworkAnonymizationKey(),
315 AuthCredentials(kServerUser, kServerPass)));
316
317 // Verify that only the AUTH_SERVER entry was removed.
318 EXPECT_FALSE(cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
319 HttpAuth::AUTH_SCHEME_BASIC,
320 NetworkAnonymizationKey()));
321 EXPECT_FALSE(cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
322 NetworkAnonymizationKey(), kServerPath));
323 entry = cache.Lookup(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm1,
324 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
325 ASSERT_TRUE(entry);
326 EXPECT_EQ(entry->credentials().username(), kProxyUser);
327 EXPECT_EQ(entry->credentials().password(), kProxyPass);
328 EXPECT_EQ(entry, cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_PROXY,
329 NetworkAnonymizationKey(), "/"));
330
331 // Remove the AUTH_PROXY entry.
332 EXPECT_TRUE(cache.Remove(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm1,
333 HttpAuth::AUTH_SCHEME_BASIC,
334 NetworkAnonymizationKey(),
335 AuthCredentials(kProxyUser, kProxyPass)));
336
337 // Verify that neither entry remains.
338 EXPECT_FALSE(cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
339 HttpAuth::AUTH_SCHEME_BASIC,
340 NetworkAnonymizationKey()));
341 EXPECT_FALSE(cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
342 NetworkAnonymizationKey(), kServerPath));
343 EXPECT_FALSE(cache.Lookup(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm1,
344 HttpAuth::AUTH_SCHEME_BASIC,
345 NetworkAnonymizationKey()));
346 EXPECT_FALSE(cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_PROXY,
347 NetworkAnonymizationKey(), "/"));
348 }
349
350 // Make sure server credentials with different NetworkAnonymizationKeys are
351 // treated separately if |key_entries_by_network_anonymization_key| is set to
352 // true.
TEST(HttpAuthCacheTest,SeparateServersByNetworkAnonymizationKey)353 TEST(HttpAuthCacheTest, SeparateServersByNetworkAnonymizationKey) {
354 const SchemefulSite kSite1(GURL("https://foo.test/"));
355 auto kNetworkAnonymizationKey1 =
356 net::NetworkAnonymizationKey::CreateSameSite(kSite1);
357 const SchemefulSite kSite2(GURL("https://bar.test/"));
358 auto kNetworkAnonymizationKey2 =
359 net::NetworkAnonymizationKey::CreateSameSite(kSite2);
360
361 url::SchemeHostPort kSchemeHostPort(GURL("http://www.google.com"));
362 const char kPath[] = "/";
363
364 const std::u16string kUser1 = u"user1";
365 const std::u16string kPass1 = u"pass1";
366 const std::u16string kUser2 = u"user2";
367 const std::u16string kPass2 = u"pass2";
368
369 for (bool key_entries_by_network_anonymization_key : {false, true}) {
370 HttpAuthCache cache(key_entries_by_network_anonymization_key);
371 HttpAuthCache::Entry* entry;
372
373 // Add entry for kNetworkAnonymizationKey1.
374 cache.Add(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
375 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1,
376 "Basic realm=Realm1", AuthCredentials(kUser1, kPass1), kPath);
377
378 entry =
379 cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
380 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
381 ASSERT_TRUE(entry);
382 EXPECT_EQ(entry->credentials().username(), kUser1);
383 EXPECT_EQ(entry->credentials().password(), kPass1);
384 EXPECT_EQ(entry, cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
385 kNetworkAnonymizationKey1, kPath));
386 if (key_entries_by_network_anonymization_key) {
387 EXPECT_FALSE(cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
388 HttpAuth::AUTH_SCHEME_BASIC,
389 kNetworkAnonymizationKey2));
390 EXPECT_FALSE(cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
391 kNetworkAnonymizationKey2, kPath));
392 } else {
393 EXPECT_EQ(entry, cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER,
394 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
395 kNetworkAnonymizationKey2));
396 EXPECT_EQ(entry,
397 cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
398 kNetworkAnonymizationKey2, kPath));
399 }
400
401 // Add entry for kNetworkAnonymizationKey2.
402 cache.Add(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
403 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2,
404 "Basic realm=Realm1", AuthCredentials(kUser2, kPass2), kPath);
405
406 entry =
407 cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
408 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2);
409 ASSERT_TRUE(entry);
410 EXPECT_EQ(entry->credentials().username(), kUser2);
411 EXPECT_EQ(entry->credentials().password(), kPass2);
412 EXPECT_EQ(entry, cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
413 kNetworkAnonymizationKey2, kPath));
414 entry =
415 cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
416 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
417 ASSERT_TRUE(entry);
418 EXPECT_EQ(entry, cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
419 kNetworkAnonymizationKey1, kPath));
420 if (key_entries_by_network_anonymization_key) {
421 EXPECT_EQ(entry->credentials().username(), kUser1);
422 EXPECT_EQ(entry->credentials().password(), kPass1);
423 } else {
424 EXPECT_EQ(entry->credentials().username(), kUser2);
425 EXPECT_EQ(entry->credentials().password(), kPass2);
426 }
427
428 // Remove the entry that was just added.
429 EXPECT_TRUE(cache.Remove(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
430 HttpAuth::AUTH_SCHEME_BASIC,
431 kNetworkAnonymizationKey2,
432 AuthCredentials(kUser2, kPass2)));
433
434 EXPECT_FALSE(cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
435 HttpAuth::AUTH_SCHEME_BASIC,
436 kNetworkAnonymizationKey2));
437 EXPECT_FALSE(cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
438 kNetworkAnonymizationKey2, kPath));
439 if (key_entries_by_network_anonymization_key) {
440 entry =
441 cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
442 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
443 ASSERT_TRUE(entry);
444 EXPECT_EQ(entry->credentials().username(), kUser1);
445 EXPECT_EQ(entry->credentials().password(), kPass1);
446 EXPECT_EQ(entry,
447 cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
448 kNetworkAnonymizationKey1, kPath));
449 } else {
450 EXPECT_FALSE(cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
451 HttpAuth::AUTH_SCHEME_BASIC,
452 kNetworkAnonymizationKey1));
453 EXPECT_FALSE(cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
454 kNetworkAnonymizationKey1, kPath));
455 }
456 }
457 }
458
459 // Make sure added proxy credentials ignore NetworkAnonymizationKey, even if if
460 // |key_entries_by_network_anonymization_key| is set to true.
TEST(HttpAuthCacheTest,NeverSeparateProxiesByNetworkAnonymizationKey)461 TEST(HttpAuthCacheTest, NeverSeparateProxiesByNetworkAnonymizationKey) {
462 const SchemefulSite kSite1(GURL("https://foo.test/"));
463 auto kNetworkAnonymizationKey1 =
464 net::NetworkAnonymizationKey::CreateSameSite(kSite1);
465 const SchemefulSite kSite2(GURL("https://bar.test/"));
466 auto kNetworkAnonymizationKey2 =
467 net::NetworkAnonymizationKey::CreateSameSite(kSite2);
468
469 url::SchemeHostPort kSchemeHostPort(GURL("http://www.google.com"));
470 const char kPath[] = "/";
471
472 const std::u16string kUser1 = u"user1";
473 const std::u16string kPass1 = u"pass1";
474 const std::u16string kUser2 = u"user2";
475 const std::u16string kPass2 = u"pass2";
476
477 for (bool key_entries_by_network_anonymization_key : {false, true}) {
478 HttpAuthCache cache(key_entries_by_network_anonymization_key);
479 HttpAuthCache::Entry* entry;
480
481 // Add entry for kNetworkAnonymizationKey1.
482 cache.Add(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
483 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1,
484 "Basic realm=Realm1", AuthCredentials(kUser1, kPass1), kPath);
485
486 entry =
487 cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
488 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
489 ASSERT_TRUE(entry);
490 EXPECT_EQ(entry->credentials().username(), kUser1);
491 EXPECT_EQ(entry->credentials().password(), kPass1);
492 EXPECT_EQ(entry, cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_PROXY,
493 kNetworkAnonymizationKey1, kPath));
494 EXPECT_EQ(entry, cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_PROXY,
495 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
496 kNetworkAnonymizationKey2));
497 EXPECT_EQ(entry, cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_PROXY,
498 kNetworkAnonymizationKey2, kPath));
499
500 // Add entry for kNetworkAnonymizationKey2. It should overwrite the entry
501 // for kNetworkAnonymizationKey1.
502 cache.Add(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
503 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2,
504 "Basic realm=Realm1", AuthCredentials(kUser2, kPass2), kPath);
505
506 entry =
507 cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
508 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2);
509 ASSERT_TRUE(entry);
510 EXPECT_EQ(entry->credentials().username(), kUser2);
511 EXPECT_EQ(entry->credentials().password(), kPass2);
512 EXPECT_EQ(entry, cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_PROXY,
513 kNetworkAnonymizationKey2, kPath));
514 EXPECT_EQ(entry, cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_PROXY,
515 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
516 kNetworkAnonymizationKey1));
517 EXPECT_EQ(entry, cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_PROXY,
518 kNetworkAnonymizationKey1, kPath));
519
520 // Remove the entry that was just added using an empty
521 // NetworkAnonymizationKey.
522 EXPECT_TRUE(cache.Remove(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
523 HttpAuth::AUTH_SCHEME_BASIC,
524 NetworkAnonymizationKey(),
525 AuthCredentials(kUser2, kPass2)));
526
527 EXPECT_FALSE(cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
528 HttpAuth::AUTH_SCHEME_BASIC,
529 kNetworkAnonymizationKey2));
530 EXPECT_FALSE(cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_PROXY,
531 kNetworkAnonymizationKey2, kPath));
532 EXPECT_FALSE(cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
533 HttpAuth::AUTH_SCHEME_BASIC,
534 kNetworkAnonymizationKey1));
535 EXPECT_FALSE(cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_PROXY,
536 kNetworkAnonymizationKey1, kPath));
537 }
538 }
539
540 // Test that SetKeyServerEntriesByNetworkAnonymizationKey() deletes server
541 // credentials when it toggles the setting. This test uses an empty
542 // NetworkAnonymizationKey() for all entries, as the interesting part of this
543 // method is what type entries are deleted, which doesn't depend on the
544 // NetworkAnonymizationKey the entries use.
TEST(HttpAuthCacheTest,SetKeyServerEntriesByNetworkAnonymizationKey)545 TEST(HttpAuthCacheTest, SetKeyServerEntriesByNetworkAnonymizationKey) {
546 const url::SchemeHostPort kSchemeHostPort(GURL("http://www.google.com"));
547 const char kPath[] = "/";
548
549 const std::u16string kUser1 = u"user1";
550 const std::u16string kPass1 = u"pass1";
551 const std::u16string kUser2 = u"user2";
552 const std::u16string kPass2 = u"pass2";
553
554 for (bool initially_key_entries_by_network_anonymization_key :
555 {false, true}) {
556 for (bool to_key_entries_by_network_anonymization_key : {false, true}) {
557 HttpAuthCache cache(initially_key_entries_by_network_anonymization_key);
558 EXPECT_EQ(initially_key_entries_by_network_anonymization_key,
559 cache.key_server_entries_by_network_anonymization_key());
560
561 cache.Add(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
562 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
563 "Basic realm=Realm1", AuthCredentials(kUser1, kPass1), kPath);
564 cache.Add(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
565 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
566 "Basic realm=Realm1", AuthCredentials(kUser2, kPass2), kPath);
567
568 EXPECT_TRUE(cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_PROXY, kRealm1,
569 HttpAuth::AUTH_SCHEME_BASIC,
570 NetworkAnonymizationKey()));
571 EXPECT_TRUE(cache.Lookup(kSchemeHostPort, HttpAuth::AUTH_SERVER, kRealm1,
572 HttpAuth::AUTH_SCHEME_BASIC,
573 NetworkAnonymizationKey()));
574
575 cache.SetKeyServerEntriesByNetworkAnonymizationKey(
576 to_key_entries_by_network_anonymization_key);
577 EXPECT_EQ(to_key_entries_by_network_anonymization_key,
578 cache.key_server_entries_by_network_anonymization_key());
579
580 // AUTH_PROXY credentials should always remain in the cache.
581 HttpAuthCache::Entry* entry =
582 cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_PROXY,
583 NetworkAnonymizationKey(), kPath);
584 ASSERT_TRUE(entry);
585 EXPECT_EQ(entry->credentials().username(), kUser1);
586 EXPECT_EQ(entry->credentials().password(), kPass1);
587
588 entry = cache.LookupByPath(kSchemeHostPort, HttpAuth::AUTH_SERVER,
589 NetworkAnonymizationKey(), kPath);
590 // AUTH_SERVER credentials should only remain in the cache if the proxy
591 // configuration changes.
592 EXPECT_EQ(initially_key_entries_by_network_anonymization_key ==
593 to_key_entries_by_network_anonymization_key,
594 !!entry);
595 if (entry) {
596 EXPECT_EQ(entry->credentials().username(), kUser2);
597 EXPECT_EQ(entry->credentials().password(), kPass2);
598 }
599 }
600 }
601 }
602
TEST(HttpAuthCacheTest,AddPath)603 TEST(HttpAuthCacheTest, AddPath) {
604 HttpAuthCache::Entry entry;
605
606 // All of these paths have a common root /1/2/2/4/5/
607 entry.AddPath("/1/2/3/4/5/x.txt");
608 entry.AddPath("/1/2/3/4/5/y.txt");
609 entry.AddPath("/1/2/3/4/5/z.txt");
610
611 EXPECT_EQ(1U, entry.paths_.size());
612 EXPECT_EQ("/1/2/3/4/5/", entry.paths_.front());
613
614 // Add a new entry (not a subpath).
615 entry.AddPath("/1/XXX/q");
616 EXPECT_EQ(2U, entry.paths_.size());
617 EXPECT_EQ("/1/XXX/", entry.paths_.front());
618 EXPECT_EQ("/1/2/3/4/5/", entry.paths_.back());
619
620 // Add containing paths of /1/2/3/4/5/ -- should swallow up the deeper paths.
621 entry.AddPath("/1/2/3/4/x.txt");
622 EXPECT_EQ(2U, entry.paths_.size());
623 EXPECT_EQ("/1/2/3/4/", entry.paths_.front());
624 EXPECT_EQ("/1/XXX/", entry.paths_.back());
625 entry.AddPath("/1/2/3/x");
626 EXPECT_EQ(2U, entry.paths_.size());
627 EXPECT_EQ("/1/2/3/", entry.paths_.front());
628 EXPECT_EQ("/1/XXX/", entry.paths_.back());
629
630 entry.AddPath("/index.html");
631 EXPECT_EQ(1U, entry.paths_.size());
632 EXPECT_EQ("/", entry.paths_.front());
633 }
634
635 // Calling Add when the realm entry already exists, should append that
636 // path.
TEST(HttpAuthCacheTest,AddToExistingEntry)637 TEST(HttpAuthCacheTest, AddToExistingEntry) {
638 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
639 url::SchemeHostPort scheme_host_port(GURL("http://www.foobar.com:70"));
640 const std::string kAuthChallenge = "Basic realm=MyRealm";
641 const std::string kRealm = "MyRealm";
642
643 HttpAuthCache::Entry* orig_entry = cache.Add(
644 scheme_host_port, HttpAuth::AUTH_SERVER, kRealm,
645 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(), kAuthChallenge,
646 CreateASCIICredentials("user1", "password1"), "/x/y/z/");
647 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm,
648 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
649 kAuthChallenge, CreateASCIICredentials("user2", "password2"),
650 "/z/y/x/");
651 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm,
652 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
653 kAuthChallenge, CreateASCIICredentials("user3", "password3"),
654 "/z/y");
655
656 HttpAuthCache::Entry* entry =
657 cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm,
658 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
659
660 EXPECT_TRUE(entry == orig_entry);
661 EXPECT_EQ(u"user3", entry->credentials().username());
662 EXPECT_EQ(u"password3", entry->credentials().password());
663
664 EXPECT_EQ(2U, entry->paths_.size());
665 EXPECT_EQ("/z/", entry->paths_.front());
666 EXPECT_EQ("/x/y/z/", entry->paths_.back());
667 }
668
TEST(HttpAuthCacheTest,Remove)669 TEST(HttpAuthCacheTest, Remove) {
670 url::SchemeHostPort scheme_host_port(GURL("http://foobar2.com"));
671
672 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
673 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
674 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
675 "basic realm=Realm1", AuthCredentials(kAlice, k123), "/");
676 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
677 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
678 "basic realm=Realm2", CreateASCIICredentials("bob", "princess"),
679 "/");
680 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
681 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
682 "basic realm=Realm3", AuthCredentials(kAdmin, kPassword), "/");
683 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
684 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey(),
685 "digest realm=Realm3", AuthCredentials(kRoot, kWileCoyote), "/");
686
687 // Fails, because there is no realm "Realm5".
688 EXPECT_FALSE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm5,
689 HttpAuth::AUTH_SCHEME_BASIC,
690 NetworkAnonymizationKey(),
691 AuthCredentials(kAlice, k123)));
692
693 // Fails because the origin is wrong.
694 EXPECT_FALSE(
695 cache.Remove(url::SchemeHostPort(GURL("http://foobar2.com:100")),
696 HttpAuth::AUTH_SERVER, kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
697 NetworkAnonymizationKey(), AuthCredentials(kAlice, k123)));
698
699 // Fails because the username is wrong.
700 EXPECT_FALSE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
701 HttpAuth::AUTH_SCHEME_BASIC,
702 NetworkAnonymizationKey(),
703 AuthCredentials(kAlice2, k123)));
704
705 // Fails because the password is wrong.
706 EXPECT_FALSE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
707 HttpAuth::AUTH_SCHEME_BASIC,
708 NetworkAnonymizationKey(),
709 AuthCredentials(kAlice, k1234)));
710
711 // Fails because the authentication type is wrong.
712 EXPECT_FALSE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
713 HttpAuth::AUTH_SCHEME_DIGEST,
714 NetworkAnonymizationKey(),
715 AuthCredentials(kAlice, k123)));
716
717 // Succeeds.
718 EXPECT_TRUE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
719 HttpAuth::AUTH_SCHEME_BASIC,
720 NetworkAnonymizationKey(),
721 AuthCredentials(kAlice, k123)));
722
723 // Fails because we just deleted the entry!
724 EXPECT_FALSE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
725 HttpAuth::AUTH_SCHEME_BASIC,
726 NetworkAnonymizationKey(),
727 AuthCredentials(kAlice, k123)));
728
729 // Succeed when there are two authentication types for the same origin,realm.
730 EXPECT_TRUE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
731 HttpAuth::AUTH_SCHEME_DIGEST,
732 NetworkAnonymizationKey(),
733 AuthCredentials(kRoot, kWileCoyote)));
734
735 // Succeed as above, but when entries were added in opposite order
736 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
737 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey(),
738 "digest realm=Realm3", AuthCredentials(kRoot, kWileCoyote), "/");
739 EXPECT_TRUE(cache.Remove(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
740 HttpAuth::AUTH_SCHEME_BASIC,
741 NetworkAnonymizationKey(),
742 AuthCredentials(kAdmin, kPassword)));
743
744 // Make sure that removing one entry still leaves the other available for
745 // lookup.
746 HttpAuthCache::Entry* entry =
747 cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
748 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey());
749 EXPECT_FALSE(nullptr == entry);
750 }
751
TEST(HttpAuthCacheTest,ClearEntriesAddedBetween)752 TEST(HttpAuthCacheTest, ClearEntriesAddedBetween) {
753 url::SchemeHostPort scheme_host_port(GURL("http://foobar.com"));
754
755 base::Time start_time;
756 ASSERT_TRUE(base::Time::FromString("30 May 2018 12:00:00", &start_time));
757 base::SimpleTestClock test_clock;
758 test_clock.SetNow(start_time);
759
760 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
761 cache.set_clock_for_testing(&test_clock);
762
763 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
764 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
765 "basic realm=Realm1", AuthCredentials(kAlice, k123), "/");
766 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
767 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
768 "basic realm=Realm2", AuthCredentials(kRoot, kWileCoyote), "/");
769
770 test_clock.Advance(base::Seconds(10)); // Time now 12:00:10
771 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
772 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
773 "basic realm=Realm3", AuthCredentials(kAlice2, k1234), "/");
774 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm4,
775 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
776 "basic realm=Realm4", AuthCredentials(kUsername, kPassword), "/");
777 // Add path to existing entry.
778 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
779 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
780 "basic realm=Realm2", AuthCredentials(kAdmin, kPassword), "/baz/");
781
782 test_clock.Advance(base::Seconds(10)); // Time now 12:00:20
783 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm5,
784 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
785 "basic realm=Realm5", AuthCredentials(kAlice3, k12345), "/");
786
787 base::Time test_time1;
788 ASSERT_TRUE(base::Time::FromString("30 May 2018 12:00:05", &test_time1));
789 base::Time test_time2;
790 ASSERT_TRUE(base::Time::FromString("30 May 2018 12:00:15", &test_time2));
791 cache.ClearEntriesAddedBetween(test_time1, test_time2,
792 base::RepeatingCallback<bool(const GURL&)>());
793
794 // Realms 1 and 2 are older than 12:00:05 and should not be cleared
795 EXPECT_NE(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
796 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
797 NetworkAnonymizationKey()));
798 EXPECT_NE(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
799 kRealm2, HttpAuth::AUTH_SCHEME_BASIC,
800 NetworkAnonymizationKey()));
801
802 // Realms 5 is newer than 12:00:15 and should not be cleared
803 EXPECT_NE(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
804 kRealm5, HttpAuth::AUTH_SCHEME_BASIC,
805 NetworkAnonymizationKey()));
806
807 // Creation time is set for a whole entry rather than for a particular path.
808 // Path added within the requested duration isn't be removed.
809 EXPECT_NE(nullptr, cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
810 NetworkAnonymizationKey(), "/baz/"));
811
812 // Realms 3 and 4 are between 12:00:05 and 12:00:10 and should be cleared.
813 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
814 kRealm3, HttpAuth::AUTH_SCHEME_BASIC,
815 NetworkAnonymizationKey()));
816 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
817 kRealm4, HttpAuth::AUTH_SCHEME_BASIC,
818 NetworkAnonymizationKey()));
819
820 cache.ClearEntriesAddedBetween(start_time - base::Seconds(1),
821 base::Time::Max(),
822 base::RepeatingCallback<bool(const GURL&)>());
823 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
824 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
825 NetworkAnonymizationKey()));
826 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
827 kRealm2, HttpAuth::AUTH_SCHEME_BASIC,
828 NetworkAnonymizationKey()));
829 EXPECT_EQ(nullptr, cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
830 NetworkAnonymizationKey(), "/baz/"));
831 }
832
TEST(HttpAuthCacheTest,ClearEntriesAddedBetweenByFilter)833 TEST(HttpAuthCacheTest, ClearEntriesAddedBetweenByFilter) {
834 url::SchemeHostPort scheme_host_port_1(GURL("http://foobar.com"));
835 url::SchemeHostPort scheme_host_port_2(GURL("http://foobar2.com"));
836
837 base::SimpleTestClock test_clock;
838 test_clock.SetNow(base::Time::Now());
839
840 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
841 cache.set_clock_for_testing(&test_clock);
842
843 cache.Add(scheme_host_port_1, HttpAuth::AUTH_SERVER, kRealm1,
844 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
845 "basic realm=Realm1", AuthCredentials(kAlice, k123), "/");
846 cache.Add(scheme_host_port_2, HttpAuth::AUTH_SERVER, kRealm1,
847 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
848 "basic realm=Realm1", AuthCredentials(kRoot, kWileCoyote), "/");
849
850 cache.ClearEntriesAddedBetween(
851 base::Time::Min(), base::Time::Max(),
852 base::BindRepeating(&DoesUrlMatchFilter,
853 std::set<std::string>({scheme_host_port_1.host()})));
854
855 // Only foobar.com should be cleared while foobar2.com remains.
856 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port_1, HttpAuth::AUTH_SERVER,
857 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
858 NetworkAnonymizationKey()));
859 EXPECT_NE(nullptr, cache.Lookup(scheme_host_port_2, HttpAuth::AUTH_SERVER,
860 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
861 NetworkAnonymizationKey()));
862 }
863
TEST(HttpAuthCacheTest,ClearEntriesAddedBetweenWithAllTimeValues)864 TEST(HttpAuthCacheTest, ClearEntriesAddedBetweenWithAllTimeValues) {
865 url::SchemeHostPort scheme_host_port(GURL("http://foobar.com"));
866
867 base::SimpleTestClock test_clock;
868 test_clock.SetNow(base::Time::Now());
869
870 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
871 cache.set_clock_for_testing(&test_clock);
872
873 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
874 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
875 "basic realm=Realm1", AuthCredentials(kAlice, k123), "/");
876 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
877 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
878 "basic realm=Realm2", AuthCredentials(kRoot, kWileCoyote), "/");
879
880 test_clock.Advance(base::Seconds(10));
881 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
882 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
883 "basic realm=Realm3", AuthCredentials(kAlice2, k1234), "/");
884 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm4,
885 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
886 "basic realm=Realm4", AuthCredentials(kUsername, kPassword), "/");
887 // Add path to existing entry.
888 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
889 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
890 "basic realm=Realm2", AuthCredentials(kAdmin, kPassword), "/baz/");
891
892 cache.ClearEntriesAddedBetween(base::Time::Min(), base::Time::Max(),
893 base::RepeatingCallback<bool(const GURL&)>());
894
895 // All entries should be cleared.
896 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
897 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
898 NetworkAnonymizationKey()));
899 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
900 kRealm2, HttpAuth::AUTH_SCHEME_BASIC,
901 NetworkAnonymizationKey()));
902 EXPECT_EQ(nullptr, cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
903 NetworkAnonymizationKey(), "/baz/"));
904 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
905 kRealm3, HttpAuth::AUTH_SCHEME_BASIC,
906 NetworkAnonymizationKey()));
907 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
908 kRealm4, HttpAuth::AUTH_SCHEME_BASIC,
909 NetworkAnonymizationKey()));
910 }
911
TEST(HttpAuthCacheTest,ClearAllEntries)912 TEST(HttpAuthCacheTest, ClearAllEntries) {
913 url::SchemeHostPort scheme_host_port(GURL("http://foobar.com"));
914
915 base::SimpleTestClock test_clock;
916 test_clock.SetNow(base::Time::Now());
917
918 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
919 cache.set_clock_for_testing(&test_clock);
920
921 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
922 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
923 "basic realm=Realm1", AuthCredentials(kAlice, k123), "/");
924 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
925 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
926 "basic realm=Realm2", AuthCredentials(kRoot, kWileCoyote), "/");
927
928 test_clock.Advance(base::Seconds(10));
929 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm3,
930 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
931 "basic realm=Realm3", AuthCredentials(kAlice2, k1234), "/");
932 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm4,
933 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
934 "basic realm=Realm4", AuthCredentials(kUsername, kPassword), "/");
935 // Add path to existing entry.
936 cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
937 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
938 "basic realm=Realm2", AuthCredentials(kAdmin, kPassword), "/baz/");
939
940 test_clock.Advance(base::Seconds(55));
941 cache.ClearAllEntries();
942
943 // All entries should be cleared.
944 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
945 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
946 NetworkAnonymizationKey()));
947 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
948 kRealm2, HttpAuth::AUTH_SCHEME_BASIC,
949 NetworkAnonymizationKey()));
950 EXPECT_EQ(nullptr, cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_SERVER,
951 NetworkAnonymizationKey(), "/baz/"));
952 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
953 kRealm3, HttpAuth::AUTH_SCHEME_BASIC,
954 NetworkAnonymizationKey()));
955 EXPECT_EQ(nullptr, cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
956 kRealm4, HttpAuth::AUTH_SCHEME_BASIC,
957 NetworkAnonymizationKey()));
958 }
959
TEST(HttpAuthCacheTest,UpdateStaleChallenge)960 TEST(HttpAuthCacheTest, UpdateStaleChallenge) {
961 HttpAuthCache cache(false /* key_entries_by_network_anonymization_key */);
962 url::SchemeHostPort scheme_host_port(GURL("http://foobar2.com"));
963 HttpAuthCache::Entry* entry_pre = cache.Add(
964 scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
965 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey(),
966 "Digest realm=Realm1,"
967 "nonce=\"s3MzvFhaBAA=4c520af5acd9d8d7ae26947529d18c8eae1e98f4\"",
968 CreateASCIICredentials("realm-digest-user", "realm-digest-password"),
969 "/baz/index.html");
970 ASSERT_TRUE(entry_pre != nullptr);
971
972 EXPECT_EQ(2, entry_pre->IncrementNonceCount());
973 EXPECT_EQ(3, entry_pre->IncrementNonceCount());
974 EXPECT_EQ(4, entry_pre->IncrementNonceCount());
975
976 bool update_success = cache.UpdateStaleChallenge(
977 scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
978 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey(),
979 "Digest realm=Realm1,"
980 "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\","
981 "stale=\"true\"");
982 EXPECT_TRUE(update_success);
983
984 // After the stale update, the entry should still exist in the cache and
985 // the nonce count should be reset to 0.
986 HttpAuthCache::Entry* entry_post =
987 cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
988 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey());
989 ASSERT_TRUE(entry_post != nullptr);
990 EXPECT_EQ(2, entry_post->IncrementNonceCount());
991
992 // UpdateStaleChallenge will fail if an entry doesn't exist in the cache.
993 bool update_failure = cache.UpdateStaleChallenge(
994 scheme_host_port, HttpAuth::AUTH_SERVER, kRealm2,
995 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey(),
996 "Digest realm=Realm2,"
997 "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\","
998 "stale=\"true\"");
999 EXPECT_FALSE(update_failure);
1000 }
1001
TEST(HttpAuthCacheTest,CopyProxyEntriesFrom)1002 TEST(HttpAuthCacheTest, CopyProxyEntriesFrom) {
1003 url::SchemeHostPort scheme_host_port(GURL("http://example.com"));
1004 std::string path("/some/path");
1005 std::string another_path("/another/path");
1006
1007 HttpAuthCache first_cache(
1008 false /* key_entries_by_network_anonymization_key */);
1009 HttpAuthCache::Entry* entry;
1010
1011 first_cache.Add(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm1,
1012 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
1013 "basic realm=Realm1", AuthCredentials(kAlice, k123), path);
1014 first_cache.Add(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm2,
1015 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
1016 "basic realm=Realm2", AuthCredentials(kAlice2, k1234), path);
1017 first_cache.Add(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm3,
1018 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey(),
1019 "digest realm=Realm3", AuthCredentials(kRoot, kWileCoyote),
1020 path);
1021 entry = first_cache.Add(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm3,
1022 HttpAuth::AUTH_SCHEME_DIGEST,
1023 NetworkAnonymizationKey(), "digest realm=Realm3",
1024 AuthCredentials(kRoot, kWileCoyote), another_path);
1025
1026 EXPECT_EQ(2, entry->IncrementNonceCount());
1027
1028 // Server entry, which should not be copied.
1029 first_cache.Add(scheme_host_port, HttpAuth::AUTH_SERVER, kRealm1,
1030 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
1031 "basic realm=Realm1", AuthCredentials(kAlice, k123), path);
1032
1033 HttpAuthCache second_cache(
1034 false /* key_entries_by_network_anonymization_key */);
1035 // Will be overwritten by kRoot:kWileCoyote.
1036 second_cache.Add(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm3,
1037 HttpAuth::AUTH_SCHEME_DIGEST, NetworkAnonymizationKey(),
1038 "digest realm=Realm3", AuthCredentials(kAlice2, k1234),
1039 path);
1040 // Should be left intact.
1041 second_cache.Add(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm4,
1042 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
1043 "basic realm=Realm4", AuthCredentials(kAdmin, kRoot), path);
1044
1045 second_cache.CopyProxyEntriesFrom(first_cache);
1046
1047 // Copied from first_cache.
1048 entry = second_cache.Lookup(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm1,
1049 HttpAuth::AUTH_SCHEME_BASIC,
1050 NetworkAnonymizationKey());
1051 EXPECT_TRUE(nullptr != entry);
1052 EXPECT_EQ(kAlice, entry->credentials().username());
1053 EXPECT_EQ(k123, entry->credentials().password());
1054
1055 // Copied from first_cache.
1056 entry = second_cache.Lookup(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm2,
1057 HttpAuth::AUTH_SCHEME_BASIC,
1058 NetworkAnonymizationKey());
1059 EXPECT_TRUE(nullptr != entry);
1060 EXPECT_EQ(kAlice2, entry->credentials().username());
1061 EXPECT_EQ(k1234, entry->credentials().password());
1062
1063 // Overwritten from first_cache.
1064 entry = second_cache.Lookup(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm3,
1065 HttpAuth::AUTH_SCHEME_DIGEST,
1066 NetworkAnonymizationKey());
1067 EXPECT_TRUE(nullptr != entry);
1068 EXPECT_EQ(kRoot, entry->credentials().username());
1069 EXPECT_EQ(kWileCoyote, entry->credentials().password());
1070 // Nonce count should get copied.
1071 EXPECT_EQ(3, entry->IncrementNonceCount());
1072
1073 // All paths should get copied.
1074 entry = second_cache.LookupByPath(scheme_host_port, HttpAuth::AUTH_PROXY,
1075 NetworkAnonymizationKey(), another_path);
1076 EXPECT_TRUE(nullptr != entry);
1077 EXPECT_EQ(kRoot, entry->credentials().username());
1078 EXPECT_EQ(kWileCoyote, entry->credentials().password());
1079
1080 // Left intact in second_cache.
1081 entry = second_cache.Lookup(scheme_host_port, HttpAuth::AUTH_PROXY, kRealm4,
1082 HttpAuth::AUTH_SCHEME_BASIC,
1083 NetworkAnonymizationKey());
1084 EXPECT_TRUE(nullptr != entry);
1085 EXPECT_EQ(kAdmin, entry->credentials().username());
1086 EXPECT_EQ(kRoot, entry->credentials().password());
1087
1088 // AUTH_SERVER entry should not have been copied from first_cache.
1089 EXPECT_TRUE(first_cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
1090 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
1091 NetworkAnonymizationKey()));
1092 EXPECT_FALSE(second_cache.Lookup(scheme_host_port, HttpAuth::AUTH_SERVER,
1093 kRealm1, HttpAuth::AUTH_SCHEME_BASIC,
1094 NetworkAnonymizationKey()));
1095 }
1096
1097 // Test fixture class for eviction tests (contains helpers for bulk
1098 // insertion and existence testing).
1099 class HttpAuthCacheEvictionTest : public testing::Test {
1100 protected:
HttpAuthCacheEvictionTest()1101 HttpAuthCacheEvictionTest()
1102 : scheme_host_port_(GURL("http://www.google.com")),
1103 cache_(false /* key_entries_by_network_anonymization_key */) {}
1104
GenerateRealm(int realm_i)1105 std::string GenerateRealm(int realm_i) {
1106 return base::StringPrintf("Realm %d", realm_i);
1107 }
1108
GeneratePath(int realm_i,int path_i)1109 std::string GeneratePath(int realm_i, int path_i) {
1110 return base::StringPrintf("/%d/%d/x/y", realm_i, path_i);
1111 }
1112
AddRealm(int realm_i)1113 void AddRealm(int realm_i) {
1114 AddPathToRealm(realm_i, 0);
1115 }
1116
AddPathToRealm(int realm_i,int path_i)1117 void AddPathToRealm(int realm_i, int path_i) {
1118 cache_.Add(scheme_host_port_, HttpAuth::AUTH_SERVER, GenerateRealm(realm_i),
1119 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
1120 std::string(), AuthCredentials(kUsername, kPassword),
1121 GeneratePath(realm_i, path_i));
1122 }
1123
CheckRealmExistence(int realm_i,bool exists)1124 void CheckRealmExistence(int realm_i, bool exists) {
1125 const HttpAuthCache::Entry* entry = cache_.Lookup(
1126 scheme_host_port_, HttpAuth::AUTH_SERVER, GenerateRealm(realm_i),
1127 HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey());
1128 if (exists) {
1129 EXPECT_FALSE(entry == nullptr);
1130 EXPECT_EQ(GenerateRealm(realm_i), entry->realm());
1131 } else {
1132 EXPECT_TRUE(entry == nullptr);
1133 }
1134 }
1135
CheckPathExistence(int realm_i,int path_i,bool exists)1136 void CheckPathExistence(int realm_i, int path_i, bool exists) {
1137 const HttpAuthCache::Entry* entry = cache_.LookupByPath(
1138 scheme_host_port_, HttpAuth::AUTH_SERVER, NetworkAnonymizationKey(),
1139 GeneratePath(realm_i, path_i));
1140 if (exists) {
1141 EXPECT_FALSE(entry == nullptr);
1142 EXPECT_EQ(GenerateRealm(realm_i), entry->realm());
1143 } else {
1144 EXPECT_TRUE(entry == nullptr);
1145 }
1146 }
1147
1148 url::SchemeHostPort scheme_host_port_;
1149 HttpAuthCache cache_;
1150
1151 static const int kMaxPaths = HttpAuthCache::kMaxNumPathsPerRealmEntry;
1152 static const int kMaxRealms = HttpAuthCache::kMaxNumRealmEntries;
1153 };
1154
1155 // Add the maxinim number of realm entries to the cache. Each of these entries
1156 // must still be retrievable. Next add three more entries -- since the cache is
1157 // full this causes FIFO eviction of the first three entries by time of last
1158 // use.
TEST_F(HttpAuthCacheEvictionTest,RealmEntryEviction)1159 TEST_F(HttpAuthCacheEvictionTest, RealmEntryEviction) {
1160 base::SimpleTestTickClock test_clock;
1161 test_clock.SetNowTicks(base::TimeTicks::Now());
1162 cache_.set_tick_clock_for_testing(&test_clock);
1163
1164 for (int i = 0; i < kMaxRealms; ++i) {
1165 AddRealm(i);
1166 test_clock.Advance(base::Seconds(1));
1167 }
1168
1169 for (int i = 0; i < kMaxRealms; ++i) {
1170 CheckRealmExistence(i, true);
1171 test_clock.Advance(base::Seconds(1));
1172 }
1173
1174 for (int i = 0; i < 3; ++i) {
1175 AddRealm(i + kMaxRealms);
1176 test_clock.Advance(base::Seconds(1));
1177 }
1178
1179 for (int i = 0; i < 3; ++i) {
1180 CheckRealmExistence(i, false);
1181 test_clock.Advance(base::Seconds(1));
1182 }
1183
1184 for (int i = 0; i < kMaxRealms; ++i) {
1185 CheckRealmExistence(i + 3, true);
1186 test_clock.Advance(base::Seconds(1));
1187 }
1188
1189 cache_.set_tick_clock_for_testing(nullptr);
1190 }
1191
1192 // Add the maximum number of paths to a single realm entry. Each of these
1193 // paths should be retrievable. Next add 3 more paths -- since the cache is
1194 // full this causes FIFO eviction of the first three paths.
TEST_F(HttpAuthCacheEvictionTest,RealmPathEviction)1195 TEST_F(HttpAuthCacheEvictionTest, RealmPathEviction) {
1196 for (int i = 0; i < kMaxPaths; ++i)
1197 AddPathToRealm(0, i);
1198
1199 for (int i = 1; i < kMaxRealms; ++i)
1200 AddRealm(i);
1201
1202 for (int i = 0; i < 3; ++i)
1203 AddPathToRealm(0, i + kMaxPaths);
1204
1205 for (int i = 0; i < 3; ++i)
1206 CheckPathExistence(0, i, false);
1207
1208 for (int i = 0; i < kMaxPaths; ++i)
1209 CheckPathExistence(0, i + 3, true);
1210
1211 for (int i = 0; i < kMaxRealms; ++i)
1212 CheckRealmExistence(i, true);
1213 }
1214
1215 } // namespace net
1216