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