Home | History | Annotate | Download | only in http
      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 
     16 template <class T> class scoped_refptr;
     17 
     18 namespace net {
     19 
     20 class BoundNetLog;
     21 class HttpAuthHandler;
     22 class HttpAuthHandlerFactory;
     23 class HttpResponseHeaders;
     24 
     25 // Utility class for http authentication.
     26 class 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