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