xref: /aosp_15_r20/external/cronet/net/http/http_auth_handler.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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