1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NET_HTTP_HTTP_AUTH_CACHE_H_
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NET_HTTP_HTTP_AUTH_CACHE_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <list>
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/gtest_prod_util.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string16.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "googleurl/src/gurl.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/http/http_auth.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// HttpAuthCache stores HTTP authentication identities and challenge info.
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For each (origin, realm, scheme) triple the cache stores a
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HttpAuthCache::Entry, which holds:
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   - the origin server {protocol scheme, host, port}
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   - the last identity used (username/password)
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   - the last auth handler used (contains realm and authentication scheme)
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   - the list of paths which used this realm
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Entries can be looked up by either (origin, realm, scheme) or (origin, path).
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass HttpAuthCache {
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class Entry;
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Prevent unbounded memory growth. These are safeguards for abuse; it is
333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // not expected that the limits will be reached in ordinary usage.
343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // This also defines the worst-case lookup times (which grow linearly
353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // with number of elements in the cache).
363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  enum { kMaxNumPathsPerRealmEntry = 10 };
373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  enum { kMaxNumRealmEntries = 10 };
383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  HttpAuthCache();
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ~HttpAuthCache();
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Find the realm entry on server |origin| for realm |realm| and
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // scheme |scheme|.
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |origin| - the {scheme, host, port} of the server.
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |realm|  - case sensitive realm string.
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //   |scheme| - the authentication scheme (i.e. basic, negotiate).
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   returns  - the matched entry or NULL.
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Entry* Lookup(const GURL& origin,
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                const std::string& realm,
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                HttpAuth::Scheme scheme);
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Find the entry on server |origin| whose protection space includes
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |path|. This uses the assumption in RFC 2617 section 2 that deeper
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // paths lie in the same protection space.
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |origin| - the {scheme, host, port} of the server.
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |path|   - absolute path of the resource, or empty string in case of
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //              proxy auth (which does not use the concept of paths).
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   returns  - the matched entry or NULL.
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Entry* LookupByPath(const GURL& origin, const std::string& path);
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add an entry on server |origin| for realm |handler->realm()| and
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // scheme |handler->scheme()|.  If an entry for this (realm,scheme)
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // already exists, update it rather than replace it -- this  preserves the
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // paths list.
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |origin|   - the {scheme, host, port} of the server.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   |realm|    - the auth realm for the challenge.
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //   |scheme|   - the authentication scheme (i.e. basic, negotiate).
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |username| - login information for the realm.
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |password| - login information for the realm.
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |path|     - absolute path for a resource contained in the protection
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //                space; this will be added to the list of known paths.
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   returns    - the entry that was just added/updated.
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Entry* Add(const GURL& origin,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const std::string& realm,
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen             HttpAuth::Scheme scheme,
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const std::string& auth_challenge,
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             const string16& username,
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             const string16& password,
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             const std::string& path);
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Remove entry on server |origin| for realm |realm| and scheme |scheme|
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // if one exists AND if the cached identity matches (|username|, |password|).
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |origin|   - the {scheme, host, port} of the server.
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |realm|    - case sensitive realm string.
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //   |scheme|   - the authentication scheme (i.e. basic, negotiate).
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |username| - condition to match.
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   |password| - condition to match.
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   returns    - true if an entry was removed.
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool Remove(const GURL& origin,
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              const std::string& realm,
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              HttpAuth::Scheme scheme,
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              const string16& username,
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              const string16& password);
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Updates a stale digest entry on server |origin| for realm |realm| and
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // scheme |scheme|. The cached auth challenge is replaced with
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // |auth_challenge| and the nonce count is reset.
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // |UpdateStaleChallenge()| returns true if a matching entry exists in the
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // cache, false otherwise.
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool UpdateStaleChallenge(const GURL& origin,
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            const std::string& realm,
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                            HttpAuth::Scheme scheme,
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            const std::string& auth_challenge);
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef std::list<Entry> EntryList;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntryList entries_;
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// An authentication realm entry.
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass HttpAuthCache::Entry {
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
1133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  ~Entry();
1143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const GURL& origin() const {
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return origin_;
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The case-sensitive realm string of the challenge.
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::string realm() const {
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return realm_;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The authentication scheme of the challenge.
12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  HttpAuth::Scheme scheme() const {
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return scheme_;
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The authentication challenge.
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string auth_challenge() const {
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return auth_challenge_;
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The login username.
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const string16 username() const {
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return username_;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The login password.
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const string16 password() const {
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return password_;
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int IncrementNonceCount() {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ++nonce_count_;
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void UpdateStaleChallenge(const std::string& auth_challenge);
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  friend class HttpAuthCache;
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FRIEND_TEST_ALL_PREFIXES(HttpAuthCacheTest, AddPath);
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FRIEND_TEST_ALL_PREFIXES(HttpAuthCacheTest, AddToExistingEntry);
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  typedef std::list<std::string> PathList;
1563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Entry();
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Adds a path defining the realm's protection space. If the path is
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // already contained in the protection space, is a no-op.
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void AddPath(const std::string& path);
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Returns true if |dir| is contained within the realm's protection
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // space.  |*path_len| is set to the length of the enclosing path if
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // such a path exists and |path_len| is non-NULL.  If no enclosing
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // path is found, |*path_len| is left unmodified.
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Note that proxy auth cache entries are associated with empty
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // paths.  Therefore it is possible for HasEnclosingPath() to return
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // true and set |*path_len| to 0.
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool HasEnclosingPath(const std::string& dir, size_t* path_len);
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // |origin_| contains the {protocol, host, port} of the server.
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GURL origin_;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string realm_;
17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  HttpAuth::Scheme scheme_;
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Identity.
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string auth_challenge_;
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  string16 username_;
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  string16 password_;
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int nonce_count_;
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // List of paths that define the realm's protection space.
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PathList paths_;
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}  // namespace net
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // NET_HTTP_HTTP_AUTH_CACHE_H_
192