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