diff options
author | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-01 18:12:26 +0000 |
---|---|---|
committer | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-01 18:12:26 +0000 |
commit | 65d3438acf8e8e4f525c23b00c46b7a1330b00ee (patch) | |
tree | 83a0c6c4299aaa901feea780b6ef6f2ec2f3c251 /net | |
parent | 5526773cbfbb6b9f3ef4fbec96bebc5014cf78ff (diff) | |
download | chromium_src-65d3438acf8e8e4f525c23b00c46b7a1330b00ee.zip chromium_src-65d3438acf8e8e4f525c23b00c46b7a1330b00ee.tar.gz chromium_src-65d3438acf8e8e4f525c23b00c46b7a1330b00ee.tar.bz2 |
Make the Negotiate Authentication Handler a state machine.
Now that the HttpNetworkTransaction correctly handles asynchronous auth token
generation, HttpAuthHandlerNegotiate can be turned into a state machine. This
also removes the need for the externally exposed "Resolve Canonical Name"
details to users of this handler.
BUG=42222
TEST=net_unittests
Review URL: http://codereview.chromium.org/2867022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51387 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/net_error_list.h | 3 | ||||
-rw-r--r-- | net/base/net_log_event_type_list.h | 4 | ||||
-rw-r--r-- | net/http/http_auth_controller.cc | 11 | ||||
-rw-r--r-- | net/http/http_auth_controller.h | 7 | ||||
-rw-r--r-- | net/http/http_auth_gssapi_posix.cc | 1 | ||||
-rw-r--r-- | net/http/http_auth_gssapi_posix.h | 1 | ||||
-rw-r--r-- | net/http/http_auth_handler.cc | 7 | ||||
-rw-r--r-- | net/http/http_auth_handler.h | 12 | ||||
-rw-r--r-- | net/http/http_auth_handler_negotiate.cc (renamed from net/http/http_auth_handler_negotiate_win.cc) | 226 | ||||
-rw-r--r-- | net/http/http_auth_handler_negotiate.h | 57 | ||||
-rw-r--r-- | net/http/http_auth_handler_negotiate_posix.cc | 211 | ||||
-rw-r--r-- | net/http/http_auth_handler_negotiate_unittest.cc | 81 | ||||
-rw-r--r-- | net/http/http_auth_handler_ntlm.cc | 1 | ||||
-rw-r--r-- | net/http/http_auth_sspi_win.cc | 19 | ||||
-rw-r--r-- | net/http/http_auth_sspi_win.h | 15 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 36 | ||||
-rw-r--r-- | net/http/http_network_transaction.h | 5 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 78 | ||||
-rw-r--r-- | net/http/mock_sspi_library_win.cc | 20 | ||||
-rw-r--r-- | net/net.gyp | 3 |
20 files changed, 301 insertions, 497 deletions
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index b471930..e138ffe 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -156,9 +156,6 @@ NET_ERROR(SSL_DECOMPRESSION_FAILURE_ALERT, -125) // from servers with buggy DEFLATE support. NET_ERROR(SSL_BAD_RECORD_MAC_ALERT, -126) -// The HTTP auth handler requires a DNS lookup to find the canonical name. -NET_ERROR(AUTH_NEEDS_CANONICAL_NAME, -127) - // A known TLS strict server didn't offer the renegotiation extension. NET_ERROR(SSL_UNSAFE_NEGOTIATION, -128) diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h index d129024..cc26f5f 100644 --- a/net/base/net_log_event_type_list.h +++ b/net/base/net_log_event_type_list.h @@ -400,10 +400,6 @@ EVENT_TYPE(HTTP_TRANSACTION_READ_HEADERS) // } EVENT_TYPE(HTTP_TRANSACTION_READ_RESPONSE_HEADERS) -// Measures the time to resolve the canonical name for HTTP Negotiate -// authentication scheme. -EVENT_TYPE(HTTP_TRANSACTION_RESOLVE_CANONICAL_NAME) - // Measures the time to read the entity body from the server. EVENT_TYPE(HTTP_TRANSACTION_READ_BODY) diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc index b85ae03..a40b5d9 100644 --- a/net/http/http_auth_controller.cc +++ b/net/http/http_auth_controller.cc @@ -196,20 +196,9 @@ int HttpAuthController::HandleAuthChallenge( PopulateAuthChallenge(); } - // SPN determination (for Negotiate) requires a DNS lookup to find the - // canonical name. This needs to be done asynchronously to prevent blocking - // the IO thread. - if (handler_->NeedsCanonicalName()) - return ERR_AUTH_NEEDS_CANONICAL_NAME; - return OK; } -int HttpAuthController::ResolveCanonicalName(CompletionCallback* callback) { - DCHECK(handler_.get()); - return handler_->ResolveCanonicalName(session_->host_resolver(), callback); -} - void HttpAuthController::ResetAuth(const std::wstring& username, const std::wstring& password) { DCHECK(identity_.invalid || (username.empty() && password.empty())); diff --git a/net/http/http_auth_controller.h b/net/http/http_auth_controller.h index bc1395f..6a74dea 100644 --- a/net/http/http_auth_controller.h +++ b/net/http/http_auth_controller.h @@ -43,14 +43,11 @@ class HttpAuthController { void AddAuthorizationHeader(HttpRequestHeaders* authorization_headers); // Checks for and handles HTTP status code 401 or 407. - // |HandleAuthChallenge()| returns OK on success, - // ERR_AUTH_NEEDS_CANONICAL_NAME if the handler needs the canonical name - // resolved, or a network error code. It may also populate |auth_info_|. + // |HandleAuthChallenge()| returns OK on success, or a network error code + // otherwise. It may also populate |auth_info_|. int HandleAuthChallenge(scoped_refptr<HttpResponseHeaders> headers, int load_flags, bool establishing_tunnel); - int ResolveCanonicalName(CompletionCallback* callback); - // Store the supplied credentials and prepare to restart the auth. void ResetAuth(const std::wstring& username, const std::wstring& password); diff --git a/net/http/http_auth_gssapi_posix.cc b/net/http/http_auth_gssapi_posix.cc index 94e2b11..b9c3144 100644 --- a/net/http/http_auth_gssapi_posix.cc +++ b/net/http/http_auth_gssapi_posix.cc @@ -614,7 +614,6 @@ bool HttpAuthGSSAPI::ParseChallenge(HttpAuth::ChallengeTokenizer* tok) { int HttpAuthGSSAPI::GenerateAuthToken(const std::wstring* username, const std::wstring* password, const std::wstring& spn, - const HttpRequestInfo* request, std::string* auth_token) { DCHECK((username == NULL) == (password == NULL)); diff --git a/net/http/http_auth_gssapi_posix.h b/net/http/http_auth_gssapi_posix.h index d42a523..f0642ea 100644 --- a/net/http/http_auth_gssapi_posix.h +++ b/net/http/http_auth_gssapi_posix.h @@ -240,7 +240,6 @@ class HttpAuthGSSAPI { int GenerateAuthToken(const std::wstring* username, const std::wstring* password, const std::wstring& spn, - const HttpRequestInfo* request, std::string* auth_token); private: diff --git a/net/http/http_auth_handler.cc b/net/http/http_auth_handler.cc index 207232b..0bb017b 100644 --- a/net/http/http_auth_handler.cc +++ b/net/http/http_auth_handler.cc @@ -115,11 +115,4 @@ void HttpAuthHandler::FinishGenerateAuthToken() { original_callback_ = NULL; } -int HttpAuthHandler::ResolveCanonicalName(net::HostResolver* host_resolver, - CompletionCallback* callback) { - NOTREACHED(); - LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED); - return ERR_NOT_IMPLEMENTED; -} - } // namespace net diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h index a6faebe..f919898 100644 --- a/net/http/http_auth_handler.h +++ b/net/http/http_auth_handler.h @@ -118,18 +118,6 @@ class HttpAuthHandler { // TODO(cbentzel): Add a pointer to Firefox documentation about risk. virtual bool AllowsDefaultCredentials() { return false; } - // Returns whether the canonical DNS name for the origin host needs to be - // resolved. The Negotiate auth scheme typically uses the canonical DNS - // name when constructing the Kerberos SPN. - virtual bool NeedsCanonicalName() { return false; } - - // Resolves the canonical name for the |origin_| host. The canonical - // name is used by the Negotiate scheme to generate a valid Kerberos - // SPN. - // The return value is a net error code. - virtual int ResolveCanonicalName(HostResolver* host_resolver, - CompletionCallback* callback); - protected: enum Property { ENCRYPTS_IDENTITY = 1 << 0, diff --git a/net/http/http_auth_handler_negotiate_win.cc b/net/http/http_auth_handler_negotiate.cc index f29a9d8..2416c1a 100644 --- a/net/http/http_auth_handler_negotiate_win.cc +++ b/net/http/http_auth_handler_negotiate.cc @@ -14,17 +14,33 @@ namespace net { HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate( +#if defined(OS_WIN) SSPILibrary* library, ULONG max_token_length, +#endif +#if defined(OS_POSIX) + GSSAPILibrary* library, +#endif URLSecurityManager* url_security_manager, + HostResolver* resolver, bool disable_cname_lookup, bool use_port) - : auth_sspi_(library, "Negotiate", NEGOSSP_NAME, max_token_length), - user_callback_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST(resolve_cname_callback_( - this, &HttpAuthHandlerNegotiate::OnResolveCanonicalName)), +#if defined(OS_WIN) + : auth_system_(library, "Negotiate", NEGOSSP_NAME, max_token_length), +#endif +#if defined(OS_POSIX) + : auth_system_(library, "Negotiate", CHROME_GSS_KRB5_MECH_OID_DESC), +#endif disable_cname_lookup_(disable_cname_lookup), use_port_(use_port), + ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( + this, &HttpAuthHandlerNegotiate::OnIOComplete)), + resolver_(resolver), + already_called_(false), + has_username_and_password_(false), + user_callback_(NULL), + auth_token_(NULL), + next_state_(STATE_NONE), url_security_manager_(url_security_manager) { } @@ -37,12 +53,28 @@ int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl( const HttpRequestInfo* request, CompletionCallback* callback, std::string* auth_token) { - return auth_sspi_.GenerateAuthToken( - username, - password, - spn_, - request, - auth_token); + DCHECK(user_callback_ == NULL); + DCHECK((username == NULL) == (password == NULL)); + DCHECK(auth_token_ == NULL); + auth_token_ = auth_token; + if (already_called_) { + DCHECK((!has_username_and_password_ && username == NULL) || + (has_username_and_password_ && *username == username_ && + *password == password_)); + next_state_ = STATE_GENERATE_AUTH_TOKEN; + } else { + already_called_ = true; + if (username) { + has_username_and_password_ = true; + username_ = *username; + password_ = *password; + } + next_state_ = STATE_RESOLVE_CANONICAL_NAME; + } + int rv = DoLoop(OK); + if (rv == ERR_IO_PENDING) + user_callback_ = callback; + return rv; } // The Negotiate challenge header looks like: @@ -51,16 +83,16 @@ bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* challenge) { scheme_ = "negotiate"; score_ = 4; properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; - return auth_sspi_.ParseChallenge(challenge); + return auth_system_.ParseChallenge(challenge); } // Require identity on first pass instead of second. bool HttpAuthHandlerNegotiate::NeedsIdentity() { - return auth_sspi_.NeedsIdentity(); + return auth_system_.NeedsIdentity(); } bool HttpAuthHandlerNegotiate::IsFinalRound() { - return auth_sspi_.IsFinalRound(); + return auth_system_.IsFinalRound(); } bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() { @@ -71,58 +103,6 @@ bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() { return url_security_manager_->CanUseDefaultCredentials(origin_); } -bool HttpAuthHandlerNegotiate::NeedsCanonicalName() { - if (!spn_.empty()) - return false; - if (disable_cname_lookup_) { - spn_ = CreateSPN(address_list_, origin_); - address_list_.Reset(); - return false; - } - return true; -} - -int HttpAuthHandlerNegotiate::ResolveCanonicalName( - HostResolver* resolver, CompletionCallback* callback) { - // TODO(cbentzel): Add reverse DNS lookup for numeric addresses. - DCHECK(!single_resolve_.get()); - DCHECK(!disable_cname_lookup_); - DCHECK(callback); - - HostResolver::RequestInfo info(origin_.host(), 0); - info.set_host_resolver_flags(HOST_RESOLVER_CANONNAME); - single_resolve_.reset(new SingleRequestHostResolver(resolver)); - int rv = single_resolve_->Resolve(info, &address_list_, - &resolve_cname_callback_, - net_log_); - if (rv == ERR_IO_PENDING) { - user_callback_ = callback; - return rv; - } - OnResolveCanonicalName(rv); - // Always return OK. OnResolveCanonicalName logs the error code if not - // OK and attempts to use the original origin_ hostname rather than failing - // the auth attempt completely. - return OK; -} - -void HttpAuthHandlerNegotiate::OnResolveCanonicalName(int result) { - if (result != OK) { - // Even in the error case, try to use origin_.host instead of - // passing the failure on to the caller. - LOG(INFO) << "Problem finding canonical name for SPN for host " - << origin_.host() << ": " << ErrorToString(result); - result = OK; - } - spn_ = CreateSPN(address_list_, origin_); - address_list_.Reset(); - if (user_callback_) { - CompletionCallback* callback = user_callback_; - user_callback_ = NULL; - callback->Run(result); - } -} - std::wstring HttpAuthHandlerNegotiate::CreateSPN( const AddressList& address_list, const GURL& origin) { // Kerberos SPNs are in the form HTTP/<host>:<port> @@ -164,18 +144,118 @@ std::wstring HttpAuthHandlerNegotiate::CreateSPN( } } +int HttpAuthHandlerNegotiate::DoLoop(int result) { + DCHECK(next_state_ != STATE_NONE); + + int rv = result; + do { + State state = next_state_; + next_state_ = STATE_NONE; + switch (state) { + case STATE_RESOLVE_CANONICAL_NAME: + DCHECK_EQ(OK, rv); + rv = DoResolveCanonicalName(); + break; + case STATE_RESOLVE_CANONICAL_NAME_COMPLETE: + rv = DoResolveCanonicalNameComplete(rv); + break; + case STATE_GENERATE_AUTH_TOKEN: + DCHECK_EQ(OK, rv); + rv = DoGenerateAuthToken(); + break; + case STATE_GENERATE_AUTH_TOKEN_COMPLETE: + rv = DoGenerateAuthTokenComplete(rv); + break; + default: + NOTREACHED() << "bad state"; + rv = ERR_FAILED; + break; + } + } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); + + return rv; +} + +int HttpAuthHandlerNegotiate::DoResolveCanonicalName() { + next_state_ = STATE_RESOLVE_CANONICAL_NAME_COMPLETE; + if (disable_cname_lookup_) + return OK; + + // TODO(cbentzel): Add reverse DNS lookup for numeric addresses. + DCHECK(!single_resolve_.get()); + HostResolver::RequestInfo info(origin_.host(), 0); + info.set_host_resolver_flags(HOST_RESOLVER_CANONNAME); + single_resolve_.reset(new SingleRequestHostResolver(resolver_)); + return single_resolve_->Resolve(info, &address_list_, &io_callback_, + net_log_); +} + +int HttpAuthHandlerNegotiate::DoResolveCanonicalNameComplete(int rv) { + DCHECK_NE(ERR_IO_PENDING, rv); + if (rv != OK) { + // Even in the error case, try to use origin_.host instead of + // passing the failure on to the caller. + LOG(INFO) << "Problem finding canonical name for SPN for host " + << origin_.host() << ": " << ErrorToString(rv); + rv = OK; + } + + next_state_ = STATE_GENERATE_AUTH_TOKEN; + spn_ = CreateSPN(address_list_, origin_); + address_list_.Reset(); + return rv; +} + +int HttpAuthHandlerNegotiate::DoGenerateAuthToken() { + next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; + std::wstring* username = has_username_and_password_ ? &username_ : NULL; + std::wstring* password = has_username_and_password_ ? &password_ : NULL; + // TODO(cbentzel): This should possibly be done async. + return auth_system_.GenerateAuthToken(username, password, spn_, auth_token_); +} + +int HttpAuthHandlerNegotiate::DoGenerateAuthTokenComplete(int rv) { + DCHECK_NE(ERR_IO_PENDING, rv); + auth_token_ = NULL; + return rv; +} + +void HttpAuthHandlerNegotiate::OnIOComplete(int result) { + int rv = DoLoop(result); + if (rv != ERR_IO_PENDING) + DoCallback(rv); +} + +void HttpAuthHandlerNegotiate::DoCallback(int rv) { + DCHECK(rv != ERR_IO_PENDING); + DCHECK(user_callback_); + CompletionCallback* callback = user_callback_; + user_callback_ = NULL; + callback->Run(rv); +} + HttpAuthHandlerNegotiate::Factory::Factory() : disable_cname_lookup_(false), use_port_(false), +#if defined(OS_WIN) max_token_length_(0), first_creation_(true), is_unsupported_(false), sspi_library_(SSPILibrary::GetDefault()) { +#endif +#if defined(OS_POSIX) + gssapi_library_(GSSAPILibrary::GetDefault()) { +#endif } HttpAuthHandlerNegotiate::Factory::~Factory() { } +void HttpAuthHandlerNegotiate::Factory::set_host_resolver( + HostResolver* resolver) { + resolver_ = resolver; +} + int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler( HttpAuth::ChallengeTokenizer* challenge, HttpAuth::Target target, @@ -184,6 +264,7 @@ int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler( int digest_nonce_count, const BoundNetLog& net_log, scoped_ptr<HttpAuthHandler>* handler) { +#if defined(OS_WIN) if (is_unsupported_ || reason == CREATE_PREEMPTIVE) return ERR_UNSUPPORTED_AUTH_SCHEME; if (max_token_length_ == 0) { @@ -198,12 +279,25 @@ int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler( // method and only constructing when valid. scoped_ptr<HttpAuthHandler> tmp_handler( new HttpAuthHandlerNegotiate(sspi_library_, max_token_length_, - url_security_manager(), + url_security_manager(), resolver_, disable_cname_lookup_, use_port_)); if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) return ERR_INVALID_RESPONSE; handler->swap(tmp_handler); return OK; +#endif +#if defined(OS_POSIX) + // TODO(ahendrickson): Move towards model of parsing in the factory + // method and only constructing when valid. + scoped_ptr<HttpAuthHandler> tmp_handler( + new HttpAuthHandlerNegotiate(gssapi_library_, url_security_manager(), + resolver_, disable_cname_lookup_, + use_port_)); + if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) + return ERR_INVALID_RESPONSE; + handler->swap(tmp_handler); + return OK; +#endif } } // namespace net diff --git a/net/http/http_auth_handler_negotiate.h b/net/http/http_auth_handler_negotiate.h index 687df8a..e4514d1 100644 --- a/net/http/http_auth_handler_negotiate.h +++ b/net/http/http_auth_handler_negotiate.h @@ -9,6 +9,7 @@ #include "build/build_config.h" +#include "build/build_config.h" #include "net/base/address_list.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" @@ -23,6 +24,7 @@ namespace net { +class HostResolver; class SingleRequestHostResolver; class URLSecurityManager; @@ -54,6 +56,8 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler { bool use_port() const { return use_port_; } void set_use_port(bool use_port) { use_port_ = use_port; } + void set_host_resolver(HostResolver* host_resolver); + virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge, HttpAuth::Target target, const GURL& origin, @@ -76,6 +80,7 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler { private: bool disable_cname_lookup_; bool use_port_; + scoped_refptr<HostResolver> resolver_; #if defined(OS_WIN) ULONG max_token_length_; bool first_creation_; @@ -91,12 +96,14 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler { #if defined(OS_WIN) HttpAuthHandlerNegotiate(SSPILibrary* sspi_library, ULONG max_token_length, URLSecurityManager* url_security_manager, + HostResolver* host_resolver, bool disable_cname_lookup, bool use_port); #endif #if defined(OS_POSIX) HttpAuthHandlerNegotiate(GSSAPILibrary* gssapi_library, URLSecurityManager* url_security_manager, + HostResolver* host_resolver, bool disable_cname_lookup, bool use_port); #endif @@ -108,11 +115,6 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler { virtual bool AllowsDefaultCredentials(); - virtual bool NeedsCanonicalName(); - - virtual int ResolveCanonicalName(HostResolver* host_resolver, - CompletionCallback* callback); - // These are public for unit tests std::wstring CreateSPN(const AddressList& address_list, const GURL& orign); const std::wstring& spn() const { return spn_; } @@ -127,23 +129,54 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler { std::string* auth_token); private: - void OnResolveCanonicalName(int result); + enum State { + STATE_RESOLVE_CANONICAL_NAME, + STATE_RESOLVE_CANONICAL_NAME_COMPLETE, + STATE_GENERATE_AUTH_TOKEN, + STATE_GENERATE_AUTH_TOKEN_COMPLETE, + STATE_NONE, + }; + + void OnIOComplete(int result); + void DoCallback(int result); + int DoLoop(int result); + + int DoResolveCanonicalName(); + int DoResolveCanonicalNameComplete(int rv); + int DoGenerateAuthToken(); + int DoGenerateAuthTokenComplete(int rv); #if defined(OS_WIN) - HttpAuthSSPI auth_sspi_; + // Members which are constant for lifetime of the handler. + HttpAuthSSPI auth_system_; #endif #if defined(OS_POSIX) - HttpAuthGSSAPI auth_gssapi_; + HttpAuthGSSAPI auth_system_; #endif - AddressList address_list_; - scoped_ptr<SingleRequestHostResolver> single_resolve_; - CompletionCallback* user_callback_; - CompletionCallbackImpl<HttpAuthHandlerNegotiate> resolve_cname_callback_; bool disable_cname_lookup_; bool use_port_; + CompletionCallbackImpl<HttpAuthHandlerNegotiate> io_callback_; + scoped_refptr<HostResolver> resolver_; + + // Members which are needed for DNS lookup + SPN. + AddressList address_list_; + scoped_ptr<SingleRequestHostResolver> single_resolve_; + + // Things which should be consistent after first call to GenerateAuthToken. + bool already_called_; + bool has_username_and_password_; + std::wstring username_; + std::wstring password_; std::wstring spn_; + + // Things which vary each round. + CompletionCallback* user_callback_; + std::string* auth_token_; + + State next_state_; + URLSecurityManager* url_security_manager_; }; diff --git a/net/http/http_auth_handler_negotiate_posix.cc b/net/http/http_auth_handler_negotiate_posix.cc deleted file mode 100644 index a863fe4..0000000 --- a/net/http/http_auth_handler_negotiate_posix.cc +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) 2010 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. - -#include "net/http/http_auth_handler_negotiate.h" - -#include "base/logging.h" -#include "base/string_util.h" -#include "net/base/address_family.h" -#include "net/base/host_resolver.h" -#include "net/base/net_errors.h" -#include "net/http/http_auth_filter.h" -#include "net/http/http_auth_gssapi_posix.h" -#include "net/http/url_security_manager.h" - -namespace net { - -HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate( - GSSAPILibrary* gssapi_library, - URLSecurityManager* url_security_manager, - bool disable_cname_lookup, - bool use_port) - : auth_gssapi_(gssapi_library, - "Negotiate", - CHROME_GSS_KRB5_MECH_OID_DESC), - user_callback_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST(resolve_cname_callback_( - this, &HttpAuthHandlerNegotiate::OnResolveCanonicalName)), - disable_cname_lookup_(disable_cname_lookup), - use_port_(use_port), - url_security_manager_(url_security_manager) { -} - -HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() { -} - -int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl( - const std::wstring* username, - const std::wstring* password, - const HttpRequestInfo* request, - CompletionCallback* callback, - std::string* auth_token) { - int rv = auth_gssapi_.GenerateAuthToken( - username, - password, - spn_, - request, - auth_token); - return rv; -} - -bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* challenge) { - if (!auth_gssapi_.Init()) { - LOG(INFO) << "can't initialize GSSAPI library"; - return false; - } - scheme_ = "negotiate"; - score_ = 4; - properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; - bool value = auth_gssapi_.ParseChallenge(challenge); - return value; -} - -bool HttpAuthHandlerNegotiate::NeedsIdentity() { - bool value = auth_gssapi_.NeedsIdentity(); - return value; -} - -bool HttpAuthHandlerNegotiate::IsFinalRound() { - bool value = auth_gssapi_.IsFinalRound(); - return value; -} - -// TODO(ahendrickson) -- Most of this code can be shared between Windows and -// Posix now. -bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() { - bool allowed = false; - if (target_ == HttpAuth::AUTH_PROXY) - allowed = true; - else if (!url_security_manager_) - allowed = false; - else - allowed = url_security_manager_->CanUseDefaultCredentials(origin_); - return allowed; -} - -bool HttpAuthHandlerNegotiate::NeedsCanonicalName() { - bool needs_name = true; - if (!spn_.empty()) - needs_name = false; - else if (disable_cname_lookup_) { - spn_ = CreateSPN(address_list_, origin_); - address_list_.Reset(); - needs_name = false; - } - return needs_name; -} - -int HttpAuthHandlerNegotiate::ResolveCanonicalName( - HostResolver* resolver, CompletionCallback* callback) { - // TODO(ahendrickson): Add reverse DNS lookup for numeric addresses. - DCHECK(!single_resolve_.get()); - DCHECK(!disable_cname_lookup_); - DCHECK(callback); - - HostResolver::RequestInfo info(origin_.host(), 0); - info.set_host_resolver_flags(HOST_RESOLVER_CANONNAME); - single_resolve_.reset(new SingleRequestHostResolver(resolver)); - int rv = single_resolve_->Resolve(info, &address_list_, - &resolve_cname_callback_, - net_log_); - if (rv == ERR_IO_PENDING) { - user_callback_ = callback; - } else { - OnResolveCanonicalName(rv); - // Always return OK. OnResolveCanonicalName logs the error code if not - // OK and attempts to use the original origin_ hostname rather than failing - // the auth attempt completely. - rv = OK; - } - return rv; -} - -void HttpAuthHandlerNegotiate::OnResolveCanonicalName(int result) { - if (result != OK) { - // Even in the error case, try to use origin_.host instead of - // passing the failure on to the caller. - LOG(INFO) << "Problem finding canonical name for SPN for host " - << origin_.host() << ": " << ErrorToString(result); - result = OK; - } - spn_ = CreateSPN(address_list_, origin_); - address_list_.Reset(); - if (user_callback_) { - CompletionCallback* callback = user_callback_; - user_callback_ = NULL; - callback->Run(result); - } -} - -std::wstring HttpAuthHandlerNegotiate::CreateSPN( - const AddressList& address_list, const GURL& origin) { - // Kerberos SPNs for GSSAPI are in the form host@<host>:<port> - // http://msdn.microsoft.com/en-us/library/ms677601%28VS.85%29.aspx - // - // However, reality differs from the specification. A good description of - // the problems can be found here: - // http://blog.michelbarneveld.nl/michel/archive/2009/11/14/the-reason-why-kb911149-and-kb908209-are-not-the-soluton.aspx - // - // Typically the <host> portion should be the canonical FQDN for the service. - // If this could not be resolved, the original hostname in the URL will be - // attempted instead. However, some intranets register SPNs using aliases - // for the same canonical DNS name to allow multiple web services to reside - // on the same host machine without requiring different ports. IE6 and IE7 - // have hotpatches that allow the default behavior to be overridden. - // http://support.microsoft.com/kb/911149 - // http://support.microsoft.com/kb/938305 - // - // According to the spec, the <port> option should be included if it is a - // non-standard port (i.e. not 80 or 443 in the HTTP case). However, - // historically browsers have not included the port, even on non-standard - // ports. IE6 required a hotpatch and a registry setting to enable - // including non-standard ports, and IE7 and IE8 also require the same - // registry setting, but no hotpatch. Firefox does not appear to have an - // option to include non-standard ports as of 3.6. - // http://support.microsoft.com/kb/908209 - // - // Without any command-line flags, Chrome matches the behavior of Firefox - // and IE. Users can override the behavior so aliases are allowed and - // non-standard ports are included. - int port = origin.EffectiveIntPort(); - std::string server; - if (!address_list.GetCanonicalName(&server)) - server = origin.host(); - std::string resulting_spn; - if (port != 80 && port != 443 && use_port_) { - resulting_spn = StringPrintf("host@%s:%d", server.c_str(), port); - } else { - resulting_spn = StringPrintf("host@%s", server.c_str()); - } - return ASCIIToWide(resulting_spn); -} - -HttpAuthHandlerNegotiate::Factory::Factory() - : disable_cname_lookup_(false), use_port_(false), - gssapi_library_(GSSAPILibrary::GetDefault()) { -} - -HttpAuthHandlerNegotiate::Factory::~Factory() { -} - -int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler( - HttpAuth::ChallengeTokenizer* challenge, - HttpAuth::Target target, - const GURL& origin, - CreateReason reason, - int digest_nonce_count, - const BoundNetLog& net_log, - scoped_ptr<HttpAuthHandler>* handler) { - // TODO(ahendrickson): Move towards model of parsing in the factory - // method and only constructing when valid. - scoped_ptr<HttpAuthHandler> tmp_handler( - new HttpAuthHandlerNegotiate(gssapi_library_, url_security_manager(), - disable_cname_lookup_, use_port_)); - if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) - return ERR_INVALID_RESPONSE; - handler->swap(tmp_handler); - return OK; -} - -} // namespace net diff --git a/net/http/http_auth_handler_negotiate_unittest.cc b/net/http/http_auth_handler_negotiate_unittest.cc index a5b3011..48206a2 100644 --- a/net/http/http_auth_handler_negotiate_unittest.cc +++ b/net/http/http_auth_handler_negotiate_unittest.cc @@ -7,6 +7,7 @@ #include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" +#include "net/http/http_request_info.h" #if defined(OS_WIN) #include "net/http/mock_sspi_library_win.h" #endif @@ -20,10 +21,20 @@ namespace net { namespace { void CreateHandler(bool disable_cname_lookup, bool include_port, + bool synchronous_resolve_mode, const std::string& url_string, SSPILibrary* sspi_library, scoped_ptr<HttpAuthHandlerNegotiate>* handler) { + // Create a MockHostResolver - this will be referenced by the + // handler (and be destroyed when the handler goes away since it holds + // the only reference). + MockHostResolver* mock_resolver = new MockHostResolver(); + scoped_refptr<HostResolver> resolver(mock_resolver); + mock_resolver->set_synchronous_mode(synchronous_resolve_mode); + mock_resolver->rules()->AddIPLiteralRule("alias", "10.0.0.2", + "canonical.example.com"); handler->reset(new HttpAuthHandlerNegotiate(sspi_library, 50, NULL, + mock_resolver, disable_cname_lookup, include_port)); std::string challenge = "Negotiate"; @@ -38,55 +49,79 @@ void CreateHandler(bool disable_cname_lookup, bool include_port, TEST(HttpAuthHandlerNegotiateTest, DisableCname) { MockSSPILibrary mock_library; scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; - CreateHandler(true, false, "http://alias:500", &mock_library, &auth_handler); - EXPECT_FALSE(auth_handler->NeedsCanonicalName()); + CreateHandler(true, false, true, "http://alias:500", + &mock_library, &auth_handler); + TestCompletionCallback callback; + HttpRequestInfo request_info; + std::string token; + std::wstring username = L"foo"; + std::wstring password = L"bar"; + EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, + &request_info, + &callback, &token)); EXPECT_EQ(L"HTTP/alias", auth_handler->spn()); } TEST(HttpAuthHandlerNegotiateTest, DisableCnameStandardPort) { MockSSPILibrary mock_library; scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; - CreateHandler(true, true, "http://alias:80", &mock_library, &auth_handler); - EXPECT_FALSE(auth_handler->NeedsCanonicalName()); + CreateHandler(true, true, true, + "http://alias:80", &mock_library, &auth_handler); + TestCompletionCallback callback; + HttpRequestInfo request_info; + std::string token; + std::wstring username = L"foo"; + std::wstring password = L"bar"; + EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, + &request_info, + &callback, &token)); EXPECT_EQ(L"HTTP/alias", auth_handler->spn()); } TEST(HttpAuthHandlerNegotiateTest, DisableCnameNonstandardPort) { MockSSPILibrary mock_library; scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; - CreateHandler(true, true, "http://alias:500", &mock_library, &auth_handler); - EXPECT_FALSE(auth_handler->NeedsCanonicalName()); + CreateHandler(true, true, true, + "http://alias:500", &mock_library, &auth_handler); + TestCompletionCallback callback; + HttpRequestInfo request_info; + std::string token; + std::wstring username = L"foo"; + std::wstring password = L"bar"; + EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, + &request_info, + &callback, &token)); EXPECT_EQ(L"HTTP/alias:500", auth_handler->spn()); } TEST(HttpAuthHandlerNegotiateTest, CnameSync) { MockSSPILibrary mock_library; scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; - CreateHandler(false, false, "http://alias:500", &mock_library, &auth_handler); - EXPECT_TRUE(auth_handler->NeedsCanonicalName()); - MockHostResolver* mock_resolver = new MockHostResolver(); - scoped_refptr<HostResolver> scoped_resolver(mock_resolver); - mock_resolver->set_synchronous_mode(true); - mock_resolver->rules()->AddIPLiteralRule("alias", "10.0.0.2", - "canonical.example.com"); + CreateHandler(false, false, true, + "http://alias:500", &mock_library, &auth_handler); TestCompletionCallback callback; - EXPECT_EQ(OK, auth_handler->ResolveCanonicalName(mock_resolver, &callback)); + HttpRequestInfo request_info; + std::string token; + std::wstring username = L"foo"; + std::wstring password = L"bar"; + EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, + &request_info, + &callback, &token)); EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn()); } TEST(HttpAuthHandlerNegotiateTest, CnameAsync) { MockSSPILibrary mock_library; scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; - CreateHandler(false, false, "http://alias:500", &mock_library, &auth_handler); - EXPECT_TRUE(auth_handler->NeedsCanonicalName()); - MockHostResolver* mock_resolver = new MockHostResolver(); - scoped_refptr<HostResolver> scoped_resolver(mock_resolver); - mock_resolver->set_synchronous_mode(false); - mock_resolver->rules()->AddIPLiteralRule("alias", "10.0.0.2", - "canonical.example.com"); + CreateHandler(false, false, false, + "http://alias:500", &mock_library, &auth_handler); TestCompletionCallback callback; - EXPECT_EQ(ERR_IO_PENDING, auth_handler->ResolveCanonicalName(mock_resolver, - &callback)); + HttpRequestInfo request_info; + std::string token; + std::wstring username = L"foo"; + std::wstring password = L"bar"; + EXPECT_EQ(ERR_IO_PENDING, auth_handler->GenerateAuthToken( + &username, &password, &request_info, &callback, &token)); EXPECT_EQ(OK, callback.WaitForResult()); EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn()); } diff --git a/net/http/http_auth_handler_ntlm.cc b/net/http/http_auth_handler_ntlm.cc index b50a0a9..d8e8a75 100644 --- a/net/http/http_auth_handler_ntlm.cc +++ b/net/http/http_auth_handler_ntlm.cc @@ -24,7 +24,6 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl( username, password, CreateSPN(origin_), - request, auth_token); #else // !defined(NTLM_SSPI) // TODO(wtc): See if we can use char* instead of void* for in_buf and diff --git a/net/http/http_auth_sspi_win.cc b/net/http/http_auth_sspi_win.cc index 381d7ab..221acf1 100644 --- a/net/http/http_auth_sspi_win.cc +++ b/net/http/http_auth_sspi_win.cc @@ -41,12 +41,12 @@ int MapAcquireCredentialsStatusToError(SECURITY_STATUS status, } } -int AcquireCredentials(SSPILibrary* library, - const SEC_WCHAR* package, - const std::wstring& domain, - const std::wstring& user, - const std::wstring& password, - CredHandle* cred) { +int AcquireExplicitCredentials(SSPILibrary* library, + const SEC_WCHAR* package, + const std::wstring& domain, + const std::wstring& user, + const std::wstring& password, + CredHandle* cred) { SEC_WINNT_AUTH_IDENTITY identity; identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; identity.User = @@ -162,7 +162,6 @@ bool HttpAuthSSPI::ParseChallenge(HttpAuth::ChallengeTokenizer* tok) { int HttpAuthSSPI::GenerateAuthToken(const std::wstring* username, const std::wstring* password, const std::wstring& spn, - const HttpRequestInfo* request, std::string* auth_token) { DCHECK((username == NULL) == (password == NULL)); @@ -173,6 +172,7 @@ int HttpAuthSSPI::GenerateAuthToken(const std::wstring* username, return rv; } + DCHECK(SecIsValidHandle(&cred_)); void* out_buf; int out_buf_len; int rv = GetNextSecurityToken( @@ -202,13 +202,14 @@ int HttpAuthSSPI::GenerateAuthToken(const std::wstring* username, int HttpAuthSSPI::OnFirstRound(const std::wstring* username, const std::wstring* password) { DCHECK((username == NULL) == (password == NULL)); + DCHECK(!SecIsValidHandle(&cred_)); int rv = OK; if (username) { std::wstring domain; std::wstring user; SplitDomainAndUser(*username, &domain, &user); - rv = AcquireCredentials(library_, security_package_, domain, - user, *password, &cred_); + rv = AcquireExplicitCredentials(library_, security_package_, domain, + user, *password, &cred_); if (rv != OK) return rv; } else { diff --git a/net/http/http_auth_sspi_win.h b/net/http/http_auth_sspi_win.h index 164bd07..14d158a 100644 --- a/net/http/http_auth_sspi_win.h +++ b/net/http/http_auth_sspi_win.h @@ -31,7 +31,7 @@ class ProxyInfo; // sensitive code. class SSPILibrary { public: - virtual ~SSPILibrary() {}; + virtual ~SSPILibrary() {} virtual SECURITY_STATUS AcquireCredentialsHandle(LPWSTR pszPrincipal, LPWSTR pszPackage, @@ -84,18 +84,17 @@ class HttpAuthSSPI { bool ParseChallenge(HttpAuth::ChallengeTokenizer* tok); - // Generates an authentication token. - // The return value is an error code. If it's not |OK|, the value of - // |*auth_token| is unspecified. - // |spn| is the Service Principal Name of the server that the token is - // being generated for. + // Generates an authentication token for the service specified by the + // Service Principal Name |spn| and stores the value in |*auth_token|. + // If the return value is not |OK|, then the value of |*auth_token| is + // unspecified. ERR_IO_PENDING is not a valid return code. // If this is the first round of a multiple round scheme, credentials are // obtained using |*username| and |*password|. If |username| and |password| - // are NULL, the default credentials are used instead. + // are both NULL, the credentials for the currently logged in user are used + // instead. int GenerateAuthToken(const std::wstring* username, const std::wstring* password, const std::wstring& spn, - const HttpRequestInfo* request, std::string* auth_token); private: diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index ff9a04f..ea30552 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -665,17 +665,6 @@ int HttpNetworkTransaction::DoLoop(int result) { rv = DoReadHeadersComplete(rv); net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL); break; - case STATE_RESOLVE_CANONICAL_NAME: - DCHECK_EQ(OK, rv); - net_log_.BeginEvent( - NetLog::TYPE_HTTP_TRANSACTION_RESOLVE_CANONICAL_NAME, NULL); - rv = DoResolveCanonicalName(); - break; - case STATE_RESOLVE_CANONICAL_NAME_COMPLETE: - rv = DoResolveCanonicalNameComplete(rv); - net_log_.EndEvent( - NetLog::TYPE_HTTP_TRANSACTION_RESOLVE_CANONICAL_NAME, NULL); - break; case STATE_READ_BODY: DCHECK_EQ(OK, rv); net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL); @@ -1394,22 +1383,6 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { return OK; } -int HttpNetworkTransaction::DoResolveCanonicalName() { - DCHECK(auth_controllers_[pending_auth_target_].get()); - next_state_ = STATE_RESOLVE_CANONICAL_NAME_COMPLETE; - return auth_controllers_[pending_auth_target_]->ResolveCanonicalName( - &io_callback_); -} - -int HttpNetworkTransaction::DoResolveCanonicalNameComplete(int result) { - // The STATE_RESOLVE_CANONICAL_NAME state ends the Start sequence when the - // canonical name of the server needs to be determined. Normally - // DoReadHeadersComplete completes the sequence. The next state is - // intentionally not set as it should be STATE_NONE; - DCHECK_EQ(STATE_NONE, next_state_); - return result; -} - int HttpNetworkTransaction::DoReadBody() { DCHECK(read_buf_); DCHECK_GT(read_buf_len_, 0); @@ -1581,7 +1554,7 @@ int HttpNetworkTransaction::DoSpdyReadBodyComplete(int result) { read_buf_len_ = 0; if (result <= 0) - spdy_http_stream_.reset() ; + spdy_http_stream_.reset(); return result; } @@ -2007,11 +1980,6 @@ int HttpNetworkTransaction::HandleAuthChallenge(bool establishing_tunnel) { if (auth_info.get()) response_.auth_challenge = auth_info; - if (rv == ERR_AUTH_NEEDS_CANONICAL_NAME) { - next_state_ = STATE_RESOLVE_CANONICAL_NAME; - rv = OK; - } - return rv; } @@ -2078,8 +2046,6 @@ std::string HttpNetworkTransaction::DescribeState(State state) { STATE_CASE(STATE_SEND_REQUEST_COMPLETE); STATE_CASE(STATE_READ_HEADERS); STATE_CASE(STATE_READ_HEADERS_COMPLETE); - STATE_CASE(STATE_RESOLVE_CANONICAL_NAME); - STATE_CASE(STATE_RESOLVE_CANONICAL_NAME_COMPLETE); STATE_CASE(STATE_READ_BODY); STATE_CASE(STATE_READ_BODY_COMPLETE); STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART); diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h index 429c08a..2a33663 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h @@ -12,7 +12,6 @@ #include "base/scoped_ptr.h" #include "base/time.h" #include "net/base/address_list.h" -#include "net/base/host_resolver.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/load_states.h" @@ -100,8 +99,6 @@ class HttpNetworkTransaction : public HttpTransaction { STATE_SEND_REQUEST_COMPLETE, STATE_READ_HEADERS, STATE_READ_HEADERS_COMPLETE, - STATE_RESOLVE_CANONICAL_NAME, - STATE_RESOLVE_CANONICAL_NAME_COMPLETE, STATE_READ_BODY, STATE_READ_BODY_COMPLETE, STATE_DRAIN_BODY_FOR_AUTH_RESTART, @@ -151,8 +148,6 @@ class HttpNetworkTransaction : public HttpTransaction { int DoSendRequestComplete(int result); int DoReadHeaders(); int DoReadHeadersComplete(int result); - int DoResolveCanonicalName(); - int DoResolveCanonicalNameComplete(int result); int DoReadBody(); int DoReadBodyComplete(int result); int DoDrainBodyForAuthRestart(); diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 498ded3..3716255 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -5444,79 +5444,6 @@ TEST_F(HttpNetworkTransactionTest, HttpNetworkTransaction::SetUseAlternateProtocols(false); } -// Tests that ResolveCanonicalName is handled correctly by the -// HttpNetworkTransaction. -TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) { - SessionDependencies session_deps; - HttpAuthHandlerMock::Factory* auth_factory( - new HttpAuthHandlerMock::Factory()); - session_deps.http_auth_handler_factory.reset(auth_factory); - - for (int i = 0; i < 2; ++i) { - HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); - std::string auth_challenge = "Mock"; - GURL origin("http://www.example.com"); - HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), - auth_challenge.end()); - auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, - origin, BoundNetLog()); - auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER); - - scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(CreateSession(&session_deps))); - - // Set up expectations for this pass of the test. Many of the EXPECT calls - // are contained inside the HttpAuthHandlerMock codebase in response to - // the expectations. - HttpAuthHandlerMock::Resolve resolve = ((i == 0) ? - HttpAuthHandlerMock::RESOLVE_SYNC : - HttpAuthHandlerMock::RESOLVE_ASYNC); - auth_handler->SetResolveExpectation(resolve); - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("http://myserver/"); - request.load_flags = 0; - - MockWrite data_writes1[] = { - MockWrite("GET / HTTP/1.1\r\n" - "Host: myserver\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - - MockRead data_reads1[] = { - MockRead("HTTP/1.1 401 Unauthorized\r\n"), - MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"), - MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), - MockRead("Content-Length: 14\r\n\r\n"), - MockRead("Unauthorized\r\n"), - }; - - StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), - data_writes1, arraysize(data_writes1)); - session_deps.socket_factory.AddSocketDataProvider(&data1); - - TestCompletionCallback callback1; - - int rv = trans->Start(&request, &callback1, BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - - rv = callback1.WaitForResult(); - EXPECT_EQ(OK, rv); - - const HttpResponseInfo* response = trans->GetResponseInfo(); - EXPECT_FALSE(response == NULL); - - // The password prompt is set after the canonical name is resolved. - // If it isn't present or is incorrect, it indicates that the scheme - // did not complete correctly. - EXPECT_FALSE(response->auth_challenge.get() == NULL); - - EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port); - EXPECT_EQ(L"", response->auth_challenge->realm); - EXPECT_EQ(L"mock", response->auth_challenge->scheme); - } -} - // GenerateAuthToken is a mighty big test. // It tests all permutation of GenerateAuthToken behavior: // - Synchronous and Asynchronous completion. @@ -5828,6 +5755,8 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) { const TestConfig& test_config = test_configs[i]; + + // Set up authentication handlers as necessary. if (test_config.proxy_auth_timing != AUTH_NONE) { HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); std::string auth_challenge = "Mock realm=proxy"; @@ -5839,7 +5768,6 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { auth_handler->SetGenerateExpectation( test_config.proxy_auth_timing == AUTH_ASYNC, test_config.proxy_auth_rv); - auth_handler->SetResolveExpectation(HttpAuthHandlerMock::RESOLVE_SKIP); auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY); } if (test_config.server_auth_timing != AUTH_NONE) { @@ -5853,7 +5781,6 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { auth_handler->SetGenerateExpectation( test_config.server_auth_timing == AUTH_ASYNC, test_config.server_auth_rv); - auth_handler->SetResolveExpectation(HttpAuthHandlerMock::RESOLVE_SKIP); auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER); } if (test_config.proxy_url) { @@ -6145,4 +6072,5 @@ TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) { HttpNetworkTransaction::SetNextProtos(""); HttpNetworkTransaction::SetUseAlternateProtocols(false); } + } // namespace net diff --git a/net/http/mock_sspi_library_win.cc b/net/http/mock_sspi_library_win.cc index de8f828..d0dae51 100644 --- a/net/http/mock_sspi_library_win.cc +++ b/net/http/mock_sspi_library_win.cc @@ -26,8 +26,9 @@ SECURITY_STATUS MockSSPILibrary::AcquireCredentialsHandle( void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { - ADD_FAILURE(); - return ERROR_CALL_NOT_IMPLEMENTED; + // Fill in phCredential with arbitrary value. + phCredential->dwLower = phCredential->dwUpper = ((ULONG_PTR) ((INT_PTR)0)); + return SEC_E_OK; } SECURITY_STATUS MockSSPILibrary::InitializeSecurityContext( @@ -43,8 +44,13 @@ SECURITY_STATUS MockSSPILibrary::InitializeSecurityContext( PSecBufferDesc pOutput, unsigned long* contextAttr, PTimeStamp ptsExpiry) { - ADD_FAILURE(); - return ERROR_CALL_NOT_IMPLEMENTED; + // Fill in the outbound buffer with garbage data. + PSecBuffer out_buffer = pOutput->pBuffers; + out_buffer->cbBuffer = 2; + uint8* buf = reinterpret_cast<uint8 *>(out_buffer->pvBuffer); + buf[0] = 0xAB; + buf[1] = 0xBA; + return SEC_E_OK; } SECURITY_STATUS MockSSPILibrary::QuerySecurityPackageInfo( @@ -62,8 +68,10 @@ SECURITY_STATUS MockSSPILibrary::QuerySecurityPackageInfo( SECURITY_STATUS MockSSPILibrary::FreeCredentialsHandle( PCredHandle phCredential) { - ADD_FAILURE(); - return ERROR_CALL_NOT_IMPLEMENTED; + EXPECT_TRUE(phCredential->dwLower == ((ULONG_PTR) ((INT_PTR) 0))); + EXPECT_TRUE(phCredential->dwLower == ((ULONG_PTR) ((INT_PTR) 0))); + SecInvalidateHandle(phCredential); + return SEC_E_OK; } SECURITY_STATUS MockSSPILibrary::DeleteSecurityContext(PCtxtHandle phContext) { diff --git a/net/net.gyp b/net/net.gyp index b5cfd93..96aeb1f 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -342,8 +342,7 @@ 'http/http_auth_handler_factory.cc', 'http/http_auth_handler_factory.h', 'http/http_auth_handler_negotiate.h', - 'http/http_auth_handler_negotiate_posix.cc', - 'http/http_auth_handler_negotiate_win.cc', + 'http/http_auth_handler_negotiate.cc', 'http/http_auth_handler_ntlm.cc', 'http/http_auth_handler_ntlm.h', 'http/http_auth_handler_ntlm_portable.cc', |