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_HANDLER_DIGEST_H_
      6 #define NET_HTTP_HTTP_AUTH_HANDLER_DIGEST_H_
      7 
      8 #include <string>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/gtest_prod_util.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "net/base/net_export.h"
     14 #include "net/http/http_auth_handler.h"
     15 #include "net/http/http_auth_handler_factory.h"
     16 
     17 namespace net {
     18 
     19 // Code for handling http digest authentication.
     20 class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler {
     21  public:
     22   // A NonceGenerator is a simple interface for generating client nonces.
     23   // Unit tests can override the default client nonce behavior with fixed
     24   // nonce generation to get reproducible results.
     25   class NET_EXPORT_PRIVATE NonceGenerator {
     26    public:
     27     NonceGenerator();
     28     virtual ~NonceGenerator();
     29 
     30     // Generates a client nonce.
     31     virtual std::string GenerateNonce() const = 0;
     32    private:
     33     DISALLOW_COPY_AND_ASSIGN(NonceGenerator);
     34   };
     35 
     36   // DynamicNonceGenerator does a random shuffle of 16
     37   // characters to generate a client nonce.
     38   class DynamicNonceGenerator : public NonceGenerator {
     39    public:
     40     DynamicNonceGenerator();
     41     virtual std::string GenerateNonce() const OVERRIDE;
     42    private:
     43     DISALLOW_COPY_AND_ASSIGN(DynamicNonceGenerator);
     44   };
     45 
     46   // FixedNonceGenerator always uses the same string specified at
     47   // construction time as the client nonce.
     48   class NET_EXPORT_PRIVATE FixedNonceGenerator : public NonceGenerator {
     49    public:
     50     explicit FixedNonceGenerator(const std::string& nonce);
     51 
     52     virtual std::string GenerateNonce() const OVERRIDE;
     53 
     54    private:
     55     const std::string nonce_;
     56     DISALLOW_COPY_AND_ASSIGN(FixedNonceGenerator);
     57   };
     58 
     59   class NET_EXPORT_PRIVATE Factory : public HttpAuthHandlerFactory {
     60    public:
     61     Factory();
     62     virtual ~Factory();
     63 
     64     // This factory owns the passed in |nonce_generator|.
     65     void set_nonce_generator(const NonceGenerator* nonce_generator);
     66 
     67     virtual int CreateAuthHandler(
     68         HttpAuth::ChallengeTokenizer* challenge,
     69         HttpAuth::Target target,
     70         const GURL& origin,
     71         CreateReason reason,
     72         int digest_nonce_count,
     73         const BoundNetLog& net_log,
     74         scoped_ptr<HttpAuthHandler>* handler) OVERRIDE;
     75 
     76    private:
     77     scoped_ptr<const NonceGenerator> nonce_generator_;
     78   };
     79 
     80   virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
     81       HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
     82 
     83  protected:
     84   virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) OVERRIDE;
     85 
     86   virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
     87                                     const HttpRequestInfo* request,
     88                                     const CompletionCallback& callback,
     89                                     std::string* auth_token) OVERRIDE;
     90 
     91  private:
     92   FRIEND_TEST_ALL_PREFIXES(HttpAuthHandlerDigestTest, ParseChallenge);
     93   FRIEND_TEST_ALL_PREFIXES(HttpAuthHandlerDigestTest, AssembleCredentials);
     94   FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, DigestPreAuthNonceCount);
     95 
     96   // Possible values for the "algorithm" property.
     97   enum DigestAlgorithm {
     98     // No algorithm was specified. According to RFC 2617 this means
     99     // we should default to ALGORITHM_MD5.
    100     ALGORITHM_UNSPECIFIED,
    101 
    102     // Hashes are run for every request.
    103     ALGORITHM_MD5,
    104 
    105     // Hash is run only once during the first WWW-Authenticate handshake.
    106     // (SESS means session).
    107     ALGORITHM_MD5_SESS,
    108   };
    109 
    110   // Possible values for QualityOfProtection.
    111   // auth-int is not supported, see http://crbug.com/62890 for justification.
    112   enum QualityOfProtection {
    113     QOP_UNSPECIFIED,
    114     QOP_AUTH,
    115   };
    116 
    117   // |nonce_count| indicates how many times the server-specified nonce has
    118   // been used so far.
    119   // |nonce_generator| is used to create a client nonce, and is not owned by
    120   // the handler. The lifetime of the |nonce_generator| must exceed that of this
    121   // handler.
    122   HttpAuthHandlerDigest(int nonce_count, const NonceGenerator* nonce_generator);
    123   virtual ~HttpAuthHandlerDigest();
    124 
    125   // Parse the challenge, saving the results into this instance.
    126   // Returns true on success.
    127   bool ParseChallenge(HttpAuth::ChallengeTokenizer* challenge);
    128 
    129   // Parse an individual property. Returns true on success.
    130   bool ParseChallengeProperty(const std::string& name,
    131                               const std::string& value);
    132 
    133   // Generates a random string, to be used for client-nonce.
    134   static std::string GenerateNonce();
    135 
    136   // Convert enum value back to string.
    137   static std::string QopToString(QualityOfProtection qop);
    138   static std::string AlgorithmToString(DigestAlgorithm algorithm);
    139 
    140   // Extract the method and path of the request, as needed by
    141   // the 'A2' production. (path may be a hostname for proxy).
    142   void GetRequestMethodAndPath(const HttpRequestInfo* request,
    143                                std::string* method,
    144                                std::string* path) const;
    145 
    146   // Build up  the 'response' production.
    147   std::string AssembleResponseDigest(const std::string& method,
    148                                      const std::string& path,
    149                                      const AuthCredentials& credentials,
    150                                      const std::string& cnonce,
    151                                      const std::string& nc) const;
    152 
    153   // Build up  the value for (Authorization/Proxy-Authorization).
    154   std::string AssembleCredentials(const std::string& method,
    155                                   const std::string& path,
    156                                   const AuthCredentials& credentials,
    157                                   const std::string& cnonce,
    158                                   int nonce_count) const;
    159 
    160   // Information parsed from the challenge.
    161   std::string nonce_;
    162   std::string domain_;
    163   std::string opaque_;
    164   bool stale_;
    165   DigestAlgorithm algorithm_;
    166   QualityOfProtection qop_;
    167 
    168   // The realm as initially encoded over-the-wire. This is used in the
    169   // challenge text, rather than |realm_| which has been converted to
    170   // UTF-8.
    171   std::string original_realm_;
    172 
    173   int nonce_count_;
    174   const NonceGenerator* nonce_generator_;
    175 };
    176 
    177 }  // namespace net
    178 
    179 #endif  // NET_HTTP_HTTP_AUTH_HANDLER_DIGEST_H_
    180