summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorcbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-01 18:12:26 +0000
committercbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-01 18:12:26 +0000
commit65d3438acf8e8e4f525c23b00c46b7a1330b00ee (patch)
tree83a0c6c4299aaa901feea780b6ef6f2ec2f3c251 /net
parent5526773cbfbb6b9f3ef4fbec96bebc5014cf78ff (diff)
downloadchromium_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.h3
-rw-r--r--net/base/net_log_event_type_list.h4
-rw-r--r--net/http/http_auth_controller.cc11
-rw-r--r--net/http/http_auth_controller.h7
-rw-r--r--net/http/http_auth_gssapi_posix.cc1
-rw-r--r--net/http/http_auth_gssapi_posix.h1
-rw-r--r--net/http/http_auth_handler.cc7
-rw-r--r--net/http/http_auth_handler.h12
-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.h57
-rw-r--r--net/http/http_auth_handler_negotiate_posix.cc211
-rw-r--r--net/http/http_auth_handler_negotiate_unittest.cc81
-rw-r--r--net/http/http_auth_handler_ntlm.cc1
-rw-r--r--net/http/http_auth_sspi_win.cc19
-rw-r--r--net/http/http_auth_sspi_win.h15
-rw-r--r--net/http/http_network_transaction.cc36
-rw-r--r--net/http/http_network_transaction.h5
-rw-r--r--net/http/http_network_transaction_unittest.cc78
-rw-r--r--net/http/mock_sspi_library_win.cc20
-rw-r--r--net/net.gyp3
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',