1 // Copyright 2011 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_HANDLER_H_ 6 #define NET_HTTP_HTTP_AUTH_HANDLER_H_ 7 8 #include <string> 9 10 #include "net/base/completion_once_callback.h" 11 #include "net/base/net_export.h" 12 #include "net/http/http_auth.h" 13 #include "net/log/net_log_with_source.h" 14 #include "url/scheme_host_port.h" 15 16 namespace net { 17 18 class NetworkAnonymizationKey; 19 class HttpAuthChallengeTokenizer; 20 struct HttpRequestInfo; 21 class SSLInfo; 22 23 // HttpAuthHandler is the interface for the authentication schemes 24 // (basic, digest, NTLM, Negotiate). 25 // HttpAuthHandler objects are typically created by an HttpAuthHandlerFactory. 26 // 27 // HttpAuthHandlers and generally created and managed by an HttpAuthController, 28 // which is the interaction point between the rest of net and the HTTP auth 29 // code. 30 // 31 // For connection-based authentication, an HttpAuthHandler handles all rounds 32 // related to using a single identity. If the identity is rejected, a new 33 // HttpAuthHandler must be created. 34 class NET_EXPORT_PRIVATE HttpAuthHandler { 35 public: 36 HttpAuthHandler(); 37 38 HttpAuthHandler(const HttpAuthHandler&) = delete; 39 HttpAuthHandler& operator=(const HttpAuthHandler&) = delete; 40 41 virtual ~HttpAuthHandler(); 42 43 // Initializes the handler using a challenge issued by a server. 44 // 45 // |challenge| must be non-nullptr and have already tokenized the 46 // authentication scheme, but none of the tokens occurring after the 47 // authentication scheme. 48 // |target| and |scheme_host_port| are both stored for later use, and are not 49 // part of the initial challenge. 50 // |ssl_info| must be valid if the underlying connection used a certificate. 51 // |network_anonymization_key| the NetworkAnonymizationKey associated with the 52 // challenge. Used for host resolutions, if any are needed. 53 // |net_log| to be used for logging. 54 bool InitFromChallenge( 55 HttpAuthChallengeTokenizer* challenge, 56 HttpAuth::Target target, 57 const SSLInfo& ssl_info, 58 const NetworkAnonymizationKey& network_anonymization_key, 59 const url::SchemeHostPort& scheme_host_port, 60 const NetLogWithSource& net_log); 61 62 // Determines how the previous authorization attempt was received. 63 // 64 // This is called when the server/proxy responds with a 401/407 after an 65 // earlier authorization attempt. Although this normally means that the 66 // previous attempt was rejected, in multi-round schemes such as 67 // NTLM+Negotiate it may indicate that another round of challenge+response 68 // is required. For Digest authentication it may also mean that the previous 69 // attempt used a stale nonce (and nonce-count) and that a new attempt should 70 // be made with a different nonce provided in the challenge. 71 // 72 // |challenge| must be non-nullptr and have already tokenized the 73 // authentication scheme, but none of the tokens occurring after the 74 // authentication scheme. 75 HttpAuth::AuthorizationResult HandleAnotherChallenge( 76 HttpAuthChallengeTokenizer* challenge); 77 78 // Generates an authentication token, potentially asynchronously. 79 // 80 // When |credentials| is nullptr, the default credentials for the currently 81 // logged in user are used. |AllowsDefaultCredentials()| MUST be true in this 82 // case. 83 // 84 // |request|, |callback|, and |auth_token| must be non-nullptr. 85 // 86 // The return value is a net error code. 87 // 88 // If |OK| is returned, |*auth_token| is filled in with an authentication 89 // token which can be inserted in the HTTP request. 90 // 91 // If |ERR_IO_PENDING| is returned, |*auth_token| will be filled in 92 // asynchronously and |callback| will be invoked. The lifetime of 93 // |request|, |callback|, and |auth_token| must last until |callback| is 94 // invoked, but |credentials| is only used during the initial call. 95 // 96 // All other return codes indicate that there was a problem generating a 97 // token, and the value of |*auth_token| is unspecified. 98 int GenerateAuthToken(const AuthCredentials* credentials, 99 const HttpRequestInfo* request, 100 CompletionOnceCallback callback, 101 std::string* auth_token); 102 103 // The authentication scheme as an enumerated value. auth_scheme()104 HttpAuth::Scheme auth_scheme() const { 105 return auth_scheme_; 106 } 107 108 // The realm, encoded as UTF-8. This may be empty. realm()109 const std::string& realm() const { 110 return realm_; 111 } 112 113 // The challenge which was issued when creating the handler. challenge()114 const std::string& challenge() const { return auth_challenge_; } 115 116 // Numeric rank based on the challenge's security level. Higher 117 // numbers are better. Used by HttpAuth::ChooseBestChallenge(). score()118 int score() const { 119 return score_; 120 } 121 target()122 HttpAuth::Target target() const { 123 return target_; 124 } 125 126 // Returns the proxy or server which issued the authentication challenge 127 // that this HttpAuthHandler is handling. scheme_host_port()128 const url::SchemeHostPort& scheme_host_port() const { 129 return scheme_host_port_; 130 } 131 132 // Returns true if the authentication scheme does not send the username and 133 // password in the clear. encrypts_identity()134 bool encrypts_identity() const { 135 return (properties_ & ENCRYPTS_IDENTITY) != 0; 136 } 137 138 // Returns true if the authentication scheme is connection-based, for 139 // example, NTLM. A connection-based authentication scheme does not support 140 // preemptive authentication, and must use the same handler object 141 // throughout the life of an HTTP transaction. is_connection_based()142 bool is_connection_based() const { 143 return (properties_ & IS_CONNECTION_BASED) != 0; 144 } 145 146 // This HttpAuthHandler's bound NetLog. net_log()147 const NetLogWithSource& net_log() const { return net_log_; } 148 149 // If NeedsIdentity() returns true, then a subsequent call to 150 // GenerateAuthToken() must indicate which identity to use. This can be done 151 // either by passing in a non-empty set of credentials, or an empty set to 152 // force the handler to use the default credentials. The latter is only an 153 // option if AllowsDefaultCredentials() returns true. 154 // 155 // If NeedsIdentity() returns false, then the handler is already bound to an 156 // identity and GenerateAuthToken() will ignore any credentials that are 157 // passed in. 158 // 159 // TODO(wtc): Find a better way to handle a multi-round challenge-response 160 // sequence used by a connection-based authentication scheme. 161 virtual bool NeedsIdentity(); 162 163 // Returns whether the default credentials may be used for the |origin| passed 164 // into |InitFromChallenge|. If true, the user does not need to be prompted 165 // for username and password to establish credentials. 166 // NOTE: SSO is a potential security risk. 167 // TODO(cbentzel): Add a pointer to Firefox documentation about risk. 168 virtual bool AllowsDefaultCredentials(); 169 170 // Returns whether explicit credentials can be used with this handler. If 171 // true the user may be prompted for credentials if an implicit identity 172 // cannot be determined. 173 virtual bool AllowsExplicitCredentials(); 174 175 protected: 176 enum Property { 177 ENCRYPTS_IDENTITY = 1 << 0, 178 IS_CONNECTION_BASED = 1 << 1, 179 }; 180 181 // Initializes the handler using a challenge issued by a server. 182 // |challenge| must be non-nullptr and have already tokenized the 183 // authentication scheme, but none of the tokens occurring after the 184 // authentication scheme. 185 // 186 // If the request was sent over an encrypted connection, |ssl_info| is valid 187 // and describes the connection. 188 // 189 // NetworkAnonymizationKey is the NetworkAnonymizationKey associated with the 190 // request. 191 // 192 // Implementations are expected to initialize the following members: 193 // scheme_, realm_, score_, properties_ 194 virtual bool Init( 195 HttpAuthChallengeTokenizer* challenge, 196 const SSLInfo& ssl_info, 197 const NetworkAnonymizationKey& network_anonymization_key) = 0; 198 199 // |GenerateAuthTokenImpl()} is the auth-scheme specific implementation 200 // of generating the next auth token. Callers should use |GenerateAuthToken()| 201 // which will in turn call |GenerateAuthTokenImpl()| 202 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials, 203 const HttpRequestInfo* request, 204 CompletionOnceCallback callback, 205 std::string* auth_token) = 0; 206 207 // See HandleAnotherChallenge() above. HandleAuthChallengeImpl is the 208 // scheme-specific implementation. Callers should use HandleAnotherChallenge() 209 // instead. 210 virtual HttpAuth::AuthorizationResult HandleAnotherChallengeImpl( 211 HttpAuthChallengeTokenizer* challenge) = 0; 212 213 // The auth-scheme as an enumerated value. 214 HttpAuth::Scheme auth_scheme_ = HttpAuth::AUTH_SCHEME_MAX; 215 216 // The realm, encoded as UTF-8. Used by "basic" and "digest". 217 std::string realm_; 218 219 // The auth challenge. 220 std::string auth_challenge_; 221 222 // The {scheme, host, port} for the authentication target. Used by "ntlm" 223 // and "negotiate" to construct the service principal name. 224 url::SchemeHostPort scheme_host_port_; 225 226 // The score for this challenge. Higher numbers are better. 227 int score_ = -1; 228 229 // Whether this authentication request is for a proxy server, or an 230 // origin server. 231 HttpAuth::Target target_ = HttpAuth::AUTH_NONE; 232 233 // A bitmask of the properties of the authentication scheme. 234 int properties_ = -1; 235 236 private: 237 void OnGenerateAuthTokenComplete(int rv); 238 void FinishGenerateAuthToken(int rv); 239 240 // NetLog that should be used for logging events generated by this 241 // HttpAuthHandler. 242 NetLogWithSource net_log_; 243 244 CompletionOnceCallback callback_; 245 }; 246 247 } // namespace net 248 249 #endif // NET_HTTP_HTTP_AUTH_HANDLER_H_ 250