// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_HTTP_HTTP_AUTH_HANDLER_DIGEST_H_ #define NET_HTTP_HTTP_AUTH_HANDLER_DIGEST_H_ #include <string> #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "net/base/net_export.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" namespace net { // Code for handling http digest authentication. class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler { public: // A NonceGenerator is a simple interface for generating client nonces. // Unit tests can override the default client nonce behavior with fixed // nonce generation to get reproducible results. class NET_EXPORT_PRIVATE NonceGenerator { public: NonceGenerator(); virtual ~NonceGenerator(); // Generates a client nonce. virtual std::string GenerateNonce() const = 0; private: DISALLOW_COPY_AND_ASSIGN(NonceGenerator); }; // DynamicNonceGenerator does a random shuffle of 16 // characters to generate a client nonce. class DynamicNonceGenerator : public NonceGenerator { public: DynamicNonceGenerator(); virtual std::string GenerateNonce() const OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(DynamicNonceGenerator); }; // FixedNonceGenerator always uses the same string specified at // construction time as the client nonce. class NET_EXPORT_PRIVATE FixedNonceGenerator : public NonceGenerator { public: explicit FixedNonceGenerator(const std::string& nonce); virtual std::string GenerateNonce() const OVERRIDE; private: const std::string nonce_; DISALLOW_COPY_AND_ASSIGN(FixedNonceGenerator); }; class NET_EXPORT_PRIVATE Factory : public HttpAuthHandlerFactory { public: Factory(); virtual ~Factory(); // This factory owns the passed in |nonce_generator|. void set_nonce_generator(const NonceGenerator* nonce_generator); virtual int CreateAuthHandler( HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, const GURL& origin, CreateReason reason, int digest_nonce_count, const BoundNetLog& net_log, scoped_ptr<HttpAuthHandler>* handler) OVERRIDE; private: scoped_ptr<const NonceGenerator> nonce_generator_; }; virtual HttpAuth::AuthorizationResult HandleAnotherChallenge( HttpAuthChallengeTokenizer* challenge) OVERRIDE; protected: virtual bool Init(HttpAuthChallengeTokenizer* challenge) OVERRIDE; virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials, const HttpRequestInfo* request, const CompletionCallback& callback, std::string* auth_token) OVERRIDE; private: FRIEND_TEST_ALL_PREFIXES(HttpAuthHandlerDigestTest, ParseChallenge); FRIEND_TEST_ALL_PREFIXES(HttpAuthHandlerDigestTest, AssembleCredentials); FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, DigestPreAuthNonceCount); // Possible values for the "algorithm" property. enum DigestAlgorithm { // No algorithm was specified. According to RFC 2617 this means // we should default to ALGORITHM_MD5. ALGORITHM_UNSPECIFIED, // Hashes are run for every request. ALGORITHM_MD5, // Hash is run only once during the first WWW-Authenticate handshake. // (SESS means session). ALGORITHM_MD5_SESS, }; // Possible values for QualityOfProtection. // auth-int is not supported, see http://crbug.com/62890 for justification. enum QualityOfProtection { QOP_UNSPECIFIED, QOP_AUTH, }; // |nonce_count| indicates how many times the server-specified nonce has // been used so far. // |nonce_generator| is used to create a client nonce, and is not owned by // the handler. The lifetime of the |nonce_generator| must exceed that of this // handler. HttpAuthHandlerDigest(int nonce_count, const NonceGenerator* nonce_generator); virtual ~HttpAuthHandlerDigest(); // Parse the challenge, saving the results into this instance. // Returns true on success. bool ParseChallenge(HttpAuthChallengeTokenizer* challenge); // Parse an individual property. Returns true on success. bool ParseChallengeProperty(const std::string& name, const std::string& value); // Generates a random string, to be used for client-nonce. static std::string GenerateNonce(); // Convert enum value back to string. static std::string QopToString(QualityOfProtection qop); static std::string AlgorithmToString(DigestAlgorithm algorithm); // Extract the method and path of the request, as needed by // the 'A2' production. (path may be a hostname for proxy). void GetRequestMethodAndPath(const HttpRequestInfo* request, std::string* method, std::string* path) const; // Build up the 'response' production. std::string AssembleResponseDigest(const std::string& method, const std::string& path, const AuthCredentials& credentials, const std::string& cnonce, const std::string& nc) const; // Build up the value for (Authorization/Proxy-Authorization). std::string AssembleCredentials(const std::string& method, const std::string& path, const AuthCredentials& credentials, const std::string& cnonce, int nonce_count) const; // Information parsed from the challenge. std::string nonce_; std::string domain_; std::string opaque_; bool stale_; DigestAlgorithm algorithm_; QualityOfProtection qop_; // The realm as initially encoded over-the-wire. This is used in the // challenge text, rather than |realm_| which has been converted to // UTF-8. std::string original_realm_; int nonce_count_; const NonceGenerator* nonce_generator_; }; } // namespace net #endif // NET_HTTP_HTTP_AUTH_HANDLER_DIGEST_H_