http_auth_cache.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  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. #ifndef NET_HTTP_HTTP_AUTH_CACHE_H_
  5. #define NET_HTTP_HTTP_AUTH_CACHE_H_
  6. #include <stddef.h>
  7. #include <list>
  8. #include <map>
  9. #include <string>
  10. #include "base/gtest_prod_util.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/time/default_clock.h"
  14. #include "base/time/default_tick_clock.h"
  15. #include "base/time/time.h"
  16. #include "net/base/net_export.h"
  17. #include "net/base/network_isolation_key.h"
  18. #include "net/http/http_auth.h"
  19. #include "url/scheme_host_port.h"
  20. namespace net {
  21. // HttpAuthCache stores HTTP authentication identities and challenge info.
  22. // For each (scheme_host_port, realm, scheme) triple the cache stores a
  23. // HttpAuthCache::Entry, which holds:
  24. // - the origin server {protocol scheme, host, port}
  25. // - the last identity used (username/password)
  26. // - the last auth handler used (contains realm and authentication scheme)
  27. // - the list of paths which used this realm
  28. // Entries can be looked up by either (origin, realm, scheme) or (origin, path).
  29. class NET_EXPORT HttpAuthCache {
  30. public:
  31. class NET_EXPORT Entry {
  32. public:
  33. Entry(const Entry& other);
  34. ~Entry();
  35. const url::SchemeHostPort& scheme_host_port() const {
  36. return scheme_host_port_;
  37. }
  38. // The case-sensitive realm string of the challenge.
  39. const std::string& realm() const { return realm_; }
  40. // The authentication scheme of the challenge.
  41. HttpAuth::Scheme scheme() const {
  42. return scheme_;
  43. }
  44. // The authentication challenge.
  45. const std::string& auth_challenge() const { return auth_challenge_; }
  46. // The login credentials.
  47. const AuthCredentials& credentials() const {
  48. return credentials_;
  49. }
  50. int IncrementNonceCount() {
  51. return ++nonce_count_;
  52. }
  53. void UpdateStaleChallenge(const std::string& auth_challenge);
  54. bool IsEqualForTesting(const Entry& other) const;
  55. bool operator==(const Entry& other) const = delete;
  56. private:
  57. friend class HttpAuthCache;
  58. FRIEND_TEST_ALL_PREFIXES(HttpAuthCacheTest, AddPath);
  59. FRIEND_TEST_ALL_PREFIXES(HttpAuthCacheTest, AddToExistingEntry);
  60. typedef std::list<std::string> PathList;
  61. Entry();
  62. // Adds a path defining the realm's protection space. If the path is
  63. // already contained in the protection space, is a no-op.
  64. void AddPath(const std::string& path);
  65. // Returns true if |dir| is contained within the realm's protection
  66. // space. |*path_len| is set to the length of the enclosing path if
  67. // such a path exists and |path_len| is non-nullptr. If no enclosing
  68. // path is found, |*path_len| is left unmodified.
  69. //
  70. // If an enclosing path is found, moves it up by one place in the paths list
  71. // so that more frequently used paths migrate to the front of the list.
  72. //
  73. // Note that proxy auth cache entries are associated with empty
  74. // paths. Therefore it is possible for HasEnclosingPath() to return
  75. // true and set |*path_len| to 0.
  76. bool HasEnclosingPath(const std::string& dir, size_t* path_len);
  77. // SchemeHostPort of the server.
  78. url::SchemeHostPort scheme_host_port_;
  79. std::string realm_;
  80. HttpAuth::Scheme scheme_ = HttpAuth::AUTH_SCHEME_MAX;
  81. // Identity.
  82. std::string auth_challenge_;
  83. AuthCredentials credentials_;
  84. int nonce_count_ = 0;
  85. // List of paths that define the realm's protection space.
  86. PathList paths_;
  87. // Times the entry was created and last used (by looking up, adding a path,
  88. // or updating the challenge.)
  89. base::TimeTicks creation_time_ticks_;
  90. base::TimeTicks last_use_time_ticks_;
  91. base::Time creation_time_;
  92. };
  93. // Prevent unbounded memory growth. These are safeguards for abuse; it is
  94. // not expected that the limits will be reached in ordinary usage.
  95. // This also defines the worst-case lookup times (which grow linearly
  96. // with number of elements in the cache).
  97. enum { kMaxNumPathsPerRealmEntry = 10 };
  98. enum { kMaxNumRealmEntries = 20 };
  99. // If |key_server_entries_by_network_isolation_key| is true, all
  100. // HttpAuth::AUTH_SERVER operations are keyed by NetworkIsolationKey.
  101. // Otherwise, NetworkIsolationKey arguments are ignored.
  102. explicit HttpAuthCache(bool key_server_entries_by_network_isolation_key);
  103. HttpAuthCache(const HttpAuthCache&) = delete;
  104. HttpAuthCache& operator=(const HttpAuthCache&) = delete;
  105. ~HttpAuthCache();
  106. // Sets whether server entries are keyed by NetworkIsolationKey.
  107. // If this results in changing the value of the setting, all current server
  108. // entries are deleted.
  109. void SetKeyServerEntriesByNetworkIsolationKey(
  110. bool key_server_entries_by_network_isolation_key);
  111. // Find the realm entry on server |origin| for realm |realm| and
  112. // scheme |scheme|. If a matching entry is found, move it up by one place
  113. // in the entries list, so that more frequently used entries migrate to the
  114. // front of the list.
  115. // |scheme_host_port| - the {scheme, host, port} of the server.
  116. // |target| - whether this is for server or proxy auth.
  117. // |realm| - case sensitive realm string.
  118. // |scheme| - the authentication scheme (i.e. basic, negotiate).
  119. // returns - the matched entry or nullptr.
  120. Entry* Lookup(const url::SchemeHostPort& scheme_host_port,
  121. HttpAuth::Target target,
  122. const std::string& realm,
  123. HttpAuth::Scheme scheme,
  124. const NetworkIsolationKey& network_isolation_key);
  125. // Find the entry on server |origin| whose protection space includes
  126. // |path|. This uses the assumption in RFC 2617 section 2 that deeper
  127. // paths lie in the same protection space. If a matching entry is found, move
  128. // it up by one place in the entries list, so that more frequently used
  129. // entries migrate to the front of the list.
  130. // |scheme_host_port| - the {scheme, host, port} of the server.
  131. // |path| - absolute path of the resource, or empty string in case of
  132. // proxy auth (which does not use the concept of paths).
  133. // returns - the matched entry or nullptr.
  134. Entry* LookupByPath(const url::SchemeHostPort& scheme_host_port,
  135. HttpAuth::Target target,
  136. const NetworkIsolationKey& network_isolation_key,
  137. const std::string& path);
  138. // Add an entry on server |scheme_host_port| for realm |handler->realm()| and
  139. // scheme |handler->scheme()|. If an entry for this (realm,scheme)
  140. // already exists, update it rather than replace it -- this preserves the
  141. // paths list.
  142. // |scheme_host_port| - the {scheme, host, port} of the server.
  143. // |realm| - the auth realm for the challenge.
  144. // |scheme| - the authentication scheme (i.e. basic, negotiate).
  145. // |credentials| - login information for the realm.
  146. // |path| - absolute path for a resource contained in the protection
  147. // space; this will be added to the list of known paths.
  148. // returns - the entry that was just added/updated.
  149. Entry* Add(const url::SchemeHostPort& scheme_host_port,
  150. HttpAuth::Target target,
  151. const std::string& realm,
  152. HttpAuth::Scheme scheme,
  153. const NetworkIsolationKey& network_isolation_key,
  154. const std::string& auth_challenge,
  155. const AuthCredentials& credentials,
  156. const std::string& path);
  157. // Remove entry on server |origin| for realm |realm| and scheme |scheme|
  158. // if one exists AND if the cached credentials matches |credentials|.
  159. // |scheme_host_port| - the {scheme, host, port} of the server.
  160. // |realm| - case sensitive realm string.
  161. // |scheme| - the authentication scheme (i.e. basic, negotiate).
  162. // |credentials| - the credentials to match.
  163. // returns - true if an entry was removed.
  164. bool Remove(const url::SchemeHostPort& scheme_host_port,
  165. HttpAuth::Target target,
  166. const std::string& realm,
  167. HttpAuth::Scheme scheme,
  168. const NetworkIsolationKey& network_isolation_key,
  169. const AuthCredentials& credentials);
  170. // Clears cache entries added between |begin_time| inclusively and |end_time|
  171. // exclusively. Clears all entries if |begin_time| and |end_time| are equal to
  172. // base::Time::Min() and base::Time::Max() respectively.
  173. void ClearEntriesAddedBetween(base::Time begin_time, base::Time end_time);
  174. // Clears all added entries.
  175. void ClearAllEntries();
  176. // Updates a stale digest entry on server |scheme_host_port| for realm |realm|
  177. // and scheme |scheme|. The cached auth challenge is replaced with
  178. // |auth_challenge| and the nonce count is reset.
  179. // |UpdateStaleChallenge()| returns true if a matching entry exists in the
  180. // cache, false otherwise.
  181. bool UpdateStaleChallenge(const url::SchemeHostPort& scheme_host_port,
  182. HttpAuth::Target target,
  183. const std::string& realm,
  184. HttpAuth::Scheme scheme,
  185. const NetworkIsolationKey& network_isolation_key,
  186. const std::string& auth_challenge);
  187. // Copies all entries from |other| cache with a target of
  188. // HttpAuth::AUTH_PROXY. |this| and |other| need not have the same
  189. // |key_server_entries_by_network_isolation_key_| value, since proxy
  190. // credentials are not keyed on NetworkIsolationKey.
  191. void CopyProxyEntriesFrom(const HttpAuthCache& other);
  192. size_t GetEntriesSizeForTesting();
  193. void set_tick_clock_for_testing(const base::TickClock* tick_clock) {
  194. tick_clock_ = tick_clock;
  195. }
  196. void set_clock_for_testing(const base::Clock* clock) { clock_ = clock; }
  197. bool key_server_entries_by_network_isolation_key() const {
  198. return key_server_entries_by_network_isolation_key_;
  199. }
  200. private:
  201. struct EntryMapKey {
  202. EntryMapKey(const url::SchemeHostPort& scheme_host_port,
  203. HttpAuth::Target target,
  204. const NetworkIsolationKey& network_isolation_key,
  205. bool key_server_entries_by_network_isolation_key);
  206. ~EntryMapKey();
  207. bool operator<(const EntryMapKey& other) const;
  208. url::SchemeHostPort scheme_host_port;
  209. HttpAuth::Target target;
  210. // Empty if |key_server_entries_by_network_isolation_key| is false, |target|
  211. // is HttpAuth::AUTH_PROXY, or an empty NetworkIsolationKey is passed in to
  212. // the EntryMap constructor.
  213. NetworkIsolationKey network_isolation_key;
  214. };
  215. using EntryMap = std::multimap<EntryMapKey, Entry>;
  216. raw_ptr<const base::TickClock> tick_clock_ =
  217. base::DefaultTickClock::GetInstance();
  218. raw_ptr<const base::Clock> clock_ = base::DefaultClock::GetInstance();
  219. EntryMap::iterator LookupEntryIt(
  220. const url::SchemeHostPort& scheme_host_port,
  221. HttpAuth::Target target,
  222. const std::string& realm,
  223. HttpAuth::Scheme scheme,
  224. const NetworkIsolationKey& network_isolation_key);
  225. void EvictLeastRecentlyUsedEntry();
  226. bool key_server_entries_by_network_isolation_key_;
  227. EntryMap entries_;
  228. };
  229. // An authentication realm entry.
  230. } // namespace net
  231. #endif // NET_HTTP_HTTP_AUTH_CACHE_H_