15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NET_HTTP_HTTP_AUTH_CACHE_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NET_HTTP_HTTP_AUTH_CACHE_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/time/time.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HttpAuthCache stores HTTP authentication identities and challenge info. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For each (origin, realm, scheme) triple the cache stores a 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HttpAuthCache::Entry, which holds: 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - the origin server {protocol scheme, host, port} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - the last identity used (username/password) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - the last auth handler used (contains realm and authentication scheme) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - the list of paths which used this realm 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Entries can be looked up by either (origin, realm, scheme) or (origin, path). 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NET_EXPORT_PRIVATE HttpAuthCache { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) class NET_EXPORT_PRIVATE Entry { 31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) public: 32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ~Entry(); 33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const GURL& origin() const { 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return origin_; 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // The case-sensitive realm string of the challenge. 39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::string realm() const { 40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return realm_; 41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // The authentication scheme of the challenge. 44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) HttpAuth::Scheme scheme() const { 45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return scheme_; 46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // The authentication challenge. 49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::string auth_challenge() const { 50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return auth_challenge_; 51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // The login credentials. 54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const AuthCredentials& credentials() const { 55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return credentials_; 56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int IncrementNonceCount() { 59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return ++nonce_count_; 60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void UpdateStaleChallenge(const std::string& auth_challenge); 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private: 65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) friend class HttpAuthCache; 66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(HttpAuthCacheTest, AddPath); 67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(HttpAuthCacheTest, AddToExistingEntry); 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) typedef std::list<std::string> PathList; 70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Entry(); 72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Adds a path defining the realm's protection space. If the path is 74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // already contained in the protection space, is a no-op. 75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void AddPath(const std::string& path); 76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Returns true if |dir| is contained within the realm's protection 78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // space. |*path_len| is set to the length of the enclosing path if 79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // such a path exists and |path_len| is non-NULL. If no enclosing 80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // path is found, |*path_len| is left unmodified. 81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Note that proxy auth cache entries are associated with empty 83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // paths. Therefore it is possible for HasEnclosingPath() to return 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // true and set |*path_len| to 0. 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool HasEnclosingPath(const std::string& dir, size_t* path_len); 86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // |origin_| contains the {protocol, host, port} of the server. 88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GURL origin_; 89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string realm_; 90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) HttpAuth::Scheme scheme_; 91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Identity. 93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string auth_challenge_; 94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) AuthCredentials credentials_; 95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int nonce_count_; 97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // List of paths that define the realm's protection space. 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) PathList paths_; 100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Times the entry was created and last used (by looking up, adding a path, 102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // or updating the challenge.) 103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::TimeTicks creation_time_; 104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::TimeTicks last_use_time_; 105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) }; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent unbounded memory growth. These are safeguards for abuse; it is 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not expected that the limits will be reached in ordinary usage. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This also defines the worst-case lookup times (which grow linearly 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with number of elements in the cache). 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum { kMaxNumPathsPerRealmEntry = 10 }; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum { kMaxNumRealmEntries = 10 }; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthCache(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~HttpAuthCache(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the realm entry on server |origin| for realm |realm| and 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scheme |scheme|. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |origin| - the {scheme, host, port} of the server. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |realm| - case sensitive realm string. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |scheme| - the authentication scheme (i.e. basic, negotiate). 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns - the matched entry or NULL. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entry* Lookup(const GURL& origin, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& realm, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::Scheme scheme); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the entry on server |origin| whose protection space includes 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |path|. This uses the assumption in RFC 2617 section 2 that deeper 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // paths lie in the same protection space. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |origin| - the {scheme, host, port} of the server. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |path| - absolute path of the resource, or empty string in case of 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // proxy auth (which does not use the concept of paths). 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns - the matched entry or NULL. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entry* LookupByPath(const GURL& origin, const std::string& path); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add an entry on server |origin| for realm |handler->realm()| and 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scheme |handler->scheme()|. If an entry for this (realm,scheme) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already exists, update it rather than replace it -- this preserves the 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // paths list. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |origin| - the {scheme, host, port} of the server. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |realm| - the auth realm for the challenge. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |scheme| - the authentication scheme (i.e. basic, negotiate). 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |credentials| - login information for the realm. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |path| - absolute path for a resource contained in the protection 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // space; this will be added to the list of known paths. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns - the entry that was just added/updated. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entry* Add(const GURL& origin, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& realm, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::Scheme scheme, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_challenge, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AuthCredentials& credentials, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& path); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove entry on server |origin| for realm |realm| and scheme |scheme| 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if one exists AND if the cached credentials matches |credentials|. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |origin| - the {scheme, host, port} of the server. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |realm| - case sensitive realm string. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |scheme| - the authentication scheme (i.e. basic, negotiate). 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |credentials| - the credentials to match. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns - true if an entry was removed. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Remove(const GURL& origin, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& realm, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::Scheme scheme, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AuthCredentials& credentials); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Clears the cache. 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void Clear(); 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates a stale digest entry on server |origin| for realm |realm| and 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scheme |scheme|. The cached auth challenge is replaced with 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |auth_challenge| and the nonce count is reset. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |UpdateStaleChallenge()| returns true if a matching entry exists in the 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cache, false otherwise. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool UpdateStaleChallenge(const GURL& origin, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& realm, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::Scheme scheme, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_challenge); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copies all entries from |other| cache. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateAllFrom(const HttpAuthCache& other); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::list<Entry> EntryList; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EntryList entries_; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An authentication realm entry. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // NET_HTTP_HTTP_AUTH_CACHE_H_ 191