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