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
17namespace net {
18
19// Code for handling http digest authentication.
20class 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        HttpAuthChallengeTokenizer* 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      HttpAuthChallengeTokenizer* challenge) OVERRIDE;
82
83 protected:
84  virtual bool Init(HttpAuthChallengeTokenizer* 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(HttpAuthChallengeTokenizer* 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