1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
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_H_
6#define NET_HTTP_HTTP_AUTH_H_
7#pragma once
8
9#include <set>
10#include <string>
11
12#include "base/memory/scoped_ptr.h"
13#include "base/string16.h"
14#include "net/http/http_util.h"
15
16template <class T> class scoped_refptr;
17
18namespace net {
19
20class BoundNetLog;
21class HttpAuthHandler;
22class HttpAuthHandlerFactory;
23class HttpResponseHeaders;
24
25// Utility class for http authentication.
26class HttpAuth {
27 public:
28  // Http authentication can be done the the proxy server, origin server,
29  // or both. This enum tracks who the target is.
30  enum Target {
31    AUTH_NONE = -1,
32    // We depend on the valid targets (!= AUTH_NONE) being usable as indexes
33    // in an array, so start from 0.
34    AUTH_PROXY = 0,
35    AUTH_SERVER = 1,
36    AUTH_NUM_TARGETS = 2,
37  };
38
39  // What the HTTP WWW-Authenticate/Proxy-Authenticate headers indicate about
40  // the previous authorization attempt.
41  enum AuthorizationResult {
42    AUTHORIZATION_RESULT_ACCEPT,   // The authorization attempt was accepted,
43                                   // although there still may be additional
44                                   // rounds of challenges.
45
46    AUTHORIZATION_RESULT_REJECT,   // The authorization attempt was rejected.
47
48    AUTHORIZATION_RESULT_STALE,    // (Digest) The nonce used in the
49                                   // authorization attempt is stale, but
50                                   // otherwise the attempt was valid.
51
52    AUTHORIZATION_RESULT_INVALID,  // The authentication challenge headers are
53                                   // poorly formed (the authorization attempt
54                                   // itself may have been fine).
55
56    AUTHORIZATION_RESULT_DIFFERENT_REALM,  // The authorization
57                                           // attempt was rejected,
58                                           // but the realm associated
59                                           // with the new challenge
60                                           // is different from the
61                                           // previous attempt.
62  };
63
64  // Describes where the identity used for authentication came from.
65  enum IdentitySource {
66    // Came from nowhere -- the identity is not initialized.
67    IDENT_SRC_NONE,
68
69    // The identity came from the auth cache, by doing a path-based
70    // lookup (premptive authorization).
71    IDENT_SRC_PATH_LOOKUP,
72
73    // The identity was extracted from a URL of the form:
74    // http://<username>:<password>@host:port
75    IDENT_SRC_URL,
76
77    // The identity was retrieved from the auth cache, by doing a
78    // realm lookup.
79    IDENT_SRC_REALM_LOOKUP,
80
81    // The identity was provided by RestartWithAuth -- it likely
82    // came from a prompt (or maybe the password manager).
83    IDENT_SRC_EXTERNAL,
84
85    // The identity used the default credentials for the computer,
86    // on schemes that support single sign-on.
87    IDENT_SRC_DEFAULT_CREDENTIALS,
88  };
89
90  enum Scheme {
91    AUTH_SCHEME_BASIC = 0,
92    AUTH_SCHEME_DIGEST,
93    AUTH_SCHEME_NTLM,
94    AUTH_SCHEME_NEGOTIATE,
95    AUTH_SCHEME_MOCK,
96    AUTH_SCHEME_MAX,
97  };
98
99  // Helper structure used by HttpNetworkTransaction to track
100  // the current identity being used for authorization.
101  struct Identity {
102    Identity();
103
104    IdentitySource source;
105    bool invalid;
106    string16 username;
107    string16 password;
108  };
109
110  // Get the name of the header containing the auth challenge
111  // (either WWW-Authenticate or Proxy-Authenticate).
112  static std::string GetChallengeHeaderName(Target target);
113
114  // Get the name of the header where the credentials go
115  // (either Authorization or Proxy-Authorization).
116  static std::string GetAuthorizationHeaderName(Target target);
117
118  // Returns a string representation of a Target value that can be used in log
119  // messages.
120  static std::string GetAuthTargetString(Target target);
121
122  // Returns a string representation of an authentication Scheme.
123  static const char* SchemeToString(Scheme scheme);
124
125  // Iterate through the challenge headers, and pick the best one that
126  // we support. Obtains the implementation class for handling the challenge,
127  // and passes it back in |*handler|. If no supported challenge was found,
128  // |*handler| is set to NULL.
129  //
130  // |disabled_schemes| is the set of schemes that we should not use.
131  //
132  // |origin| is used by the NTLM and Negotiation authentication scheme to
133  // construct the service principal name.  It is ignored by other schemes.
134  static void ChooseBestChallenge(
135      HttpAuthHandlerFactory* http_auth_handler_factory,
136      const HttpResponseHeaders* headers,
137      Target target,
138      const GURL& origin,
139      const std::set<Scheme>& disabled_schemes,
140      const BoundNetLog& net_log,
141      scoped_ptr<HttpAuthHandler>* handler);
142
143  // Handle a 401/407 response from a server/proxy after a previous
144  // authentication attempt. For connection-based authentication schemes, the
145  // new response may be another round in a multi-round authentication sequence.
146  // For request-based schemes, a 401/407 response is typically treated like a
147  // rejection of the previous challenge, except in the Digest case when a
148  // "stale" attribute is present.
149  //
150  // |handler| must be non-NULL, and is the HttpAuthHandler from the previous
151  // authentication round.
152  //
153  // |headers| must be non-NULL and contain the new HTTP response.
154  //
155  // |target| specifies whether the authentication challenge response came
156  // from a server or a proxy.
157  //
158  // |disabled_schemes| are the authentication schemes to ignore.
159  //
160  // |challenge_used| is the text of the authentication challenge used in
161  // support of the returned AuthorizationResult. If no headers were used for
162  // the result (for example, all headers have unknown authentication schemes),
163  // the value is cleared.
164  static AuthorizationResult HandleChallengeResponse(
165      HttpAuthHandler* handler,
166      const HttpResponseHeaders* headers,
167      Target target,
168      const std::set<Scheme>& disabled_schemes,
169      std::string* challenge_used);
170
171  // Breaks up a challenge string into the the auth scheme and parameter list,
172  // according to RFC 2617 Sec 1.2:
173  //    challenge = auth-scheme 1*SP 1#auth-param
174  //
175  // Depending on the challenge scheme, it may be appropriate to interpret the
176  // parameters as either a base-64 encoded string or a comma-delimited list
177  // of name-value pairs. param_pairs() and base64_param() methods are provided
178  // to support either usage.
179  class ChallengeTokenizer {
180   public:
181    ChallengeTokenizer(std::string::const_iterator begin,
182                       std::string::const_iterator end)
183        : begin_(begin),
184          end_(end),
185          scheme_begin_(begin),
186          scheme_end_(begin),
187          params_begin_(end),
188          params_end_(end) {
189      Init(begin, end);
190    }
191
192    // Get the original text.
193    std::string challenge_text() const {
194      return std::string(begin_, end_);
195    }
196
197    // Get the auth scheme of the challenge.
198    std::string::const_iterator scheme_begin() const { return scheme_begin_; }
199    std::string::const_iterator scheme_end() const { return scheme_end_; }
200    std::string scheme() const {
201      return std::string(scheme_begin_, scheme_end_);
202    }
203
204    HttpUtil::NameValuePairsIterator param_pairs() const;
205    std::string base64_param() const;
206
207   private:
208    void Init(std::string::const_iterator begin,
209              std::string::const_iterator end);
210
211    std::string::const_iterator begin_;
212    std::string::const_iterator end_;
213
214    std::string::const_iterator scheme_begin_;
215    std::string::const_iterator scheme_end_;
216
217    std::string::const_iterator params_begin_;
218    std::string::const_iterator params_end_;
219  };
220};
221
222}  // namespace net
223
224#endif  // NET_HTTP_HTTP_AUTH_H_
225