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