diff options
author | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-15 21:51:14 +0000 |
---|---|---|
committer | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-15 21:51:14 +0000 |
commit | c871bce9392dbf053c1cc73e22a2ef6f811fa412 (patch) | |
tree | 5066b447c29b9266d9c4760c5b5de1323f5d44cc | |
parent | c4bfb4f11dba0d48ae808c2b3fd023ed9f7a029b (diff) | |
download | chromium_src-c871bce9392dbf053c1cc73e22a2ef6f811fa412.zip chromium_src-c871bce9392dbf053c1cc73e22a2ef6f811fa412.tar.gz chromium_src-c871bce9392dbf053c1cc73e22a2ef6f811fa412.tar.bz2 |
On multi-round authentication schemes, the info_ field in the HttpAuthController should be cleared (the user should only be prompted for username/password on the first round).
BUG=48752
TEST=net_unittests --gtest_filter="*MultiRoundAuth*"
Review URL: http://codereview.chromium.org/2941006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52550 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/http/http_auth_controller.cc | 2 | ||||
-rw-r--r-- | net/http/http_auth_handler_mock.cc | 7 | ||||
-rw-r--r-- | net/http/http_auth_handler_mock.h | 11 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 104 |
4 files changed, 122 insertions, 2 deletions
diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc index 0392741..eaf958a 100644 --- a/net/http/http_auth_controller.cc +++ b/net/http/http_auth_controller.cc @@ -195,6 +195,8 @@ int HttpAuthController::HandleAuthChallenge( // We have exhausted all identity possibilities, all we can do now is // pass the challenge information back to the client. PopulateAuthChallenge(); + } else { + auth_info_ = NULL; } return OK; diff --git a/net/http/http_auth_handler_mock.cc b/net/http/http_auth_handler_mock.cc index 4d034a8..09a03561 100644 --- a/net/http/http_auth_handler_mock.cc +++ b/net/http/http_auth_handler_mock.cc @@ -14,7 +14,9 @@ HttpAuthHandlerMock::HttpAuthHandlerMock() : resolve_(RESOLVE_INIT), user_callback_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), generate_async_(false), generate_rv_(OK), - auth_token_(NULL) { + auth_token_(NULL), + first_round_(true), + connection_based_(false) { } HttpAuthHandlerMock::~HttpAuthHandlerMock() { @@ -70,7 +72,7 @@ void HttpAuthHandlerMock::SetGenerateExpectation(bool async, int rv) { bool HttpAuthHandlerMock::Init(HttpAuth::ChallengeTokenizer* challenge) { scheme_ = "mock"; score_ = 1; - properties_ = 0; + properties_ = connection_based_ ? IS_CONNECTION_BASED : 0; return true; } @@ -79,6 +81,7 @@ int HttpAuthHandlerMock::GenerateAuthTokenImpl(const std::wstring* username, const HttpRequestInfo* request, CompletionCallback* callback, std::string* auth_token) { + first_round_ = false; if (generate_async_) { EXPECT_TRUE(user_callback_ == NULL); EXPECT_TRUE(auth_token_ == NULL); diff --git a/net/http/http_auth_handler_mock.h b/net/http/http_auth_handler_mock.h index 4a7fa22..a0ef4f0 100644 --- a/net/http/http_auth_handler_mock.h +++ b/net/http/http_auth_handler_mock.h @@ -5,6 +5,8 @@ #ifndef NET_HTTP_HTTP_AUTH_HANDLER_MOCK_H_ #define NET_HTTP_HTTP_AUTH_HANDLER_MOCK_H_ +#include <string> + #include "base/task.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" @@ -33,8 +35,15 @@ class HttpAuthHandlerMock : public HttpAuthHandler { virtual int ResolveCanonicalName(HostResolver* host_resolver, CompletionCallback* callback); + virtual bool NeedsIdentity() { return first_round_; } + virtual bool IsFinalRound() { return false; } + void SetGenerateExpectation(bool async, int rv); + void set_connection_based(bool connection_based) { + connection_based_ = connection_based; + } + // The Factory class simply returns the same handler each time // CreateAuthHandler is called. class Factory : public HttpAuthHandlerFactory { @@ -76,6 +85,8 @@ class HttpAuthHandlerMock : public HttpAuthHandler { bool generate_async_; int generate_rv_; std::string* auth_token_; + bool first_round_; + bool connection_based_; }; } // namespace net diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index c21634f..867c9583 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -5930,6 +5930,110 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { session->FlushSocketPools(); } +TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) { + // Do multi-round authentication and make sure it works correctly. + SessionDependencies session_deps; + HttpAuthHandlerMock::Factory* auth_factory( + new HttpAuthHandlerMock::Factory()); + session_deps.http_auth_handler_factory.reset(auth_factory); + session_deps.proxy_service = ProxyService::CreateNull(); + session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1"); + session_deps.host_resolver->set_synchronous_mode(true); + + HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); + auth_handler->set_connection_based(true); + std::string auth_challenge = "Mock realm=server"; + 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_refptr<HttpNetworkSession> session = CreateSession(&session_deps); + scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); + + int rv = OK; + const HttpResponseInfo* response = NULL; + HttpRequestInfo request; + request.method = "GET"; + request.url = origin; + request.load_flags = 0; + TestCompletionCallback callback; + + const MockWrite kGet( + "GET / HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "Connection: keep-alive\r\n\r\n"); + const MockWrite kGetAuth( + "GET / HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "Connection: keep-alive\r\n" + "Authorization: auth_token\r\n\r\n"); + + const MockRead kServerChallenge( + "HTTP/1.1 401 Unauthorized\r\n" + "WWW-Authenticate: Mock realm=server\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Content-Length: 14\r\n\r\n" + "Unauthorized\r\n"); + const MockRead kSuccess( + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Content-Length: 3\r\n\r\n" + "Yes"); + + MockWrite writes[] = { + // First round + kGet, + // Second round + kGetAuth, + // Third round + kGetAuth, + }; + MockRead reads[] = { + // First round + kServerChallenge, + // Second round + kServerChallenge, + // Third round + kSuccess, + }; + StaticSocketDataProvider data_provider(reads, arraysize(reads), + writes, arraysize(writes)); + session_deps.socket_factory.AddSocketDataProvider(&data_provider); + + // First round + auth_handler->SetGenerateExpectation(false, OK); + rv = trans->Start(&request, &callback, BoundNetLog()); + if (rv == ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + response = trans->GetResponseInfo(); + ASSERT_FALSE(response == NULL); + EXPECT_FALSE(response->auth_challenge.get() == NULL); + + // Second round + auth_handler->SetGenerateExpectation(false, OK); + rv = trans->RestartWithAuth(L"foo", L"bar", &callback); + if (rv == ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + response = trans->GetResponseInfo(); + ASSERT_FALSE(response == NULL); + EXPECT_TRUE(response->auth_challenge.get() == NULL); + + // Third round + auth_handler->SetGenerateExpectation(false, OK); + rv = trans->RestartWithAuth(L"", L"", &callback); + if (rv == ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + response = trans->GetResponseInfo(); + ASSERT_FALSE(response == NULL); + EXPECT_TRUE(response->auth_challenge.get() == NULL); +} + class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider { public: explicit TLSDecompressionFailureSocketDataProvider(bool fail_all) |