diff options
author | nick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-02 22:00:19 +0000 |
---|---|---|
committer | nick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-02 22:00:19 +0000 |
commit | 4dfabfcfe11281e15bc2a37dad0a73de2ec4b5aa (patch) | |
tree | 8888d228d02d867cd84f7aeff5f5e15ba5327e43 /net | |
parent | fae7669f438f42169f9da35406d9b4cef6b541fd (diff) | |
download | chromium_src-4dfabfcfe11281e15bc2a37dad0a73de2ec4b5aa.zip chromium_src-4dfabfcfe11281e15bc2a37dad0a73de2ec4b5aa.tar.gz chromium_src-4dfabfcfe11281e15bc2a37dad0a73de2ec4b5aa.tar.bz2 |
Revert 54528 - Digest authentication uses a uri field to prevent replay attacks.
[Reason for revert: we want to revert r54505, this was a dependent change. cbentzel agrees to reland.]
When authenticating to an HTTP proxy to establish a secure tunnel (via CONNECT), the uri should be the hostname of the server and the destination port, such as "www.example.com:443". When authenticating to an HTTP proxy for a non-secure content, the uri should be the path at the server, i.e. "/index.html".
If the site we are trying to connect to previously advertised "Alternate-Protocol: 443:spdy-npn/1" a request to "http://www.example.com" will be attempted on a secure port.
However, the URL passed into the digest authenticator was an unsecure one, and it decided to have a uri in the form "/index.html" rather than the correct "www.example.com:443". This causes persistent failure with the password and many password prompts.
BUG=49865,50822
TEST=Run with --use-spdy=npn, force connection through a digest authenticating proxy, and browse a site which advertises Alternate-Protocol through http URLs.
Review URL: http://codereview.chromium.org/3028021
TBR=cbentzel@chromium.org
Review URL: http://codereview.chromium.org/3091001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54614 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_auth_handler_mock.cc | 16 | ||||
-rw-r--r-- | net/http/http_auth_handler_mock.h | 15 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 39 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 142 | ||||
-rw-r--r-- | net/socket/socket_test_util.cc | 1 |
5 files changed, 13 insertions, 200 deletions
diff --git a/net/http/http_auth_handler_mock.cc b/net/http/http_auth_handler_mock.cc index 9f0011d..983105b 100644 --- a/net/http/http_auth_handler_mock.cc +++ b/net/http/http_auth_handler_mock.cc @@ -6,7 +6,6 @@ #include "base/message_loop.h" #include "net/base/net_errors.h" -#include "net/http/http_request_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -83,7 +82,6 @@ int HttpAuthHandlerMock::GenerateAuthTokenImpl(const string16* username, CompletionCallback* callback, std::string* auth_token) { first_round_ = false; - request_url_ = request->url; if (generate_async_) { EXPECT_TRUE(user_callback_ == NULL); EXPECT_TRUE(auth_token_ == NULL); @@ -120,14 +118,6 @@ void HttpAuthHandlerMock::OnGenerateAuthToken() { callback->Run(generate_rv_); } -HttpAuthHandlerMock::Factory::Factory() - : do_init_from_challenge_(false) { - // TODO(cbentzel): Default do_init_from_challenge_ to true. -} - -HttpAuthHandlerMock::Factory::~Factory() { -} - void HttpAuthHandlerMock::Factory::set_mock_handler( HttpAuthHandler* handler, HttpAuth::Target target) { EXPECT_TRUE(handlers_[target].get() == NULL); @@ -144,11 +134,7 @@ int HttpAuthHandlerMock::Factory::CreateAuthHandler( scoped_ptr<HttpAuthHandler>* handler) { if (!handlers_[target].get()) return ERR_UNEXPECTED; - scoped_ptr<HttpAuthHandler> tmp_handler(handlers_[target].release()); - if (do_init_from_challenge_ && - !tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) - return ERR_INVALID_RESPONSE; - handler->swap(tmp_handler); + handler->swap(handlers_[target]); return OK; } diff --git a/net/http/http_auth_handler_mock.h b/net/http/http_auth_handler_mock.h index a6b0d48..f9a676c 100644 --- a/net/http/http_auth_handler_mock.h +++ b/net/http/http_auth_handler_mock.h @@ -10,7 +10,6 @@ #include "base/string16.h" #include "base/task.h" -#include "googleurl/src/gurl.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" @@ -47,23 +46,15 @@ class HttpAuthHandlerMock : public HttpAuthHandler { connection_based_ = connection_based; } - const GURL& request_url() const { - return request_url_; - } - // The Factory class simply returns the same handler each time // CreateAuthHandler is called. class Factory : public HttpAuthHandlerFactory { public: - Factory(); - virtual ~Factory(); + Factory() {} + virtual ~Factory() {} void set_mock_handler(HttpAuthHandler* handler, HttpAuth::Target target); - void set_do_init_from_challenge(bool do_init_from_challenge) { - do_init_from_challenge_ = do_init_from_challenge; - } - virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge, HttpAuth::Target target, const GURL& origin, @@ -74,7 +65,6 @@ class HttpAuthHandlerMock : public HttpAuthHandler { private: scoped_ptr<HttpAuthHandler> handlers_[HttpAuth::AUTH_NUM_TARGETS]; - bool do_init_from_challenge_; }; protected: @@ -99,7 +89,6 @@ class HttpAuthHandlerMock : public HttpAuthHandler { std::string* auth_token_; bool first_round_; bool connection_based_; - GURL request_url_; }; } // namespace net diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 966eccb..bb17bcb 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -194,17 +194,6 @@ void ProcessAlternateProtocol(const HttpResponseHeaders& headers, alternate_protocols->SetAlternateProtocolFor(host_port, port, protocol); } -GURL UpgradeUrlToHttps(const GURL& original_url) { - GURL::Replacements replacements; - // new_sheme and new_port need to be in scope here because GURL::Replacements - // references the memory contained by them directly. - const std::string new_scheme = "https"; - const std::string new_port = IntToString(443); - replacements.SetSchemeStr(new_scheme); - replacements.SetPortStr(new_port); - return original_url.ReplaceComponents(replacements); -} - } // namespace //----------------------------------------------------------------------------- @@ -693,7 +682,15 @@ int HttpNetworkTransaction::DoResolveProxy() { endpoint_.set_port(alternate.port); alternate_protocol_ = alternate.protocol; alternate_protocol_mode_ = kUsingAlternateProtocol; - alternate_endpoint_url = UpgradeUrlToHttps(*curr_endpoint_url); + + url_canon::Replacements<char> replacements; + replacements.SetScheme("https", + url_parse::Component(0, strlen("https"))); + const std::string port_str = base::IntToString(endpoint_.port()); + replacements.SetPort(port_str.c_str(), + url_parse::Component(0, port_str.size())); + alternate_endpoint_url = + curr_endpoint_url->ReplaceComponents(replacements); curr_endpoint_url = &alternate_endpoint_url; } } @@ -783,25 +780,9 @@ int HttpNetworkTransaction::DoInitConnection() { request_->referrer, disable_resolver_cache); if (proxy_info_.is_http()) { - GURL authentication_url = request_->url; - if (using_ssl_) { - if (!authentication_url.SchemeIs("https")) { - // If a proxy tunnel connection needs to be established due to - // an Alternate-Protocol, the URL needs to be changed to indicate - // https or digest authentication attempts will fail. - // For example, suppose the initial request was for - // "http://www.example.com/index.html". If this is an SSL - // upgrade due to alternate protocol, the digest authorization - // should have a uri="www.example.com:443" field rather than a - // "/index.html" entry, even though the original request URL has not - // changed. - authentication_url = UpgradeUrlToHttps(authentication_url); - } - } establishing_tunnel_ = using_ssl_; http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, - authentication_url, - endpoint_, + request_->url, endpoint_, session_, using_ssl_); } else { DCHECK(proxy_info_.is_socks()); diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 4e0d354..d6e5779 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -6373,146 +6373,4 @@ TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) { HttpNetworkTransaction::SetUseAlternateProtocols(false); } -TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { - // This test ensures that the URL passed into the proxy is upgraded - // to https when doing an Alternate Protocol upgrade. - HttpNetworkTransaction::SetUseAlternateProtocols(true); - HttpNetworkTransaction::SetNextProtos( - "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy"); - - SessionDependencies session_deps(CreateFixedProxyService("myproxy:70")); - HttpAuthHandlerMock::Factory* auth_factory = - new HttpAuthHandlerMock::Factory(); - HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock(); - auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY); - auth_factory->set_do_init_from_challenge(true); - session_deps.http_auth_handler_factory.reset(auth_factory); - - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("http://www.google.com"); - request.load_flags = 0; - - // First round goes unauthenticated through the proxy. - MockWrite data_writes_1[] = { - MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Proxy-Connection: keep-alive\r\n" - "\r\n"), - }; - MockRead data_reads_1[] = { - MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), - MockRead("HTTP/1.1 200 OK\r\n" - "Alternate-Protocol: 443:npn-spdy/2\r\n" - "Proxy-Connection: close\r\n" - "\r\n"), - }; - StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1), - data_writes_1, arraysize(data_writes_1)); - - // Second round tries to tunnel to www.google.com due to the - // Alternate-Protocol announcement in the first round. It fails due - // to a proxy authentication challenge. - // After the failure, a tunnel is established to www.google.com using - // Proxy-Authorization headers. There is then a SPDY request round. - // - // NOTE: Despite the "Proxy-Connection: Close", these are done on the - // same MockTCPClientSocket since the underlying HttpNetworkClientSocket - // does a Disconnect and Connect on the same socket, rather than trying - // to obtain a new one. - // - // NOTE: Originally, the proxy response to the second CONNECT request - // simply returned another 407 so the unit test could skip the SSL connection - // establishment and SPDY framing issues. Alas, the - // retry-http-when-alternate-protocol fails logic kicks in, which was more - // complicated to set up expectations for than the SPDY session. - - scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); - scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); - - MockWrite data_writes_2[] = { - // First connection attempt without Proxy-Authorization. - MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Proxy-Connection: keep-alive\r\n" - "\r\n"), - - // Second connection attempt with Proxy-Authorization. - MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" - "Host: www.google.com\r\n" - "Proxy-Connection: keep-alive\r\n" - "Proxy-Authorization: auth_token\r\n" - "\r\n"), - - // SPDY request - CreateMockWrite(*req), - }; - const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n" - "Proxy-Authenticate: Mock\r\n" - "Proxy-Connection: close\r\n" - "\r\n"); - const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; - MockRead data_reads_2[] = { - // First connection attempt fails - MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1), - MockRead(true, kRejectConnectResponse, - arraysize(kRejectConnectResponse) - 1, 1), - - // Second connection attempt passes - MockRead(true, kAcceptConnectResponse, - arraysize(kAcceptConnectResponse) -1, 4), - - // SPDY response - CreateMockRead(*resp.get(), 6), - CreateMockRead(*data.get(), 6), - MockRead(true, 0, 0, 6), - }; - scoped_refptr<OrderedSocketData> data_2( - new OrderedSocketData(data_reads_2, arraysize(data_reads_2), - data_writes_2, arraysize(data_writes_2))); - - SSLSocketDataProvider ssl(true, OK); - ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; - ssl.next_proto = "spdy/2"; - ssl.was_npn_negotiated = true; - - session_deps.socket_factory.AddSocketDataProvider(&data_1); - session_deps.socket_factory.AddSocketDataProvider(data_2.get()); - session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); - - // First round should work and provide the Alternate-Protocol state. - TestCompletionCallback callback_1; - scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session)); - int rv = trans_1->Start(&request, &callback_1, BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback_1.WaitForResult()); - - // Second round should attempt a tunnel connect and get an auth challenge. - TestCompletionCallback callback_2; - scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session)); - rv = trans_2->Start(&request, &callback_2, BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback_2.WaitForResult()); - const HttpResponseInfo* response = trans_2->GetResponseInfo(); - ASSERT_FALSE(response == NULL); - ASSERT_FALSE(response->auth_challenge.get() == NULL); - - // Restart with auth. Tunnel should work and response received. - TestCompletionCallback callback_3; - rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback_3.WaitForResult()); - - // After all that work, these two lines (or actually, just the scheme) are - // what this test is all about. Make sure it happens correctly. - const GURL& request_url = auth_handler->request_url(); - EXPECT_EQ("https", request_url.scheme()); - EXPECT_EQ("www.google.com", request_url.host()); - - HttpNetworkTransaction::SetNextProtos(""); - HttpNetworkTransaction::SetUseAlternateProtocols(false); -} - } // namespace net diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 142a39e..ce7f3fc06 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc @@ -187,7 +187,6 @@ int MockTCPClientSocket::Connect(net::CompletionCallback* callback) { if (connected_) return net::OK; connected_ = true; - peer_closed_connection_ = false; if (data_->connect_data().async) { RunCallbackAsync(callback, data_->connect_data().result); return net::ERR_IO_PENDING; |