summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-15 21:51:14 +0000
committercbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-15 21:51:14 +0000
commitc871bce9392dbf053c1cc73e22a2ef6f811fa412 (patch)
tree5066b447c29b9266d9c4760c5b5de1323f5d44cc
parentc4bfb4f11dba0d48ae808c2b3fd023ed9f7a029b (diff)
downloadchromium_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.cc2
-rw-r--r--net/http/http_auth_handler_mock.cc7
-rw-r--r--net/http/http_auth_handler_mock.h11
-rw-r--r--net/http/http_network_transaction_unittest.cc104
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)