1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_HTTP_HTTP_AUTH_CONTROLLER_H_ 6 #define NET_HTTP_HTTP_AUTH_CONTROLLER_H_ 7 8 #include <memory> 9 #include <optional> 10 #include <set> 11 #include <string> 12 13 #include "base/memory/raw_ptr.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/threading/thread_checker.h" 16 #include "net/base/completion_once_callback.h" 17 #include "net/base/net_export.h" 18 #include "net/base/network_anonymization_key.h" 19 #include "net/http/http_auth.h" 20 #include "net/http/http_auth_preferences.h" 21 #include "net/log/net_log_with_source.h" 22 #include "url/gurl.h" 23 #include "url/scheme_host_port.h" 24 25 namespace net { 26 27 class AuthChallengeInfo; 28 class AuthCredentials; 29 class HttpAuthHandler; 30 class HttpAuthHandlerFactory; 31 class HttpAuthCache; 32 class HttpRequestHeaders; 33 class HostResolver; 34 class NetLogWithSource; 35 struct HttpRequestInfo; 36 class SSLInfo; 37 38 // HttpAuthController is the main entry point for external callers into the HTTP 39 // authentication stack. A single instance of an HttpAuthController can be used 40 // to handle authentication to a single "target", where "target" is a HTTP 41 // server or a proxy. During its lifetime, the HttpAuthController can make use 42 // of multiple authentication handlers (implemented as HttpAuthHandler 43 // subclasses), and respond to multiple challenges. 44 // 45 // Individual HTTP authentication schemes can have additional requirements other 46 // than what's prescribed in RFC 7235. See HandleAuthChallenge() for details. 47 class NET_EXPORT_PRIVATE HttpAuthController 48 : public base::RefCounted<HttpAuthController> { 49 public: 50 // Construct a new HttpAuthController. 51 // 52 // * |target| is either PROXY or SERVER and determines the authentication 53 // headers to use ("WWW-Authenticate"/"Authorization" vs. 54 // "Proxy-Authenticate"/"Proxy-Authorization") and how ambient 55 // credentials are used. 56 // 57 // * |auth_url| specifies the target URL. The origin of the URL identifies the 58 // target host. The path (hierarchical part defined in RFC 3986 section 59 // 3.3) of the URL is used by HTTP basic authentication to determine 60 // cached credentials can be used to preemptively send an authorization 61 // header. See RFC 7617 section 2.2 (Reusing Credentials) for details. 62 // If |target| is PROXY, then |auth_url| should have no hierarchical 63 // part since that is meaningless. 64 // 65 // * |network_anonymization_key| specifies the NetworkAnonymizationKey 66 // associated with the resource load. Depending on settings, credentials 67 // may be scoped to a single NetworkAnonymizationKey. 68 // 69 // * |http_auth_cache| specifies the credentials cache to use. During 70 // authentication if explicit (user-provided) credentials are used and 71 // they can be cached to respond to authentication challenges in the 72 // future, they are stored in the cache. In addition, the HTTP Digest 73 // authentication is stateful across requests. So the |http_auth_cache| 74 // is also used to maintain state for this authentication scheme. 75 // 76 // * |http_auth_handler_factory| is used to construct instances of 77 // HttpAuthHandler subclasses to handle scheme-specific authentication 78 // logic. The |http_auth_handler_factory| is also responsible for 79 // determining whether the authentication stack should use a specific 80 // authentication scheme or not. 81 // 82 // * |host_resolver| is used for determining the canonical hostname given a 83 // possibly non-canonical host name. Name canonicalization is used for 84 // NTLM and Negotiate HTTP authentication schemes. 85 // 86 // * |allow_default_credentials| is used for determining if the current 87 // context allows ambient authentication using default credentials. 88 HttpAuthController(HttpAuth::Target target, 89 const GURL& auth_url, 90 const NetworkAnonymizationKey& network_anonymization_key, 91 HttpAuthCache* http_auth_cache, 92 HttpAuthHandlerFactory* http_auth_handler_factory, 93 HostResolver* host_resolver); 94 95 // Generate an authentication token for |target| if necessary. The return 96 // value is a net error code. |OK| will be returned both in the case that 97 // a token is correctly generated synchronously, as well as when no tokens 98 // were necessary. 99 int MaybeGenerateAuthToken(const HttpRequestInfo* request, 100 CompletionOnceCallback callback, 101 const NetLogWithSource& net_log); 102 103 // Adds either the proxy auth header, or the origin server auth header, 104 // as specified by |target_|. 105 void AddAuthorizationHeader(HttpRequestHeaders* authorization_headers); 106 107 // Checks for and handles HTTP status code 401 or 407. 108 // |HandleAuthChallenge()| returns OK on success, or a network error code 109 // otherwise. It may also populate |auth_info_|. 110 int HandleAuthChallenge(scoped_refptr<HttpResponseHeaders> headers, 111 const SSLInfo& ssl_info, 112 bool do_not_send_server_auth, 113 bool establishing_tunnel, 114 const NetLogWithSource& net_log); 115 116 // Store the supplied credentials and prepare to restart the auth. 117 void ResetAuth(const AuthCredentials& credentials); 118 119 bool HaveAuthHandler() const; 120 121 bool HaveAuth() const; 122 123 // Return whether the authentication scheme is incompatible with HTTP/2 124 // and thus the server would presumably reject a request on HTTP/2 anyway. 125 bool NeedsHTTP11() const; 126 127 // Swaps the authentication challenge info into |other|. 128 void TakeAuthInfo(std::optional<AuthChallengeInfo>* other); 129 130 bool IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const; 131 void DisableAuthScheme(HttpAuth::Scheme scheme); 132 void DisableEmbeddedIdentity(); 133 134 // Called when the connection has been closed, so the current handler (which 135 // contains state bound to the connection) should be dropped. If retrying on a 136 // new connection, the next call to MaybeGenerateAuthToken will retry the 137 // current auth scheme. 138 void OnConnectionClosed(); 139 140 private: 141 // Actions for InvalidateCurrentHandler() 142 enum InvalidateHandlerAction { 143 INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS, 144 INVALIDATE_HANDLER_AND_DISABLE_SCHEME, 145 INVALIDATE_HANDLER 146 }; 147 148 // So that we can mock this object. 149 friend class base::RefCounted<HttpAuthController>; 150 151 ~HttpAuthController(); 152 153 // If this controller's NetLog hasn't been created yet, creates it and 154 // associates it with |caller_net_log|. Does nothing after the first 155 // invocation. 156 void BindToCallingNetLog(const NetLogWithSource& caller_net_log); 157 158 // Searches the auth cache for an entry that encompasses the request's path. 159 // If such an entry is found, updates |identity_| and |handler_| with the 160 // cache entry's data and returns true. 161 bool SelectPreemptiveAuth(const NetLogWithSource& caller_net_log); 162 163 // Invalidates the current handler. If |action| is 164 // INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS, then also invalidate 165 // the cached credentials used by the handler. 166 void InvalidateCurrentHandler(InvalidateHandlerAction action); 167 168 // Invalidates any auth cache entries after authentication has failed. 169 // The identity that was rejected is |identity_|. 170 void InvalidateRejectedAuthFromCache(); 171 172 // Allows reusing last used identity source. If the authentication handshake 173 // breaks down halfway, then the controller needs to restart it from the 174 // beginning and resue the same identity. 175 void PrepareIdentityForReuse(); 176 177 // Sets |identity_| to the next identity that the transaction should try. It 178 // chooses candidates by searching the auth cache and the URL for a 179 // username:password. Returns true if an identity was found. 180 bool SelectNextAuthIdentityToTry(); 181 182 // Populates auth_info_ with the challenge information, so that 183 // URLRequestHttpJob can prompt for credentials. 184 void PopulateAuthChallenge(); 185 186 // Handle the result of calling GenerateAuthToken on an HttpAuthHandler. The 187 // return value of this function should be used as the return value of the 188 // GenerateAuthToken operation. 189 int HandleGenerateTokenResult(int result); 190 191 void OnGenerateAuthTokenDone(int result); 192 193 // Indicates if this handler is for Proxy auth or Server auth. 194 HttpAuth::Target target_; 195 196 // Holds the {scheme, host, port, path} for the authentication target. 197 const GURL auth_url_; 198 199 // Holds the {scheme, host, port} for the authentication target. 200 const url::SchemeHostPort auth_scheme_host_port_; 201 202 // The absolute path of the resource needing authentication. 203 // For proxy authentication, the path is empty. 204 const std::string auth_path_; 205 206 // NetworkAnonymizationKey associated with the request. 207 const NetworkAnonymizationKey network_anonymization_key_; 208 209 // |handler_| encapsulates the logic for the particular auth-scheme. 210 // This includes the challenge's parameters. If nullptr, then there is no 211 // associated auth handler. 212 std::unique_ptr<HttpAuthHandler> handler_; 213 214 // |identity_| holds the credentials that should be used by the handler_ to 215 // generate challenge responses. This identity can come from a number of 216 // places (url, cache, prompt). 217 HttpAuth::Identity identity_; 218 219 // |auth_token_| contains the opaque string to pass to the proxy or 220 // server to authenticate the client. 221 std::string auth_token_; 222 223 // Contains information about the auth challenge. 224 std::optional<AuthChallengeInfo> auth_info_; 225 226 // True if we've used the username:password embedded in the URL. This 227 // makes sure we use the embedded identity only once for the transaction, 228 // preventing an infinite auth restart loop. 229 bool embedded_identity_used_ = false; 230 231 // True if default credentials have already been tried for this transaction 232 // in response to an HTTP authentication challenge. 233 bool default_credentials_used_ = false; 234 235 // These two are owned by the HttpNetworkSession/IOThread, which own the 236 // objects which reference |this|. Therefore, these raw pointers are valid 237 // for the lifetime of this object. 238 const raw_ptr<HttpAuthCache> http_auth_cache_; 239 const raw_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_; 240 const raw_ptr<HostResolver> host_resolver_; 241 242 std::set<HttpAuth::Scheme> disabled_schemes_; 243 244 CompletionOnceCallback callback_; 245 246 // NetLog to be used for logging in this controller. 247 NetLogWithSource net_log_; 248 249 THREAD_CHECKER(thread_checker_); 250 }; 251 252 } // namespace net 253 254 #endif // NET_HTTP_HTTP_AUTH_CONTROLLER_H_ 255