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 #include <string_view> 11 12 #include "base/gtest_prod_util.h" 13 #include "base/memory/raw_ptr.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 class Algorithm { 116 // No algorithm was specified. According to RFC 2617 this means 117 // we should default to MD5. 118 UNSPECIFIED, 119 120 // Hashes are run for every request. 121 MD5, 122 123 // Hash is run only once during the first WWW-Authenticate handshake. 124 // (SESS means session). 125 MD5_SESS, 126 127 // SHA256 variants of the above. 128 SHA256, 129 SHA256_SESS, 130 }; 131 132 // Possible values for QualityOfProtection. 133 // auth-int is not supported, see http://crbug.com/62890 for justification. 134 enum QualityOfProtection { 135 QOP_UNSPECIFIED, 136 QOP_AUTH, 137 }; 138 139 // |nonce_count| indicates how many times the server-specified nonce has 140 // been used so far. 141 // |nonce_generator| is used to create a client nonce, and is not owned by 142 // the handler. The lifetime of the |nonce_generator| must exceed that of this 143 // handler. 144 HttpAuthHandlerDigest(int nonce_count, const NonceGenerator* nonce_generator); 145 146 // Parse the challenge, saving the results into this instance. 147 // Returns true on success. 148 bool ParseChallenge(HttpAuthChallengeTokenizer* challenge); 149 150 // Parse an individual property. Returns true on success. 151 bool ParseChallengeProperty(std::string_view name, std::string_view value); 152 153 // Generates a random string, to be used for client-nonce. 154 static std::string GenerateNonce(); 155 156 // Convert enum value back to string. 157 static std::string QopToString(QualityOfProtection qop); 158 static std::string AlgorithmToString(Algorithm algorithm); 159 160 // Extract the method and path of the request, as needed by 161 // the 'A2' production. (path may be a hostname for proxy). 162 void GetRequestMethodAndPath(const HttpRequestInfo* request, 163 std::string* method, 164 std::string* path) const; 165 166 // Build up the 'response' production. 167 std::string AssembleResponseDigest(const std::string& method, 168 const std::string& path, 169 const AuthCredentials& credentials, 170 const std::string& cnonce, 171 const std::string& nc) const; 172 173 // Build up the value for (Authorization/Proxy-Authorization). 174 std::string AssembleCredentials(const std::string& method, 175 const std::string& path, 176 const AuthCredentials& credentials, 177 const std::string& cnonce, 178 int nonce_count) const; 179 180 // Information parsed from the challenge. 181 std::string nonce_; 182 std::string domain_; 183 std::string opaque_; 184 bool stale_ = false; 185 Algorithm algorithm_ = Algorithm::UNSPECIFIED; 186 QualityOfProtection qop_ = QOP_UNSPECIFIED; 187 bool userhash_ = false; 188 189 // The realm as initially encoded over-the-wire. This is used in the 190 // challenge text, rather than |realm_| which has been converted to 191 // UTF-8. 192 std::string original_realm_; 193 194 int nonce_count_; 195 raw_ptr<const NonceGenerator> nonce_generator_; 196 197 class DigestContext; 198 }; 199 200 } // namespace net 201 202 #endif // NET_HTTP_HTTP_AUTH_HANDLER_DIGEST_H_ 203