http_auth_cache_unittest.cc 52 KB

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