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