diff options
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_network_session.cc | 14 | ||||
-rw-r--r-- | net/http/http_network_session.h | 4 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 14 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 290 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool.cc | 121 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool.h | 40 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool_unittest.cc | 96 | ||||
-rw-r--r-- | net/http/http_stream_request.cc | 88 | ||||
-rw-r--r-- | net/http/http_stream_request.h | 13 |
9 files changed, 578 insertions, 102 deletions
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index d85a4ef..93340ef 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc @@ -46,6 +46,10 @@ HttpNetworkSession::HttpNetworkSession( tcp_for_http_proxy_pool_histograms_( new ClientSocketPoolHistograms("TCPforHTTPProxy")), http_proxy_pool_histograms_(new ClientSocketPoolHistograms("HTTPProxy")), + tcp_for_https_proxy_pool_histograms_( + new ClientSocketPoolHistograms("TCPforHTTPSProxy")), + ssl_for_https_proxy_pool_histograms_( + new ClientSocketPoolHistograms("SSLforHTTPSProxy")), tcp_for_socks_pool_histograms_( new ClientSocketPoolHistograms("TCPforSOCKS")), socks_pool_histograms_(new ClientSocketPoolHistograms("SOCK")), @@ -91,6 +95,16 @@ HttpNetworkSession::GetSocketPoolForHTTPProxy(const HostPortPair& http_proxy) { g_max_sockets_per_proxy_server, g_max_sockets_per_group, tcp_for_http_proxy_pool_histograms_, host_resolver_, socket_factory_, net_log_), + new SSLClientSocketPool( + g_max_sockets_per_proxy_server, g_max_sockets_per_group, + ssl_for_https_proxy_pool_histograms_, host_resolver_, + socket_factory_, + new TCPClientSocketPool( + g_max_sockets_per_proxy_server, + g_max_sockets_per_group, + tcp_for_https_proxy_pool_histograms_, host_resolver_, + socket_factory_, net_log_), + NULL, NULL, net_log_), net_log_))); return ret.first->second; diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index ae1738e..9efcb9f 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -156,6 +156,10 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, scoped_refptr<ClientSocketPoolHistograms> tcp_pool_histograms_; scoped_refptr<ClientSocketPoolHistograms> tcp_for_http_proxy_pool_histograms_; scoped_refptr<ClientSocketPoolHistograms> http_proxy_pool_histograms_; + scoped_refptr<ClientSocketPoolHistograms> + tcp_for_https_proxy_pool_histograms_; + scoped_refptr<ClientSocketPoolHistograms> + ssl_for_https_proxy_pool_histograms_; scoped_refptr<ClientSocketPoolHistograms> tcp_for_socks_pool_histograms_; scoped_refptr<ClientSocketPoolHistograms> socks_pool_histograms_; scoped_refptr<ClientSocketPoolHistograms> ssl_pool_histograms_; diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 1ff166c..bf3c4b9 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -322,7 +322,7 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len, // because an active network attacker can already control HTTP sessions. // We reach this case when the user cancels a 407 proxy auth prompt. // See http://crbug.com/8473. - DCHECK(proxy_info_.is_http()); + DCHECK(proxy_info_.is_http() || proxy_info_.is_https()); DCHECK_EQ(headers->response_code(), 407); LOG(WARNING) << "Blocked proxy response with status " << headers->response_code() << " to CONNECT request for " @@ -658,7 +658,8 @@ int HttpNetworkTransaction::DoSendRequest() { HttpRequestHeaders request_headers; BuildRequestHeaders(request_, authorization_headers, request_body, - !is_https_request() && proxy_info_.is_http(), + !is_https_request() && (proxy_info_.is_http() || + proxy_info_.is_https()), &request_line, &request_headers); if (session_->network_delegate()) @@ -1093,7 +1094,8 @@ void HttpNetworkTransaction::ResetConnectionAndRequestForResend() { } bool HttpNetworkTransaction::ShouldApplyProxyAuth() const { - return !is_https_request() && proxy_info_.is_http(); + return !is_https_request() && + (proxy_info_.is_https() || proxy_info_.is_http()); } bool HttpNetworkTransaction::ShouldApplyServerAuth() const { @@ -1134,13 +1136,15 @@ bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const { GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const { switch (target) { - case HttpAuth::AUTH_PROXY: + case HttpAuth::AUTH_PROXY: { if (!proxy_info_.proxy_server().is_valid() || proxy_info_.proxy_server().is_direct()) { return GURL(); // There is no proxy server. } - return GURL("http://" + + const char* scheme = proxy_info_.is_https() ? "https://" : "http://"; + return GURL(scheme + proxy_info_.proxy_server().host_port_pair().ToString()); + } case HttpAuth::AUTH_SERVER: return request_->url; default: diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 5e07b88..81c26fa 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -327,6 +327,12 @@ CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool( : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {} template<> +CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool( + HttpNetworkSession* session) + : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, + NULL, NULL) {} + +template<> CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( HttpNetworkSession* session) : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL, @@ -1661,6 +1667,153 @@ TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) { EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); } + +// Test a simple get through an HTTPS Proxy. +TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) { + // Configure against https proxy server "proxy:70". + SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70")); + CapturingBoundNetLog log(CapturingNetLog::kUnbounded); + session_deps.net_log = log.bound().net_log(); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + + scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.google.com/"); + + // Since we have proxy, should use full url + MockWrite data_writes1[] = { + 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_reads1[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead("Content-Length: 100\r\n\r\n"), + MockRead(false, OK), + }; + + StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), + data_writes1, arraysize(data_writes1)); + session_deps.socket_factory.AddSocketDataProvider(&data1); + SSLSocketDataProvider ssl(true, OK); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + + TestCompletionCallback callback1; + + int rv = trans->Start(&request, &callback1, log.bound()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback1.WaitForResult(); + EXPECT_EQ(OK, rv); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_FALSE(response == NULL); + + EXPECT_TRUE(response->headers->IsKeepAlive()); + EXPECT_EQ(200, response->headers->response_code()); + EXPECT_EQ(100, response->headers->GetContentLength()); + EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + + // The password prompt info should not be set. + EXPECT_TRUE(response->auth_challenge.get() == NULL); +} + +// Test the challenge-response-retry sequence through an HTTPS Proxy +TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) { + // Configure against https proxy server "proxy:70". + SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70")); + CapturingBoundNetLog log(CapturingNetLog::kUnbounded); + session_deps.net_log = log.bound().net_log(); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + + scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.google.com/"); + // when the no authentication data flag is set. + request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + + // Since we have proxy, should use full url + MockWrite data_writes1[] = { + 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"), + + // After calling trans->RestartWithAuth(), this is the request we should + // be issuing -- the final header line contains the credentials. + MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Proxy-Connection: keep-alive\r\n" + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), + }; + + // The proxy responds to the GET with a 407, using a persistent + // connection. + MockRead data_reads1[] = { + // No credentials. + MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), + MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), + MockRead("Proxy-Connection: keep-alive\r\n"), + MockRead("Content-Length: 0\r\n\r\n"), + + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead("Content-Length: 100\r\n\r\n"), + MockRead(false, OK), + }; + + StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), + data_writes1, arraysize(data_writes1)); + session_deps.socket_factory.AddSocketDataProvider(&data1); + SSLSocketDataProvider ssl(true, OK); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + + TestCompletionCallback callback1; + + int rv = trans->Start(&request, &callback1, log.bound()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback1.WaitForResult(); + EXPECT_EQ(OK, rv); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_FALSE(response == NULL); + + EXPECT_EQ(407, response->headers->response_code()); + EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + + // The password prompt info should have been set in response->auth_challenge. + ASSERT_FALSE(response->auth_challenge.get() == NULL); + + EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port); + EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); + EXPECT_EQ(L"basic", response->auth_challenge->scheme); + + TestCompletionCallback callback2; + + rv = trans->RestartWithAuth(kFoo, kBar, &callback2); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback2.WaitForResult(); + EXPECT_EQ(OK, rv); + + response = trans->GetResponseInfo(); + ASSERT_FALSE(response == NULL); + + EXPECT_TRUE(response->headers->IsKeepAlive()); + EXPECT_EQ(200, response->headers->response_code()); + EXPECT_EQ(100, response->headers->GetContentLength()); + EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + + // The password prompt info should not be set. + EXPECT_TRUE(response->auth_challenge.get() == NULL); +} + void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus( const MockRead& status, int expected_status) { // Configure against proxy server "myproxy:70". @@ -3691,6 +3844,143 @@ TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) { } } + +// Test HTTPS connections to a site, going through an HTTPS proxy +TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) { + SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70")); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("https://www.google.com/"); + request.load_flags = 0; + + MockWrite data_writes[] = { + 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"), + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Connection: keep-alive\r\n\r\n"), + }; + + MockRead data_reads[] = { + MockRead("HTTP/1.0 200 Connected\r\n\r\n"), + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead("Content-Length: 100\r\n\r\n"), + MockRead(false, OK), + }; + + StaticSocketDataProvider data(data_reads, arraysize(data_reads), + data_writes, arraysize(data_writes)); + SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy + SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel + + session_deps.socket_factory.AddSocketDataProvider(&data); + session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl); + session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl); + + TestCompletionCallback callback; + + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + int rv = trans->Start(&request, &callback, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + const HttpResponseInfo* response = trans->GetResponseInfo(); + + ASSERT_FALSE(response == NULL); + + EXPECT_TRUE(response->headers->IsKeepAlive()); + EXPECT_EQ(200, response->headers->response_code()); + EXPECT_EQ(100, response->headers->GetContentLength()); + EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); +} + +// Test HTTPS connections to a site with a bad certificate, going through an +// HTTPS proxy +TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) { + SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70")); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("https://www.google.com/"); + request.load_flags = 0; + + // Attempt to fetch the URL from a server with a bad cert + MockWrite bad_cert_writes[] = { + 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"), + }; + + MockRead bad_cert_reads[] = { + MockRead("HTTP/1.0 200 Connected\r\n\r\n"), + MockRead(false, OK) + }; + + // Attempt to fetch the URL with a good cert + MockWrite good_data_writes[] = { + 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"), + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Connection: keep-alive\r\n\r\n"), + }; + + MockRead good_cert_reads[] = { + MockRead("HTTP/1.0 200 Connected\r\n\r\n"), + MockRead("HTTP/1.0 200 OK\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead("Content-Length: 100\r\n\r\n"), + MockRead(false, OK), + }; + + StaticSocketDataProvider ssl_bad_certificate( + bad_cert_reads, arraysize(bad_cert_reads), + bad_cert_writes, arraysize(bad_cert_writes)); + StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads), + good_data_writes, arraysize(good_data_writes)); + SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID); + SSLSocketDataProvider ssl(true, OK); + + // SSL to the proxy, then CONNECT request, then SSL with bad certificate + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad); + + // SSL to the proxy, then CONNECT request, then valid SSL certificate + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + session_deps.socket_factory.AddSocketDataProvider(&data); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + + TestCompletionCallback callback; + + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + int rv = trans->Start(&request, &callback, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); + + rv = trans->RestartIgnoringLastError(&callback); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + + EXPECT_FALSE(response == NULL); + EXPECT_EQ(100, response->headers->GetContentLength()); +} + TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) { SessionDependencies session_deps; scoped_ptr<HttpTransaction> trans( diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc index ef2a640..23654d3 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc @@ -4,6 +4,8 @@ #include "net/http/http_proxy_client_socket_pool.h" +#include <algorithm> + #include "base/time.h" #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" @@ -17,18 +19,29 @@ namespace net { HttpProxySocketParams::HttpProxySocketParams( - const scoped_refptr<TCPSocketParams>& proxy_server, + const scoped_refptr<TCPSocketParams>& tcp_params, + const scoped_refptr<SSLSocketParams>& ssl_params, const GURL& request_url, const std::string& user_agent, HostPortPair endpoint, scoped_refptr<HttpNetworkSession> session, bool tunnel) - : tcp_params_(proxy_server), + : tcp_params_(tcp_params), + ssl_params_(ssl_params), request_url_(request_url), user_agent_(user_agent), endpoint_(endpoint), session_(tunnel ? session : NULL), tunnel_(tunnel) { + DCHECK((tcp_params == NULL && ssl_params != NULL) || + (tcp_params != NULL && ssl_params == NULL)); +} + +const HostResolver::RequestInfo& HttpProxySocketParams::destination() const { + if (tcp_params_ == NULL) + return ssl_params_->tcp_params()->destination(); + else + return tcp_params_->destination(); } HttpProxySocketParams::~HttpProxySocketParams() {} @@ -42,6 +55,7 @@ HttpProxyConnectJob::HttpProxyConnectJob( const scoped_refptr<HttpProxySocketParams>& params, const base::TimeDelta& timeout_duration, const scoped_refptr<TCPClientSocketPool>& tcp_pool, + const scoped_refptr<SSLClientSocketPool>& ssl_pool, const scoped_refptr<HostResolver>& host_resolver, Delegate* delegate, NetLog* net_log) @@ -49,6 +63,7 @@ HttpProxyConnectJob::HttpProxyConnectJob( BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), params_(params), tcp_pool_(tcp_pool), + ssl_pool_(ssl_pool), resolver_(host_resolver), ALLOW_THIS_IN_INITIALIZER_LIST( callback_(this, &HttpProxyConnectJob::OnIOComplete)) { @@ -60,7 +75,9 @@ LoadState HttpProxyConnectJob::GetLoadState() const { switch (next_state_) { case kStateTCPConnect: case kStateTCPConnectComplete: - return tcp_socket_handle_->GetLoadState(); + case kStateSSLConnect: + case kStateSSLConnectComplete: + return transport_socket_handle_->GetLoadState(); case kStateHttpProxyConnect: case kStateHttpProxyConnectComplete: return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL; @@ -71,7 +88,10 @@ LoadState HttpProxyConnectJob::GetLoadState() const { } int HttpProxyConnectJob::ConnectInternal() { - next_state_ = kStateTCPConnect; + if (params_->tcp_params()) + next_state_ = kStateTCPConnect; + else + next_state_ = kStateSSLConnect; return DoLoop(OK); } @@ -96,6 +116,13 @@ int HttpProxyConnectJob::DoLoop(int result) { case kStateTCPConnectComplete: rv = DoTCPConnectComplete(rv); break; + case kStateSSLConnect: + DCHECK_EQ(OK, rv); + rv = DoSSLConnect(); + break; + case kStateSSLConnectComplete: + rv = DoSSLConnectComplete(rv); + break; case kStateHttpProxyConnect: DCHECK_EQ(OK, rv); rv = DoHttpProxyConnect(); @@ -115,8 +142,8 @@ int HttpProxyConnectJob::DoLoop(int result) { int HttpProxyConnectJob::DoTCPConnect() { next_state_ = kStateTCPConnectComplete; - tcp_socket_handle_.reset(new ClientSocketHandle()); - return tcp_socket_handle_->Init( + transport_socket_handle_.reset(new ClientSocketHandle()); + return transport_socket_handle_->Init( group_name(), params_->tcp_params(), params_->tcp_params()->destination().priority(), &callback_, tcp_pool_, net_log()); @@ -135,22 +162,46 @@ int HttpProxyConnectJob::DoTCPConnectComplete(int result) { return result; } +int HttpProxyConnectJob::DoSSLConnect() { + next_state_ = kStateSSLConnectComplete; + transport_socket_handle_.reset(new ClientSocketHandle()); + return transport_socket_handle_->Init( + group_name(), params_->ssl_params(), + params_->ssl_params()->tcp_params()->destination().priority(), + &callback_, ssl_pool_, net_log()); +} + +int HttpProxyConnectJob::DoSSLConnectComplete(int result) { + if (result < 0) { + if (transport_socket_handle_->socket()) + transport_socket_handle_->socket()->Disconnect(); + return result; + } + + // Reset the timer to just the length of time allowed for HttpProxy handshake + // so that a fast SSL connection plus a slow HttpProxy failure doesn't take + // longer to timeout than it should. + ResetTimer(base::TimeDelta::FromSeconds( + kHttpProxyConnectJobTimeoutInSeconds)); + next_state_ = kStateHttpProxyConnect; + return result; +} + int HttpProxyConnectJob::DoHttpProxyConnect() { next_state_ = kStateHttpProxyConnectComplete; - const HostResolver::RequestInfo& tcp_destination = - params_->tcp_params()->destination(); + const HostResolver::RequestInfo& tcp_destination = params_->destination(); HostPortPair proxy_server(tcp_destination.hostname(), tcp_destination.port()); // Add a HttpProxy connection on top of the tcp socket. - socket_.reset(new HttpProxyClientSocket(tcp_socket_handle_.release(), - params_->request_url(), - params_->user_agent(), - params_->endpoint(), - proxy_server, - params_->session(), - params_->tunnel())); - int result = socket_->Connect(&callback_); + transport_socket_.reset( + new HttpProxyClientSocket(transport_socket_handle_.release(), + params_->request_url(), + params_->user_agent(), + params_->endpoint(), + proxy_server, params_->session(), + params_->tunnel())); + int result = transport_socket_->Connect(&callback_); // Clear the circular reference to HttpNetworkSession (|params_| reference // HttpNetworkSession, which reference HttpProxyClientSocketPool, which @@ -162,26 +213,40 @@ int HttpProxyConnectJob::DoHttpProxyConnect() { int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) { if (result == OK || result == ERR_PROXY_AUTH_REQUESTED) - set_socket(socket_.release()); + set_socket(transport_socket_.release()); return result; } +HttpProxyClientSocketPool:: +HttpProxyConnectJobFactory::HttpProxyConnectJobFactory( + const scoped_refptr<TCPClientSocketPool>& tcp_pool, + const scoped_refptr<SSLClientSocketPool>& ssl_pool, + HostResolver* host_resolver, + NetLog* net_log) + : tcp_pool_(tcp_pool), + ssl_pool_(ssl_pool), + host_resolver_(host_resolver), + net_log_(net_log) { + base::TimeDelta max_pool_timeout = base::TimeDelta(); + if (tcp_pool_) + max_pool_timeout = tcp_pool_->ConnectionTimeout(); + if (ssl_pool_) + max_pool_timeout = std::max(max_pool_timeout, + ssl_pool_->ConnectionTimeout()); + timeout_ = max_pool_timeout + + base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds); +} + + ConnectJob* HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob( const std::string& group_name, const PoolBase::Request& request, ConnectJob::Delegate* delegate) const { return new HttpProxyConnectJob(group_name, request.params(), - ConnectionTimeout(), tcp_pool_, host_resolver_, - delegate, net_log_); -} - -base::TimeDelta -HttpProxyClientSocketPool::HttpProxyConnectJobFactory::ConnectionTimeout() -const { - return tcp_pool_->ConnectionTimeout() + - base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds); + ConnectionTimeout(), tcp_pool_, ssl_pool_, + host_resolver_, delegate, net_log_); } HttpProxyClientSocketPool::HttpProxyClientSocketPool( @@ -190,12 +255,14 @@ HttpProxyClientSocketPool::HttpProxyClientSocketPool( const scoped_refptr<ClientSocketPoolHistograms>& histograms, const scoped_refptr<HostResolver>& host_resolver, const scoped_refptr<TCPClientSocketPool>& tcp_pool, + const scoped_refptr<SSLClientSocketPool>& ssl_pool, NetLog* net_log) : base_(max_sockets, max_sockets_per_group, histograms, base::TimeDelta::FromSeconds( ClientSocketPool::unused_idle_socket_timeout()), base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout), - new HttpProxyConnectJobFactory(tcp_pool, host_resolver, net_log)) {} + new HttpProxyConnectJobFactory(tcp_pool, ssl_pool, host_resolver, + net_log)) {} HttpProxyClientSocketPool::~HttpProxyClientSocketPool() {} diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h index 3e3df7c..c992cf0 100644 --- a/net/http/http_proxy_client_socket_pool.h +++ b/net/http/http_proxy_client_socket_pool.h @@ -22,12 +22,19 @@ namespace net { class HostResolver; class HttpNetworkSession; +class SSLClientSocketPool; +class SSLSocketParams; class TCPClientSocketPool; class TCPSocketParams; +// HttpProxySocketParams only needs the socket params for one of the proxy +// types. The other param must be NULL. When using an HTTP Proxy, +// |tcp_params| must be set. When using an HTTPS Proxy, |ssl_params| +// must be set. class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> { public: - HttpProxySocketParams(const scoped_refptr<TCPSocketParams>& proxy_server, + HttpProxySocketParams(const scoped_refptr<TCPSocketParams>& tcp_params, + const scoped_refptr<SSLSocketParams>& ssl_params, const GURL& request_url, const std::string& user_agent, HostPortPair endpoint, @@ -37,12 +44,16 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> { const scoped_refptr<TCPSocketParams>& tcp_params() const { return tcp_params_; } + const scoped_refptr<SSLSocketParams>& ssl_params() const { + return ssl_params_; + } const GURL& request_url() const { return request_url_; } const std::string& user_agent() const { return user_agent_; } const HostPortPair& endpoint() const { return endpoint_; } const scoped_refptr<HttpNetworkSession>& session() { return session_; } + const HostResolver::RequestInfo& destination() const; bool tunnel() const { return tunnel_; } private: @@ -50,6 +61,7 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> { ~HttpProxySocketParams(); const scoped_refptr<TCPSocketParams> tcp_params_; + const scoped_refptr<SSLSocketParams> ssl_params_; const GURL request_url_; const std::string user_agent_; const HostPortPair endpoint_; @@ -67,6 +79,7 @@ class HttpProxyConnectJob : public ConnectJob { const scoped_refptr<HttpProxySocketParams>& params, const base::TimeDelta& timeout_duration, const scoped_refptr<TCPClientSocketPool>& tcp_pool, + const scoped_refptr<SSLClientSocketPool>& ssl_pool, const scoped_refptr<HostResolver> &host_resolver, Delegate* delegate, NetLog* net_log); @@ -79,6 +92,8 @@ class HttpProxyConnectJob : public ConnectJob { enum State { kStateTCPConnect, kStateTCPConnectComplete, + kStateSSLConnect, + kStateSSLConnectComplete, kStateHttpProxyConnect, kStateHttpProxyConnectComplete, kStateNone, @@ -98,19 +113,25 @@ class HttpProxyConnectJob : public ConnectJob { // Runs the state transition loop. int DoLoop(int result); + // Connecting to HTTP Proxy int DoTCPConnect(); int DoTCPConnectComplete(int result); + // Connecting to HTTPS Proxy + int DoSSLConnect(); + int DoSSLConnectComplete(int result); + int DoHttpProxyConnect(); int DoHttpProxyConnectComplete(int result); scoped_refptr<HttpProxySocketParams> params_; const scoped_refptr<TCPClientSocketPool> tcp_pool_; + const scoped_refptr<SSLClientSocketPool> ssl_pool_; const scoped_refptr<HostResolver> resolver_; State next_state_; CompletionCallbackImpl<HttpProxyConnectJob> callback_; - scoped_ptr<ClientSocketHandle> tcp_socket_handle_; - scoped_ptr<ClientSocket> socket_; + scoped_ptr<ClientSocketHandle> transport_socket_handle_; + scoped_ptr<ClientSocket> transport_socket_; DISALLOW_COPY_AND_ASSIGN(HttpProxyConnectJob); }; @@ -123,6 +144,7 @@ class HttpProxyClientSocketPool : public ClientSocketPool { const scoped_refptr<ClientSocketPoolHistograms>& histograms, const scoped_refptr<HostResolver>& host_resolver, const scoped_refptr<TCPClientSocketPool>& tcp_pool, + const scoped_refptr<SSLClientSocketPool>& ssl_pool, NetLog* net_log); // ClientSocketPool methods: @@ -171,25 +193,23 @@ class HttpProxyClientSocketPool : public ClientSocketPool { public: HttpProxyConnectJobFactory( const scoped_refptr<TCPClientSocketPool>& tcp_pool, + const scoped_refptr<SSLClientSocketPool>& ssl_pool, HostResolver* host_resolver, - NetLog* net_log) - : tcp_pool_(tcp_pool), - host_resolver_(host_resolver), - net_log_(net_log) {} - - virtual ~HttpProxyConnectJobFactory() {} + NetLog* net_log); // ClientSocketPoolBase::ConnectJobFactory methods. virtual ConnectJob* NewConnectJob(const std::string& group_name, const PoolBase::Request& request, ConnectJob::Delegate* delegate) const; - virtual base::TimeDelta ConnectionTimeout() const; + virtual base::TimeDelta ConnectionTimeout() const { return timeout_; } private: const scoped_refptr<TCPClientSocketPool> tcp_pool_; + const scoped_refptr<SSLClientSocketPool> ssl_pool_; const scoped_refptr<HostResolver> host_resolver_; NetLog* net_log_; + base::TimeDelta timeout_; DISALLOW_COPY_AND_ASSIGN(HttpProxyConnectJobFactory); }; diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index 2324b0d..761360b 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc @@ -29,14 +29,27 @@ namespace { const int kMaxSockets = 32; const int kMaxSocketsPerGroup = 6; -class HttpProxyClientSocketPoolTest : public ClientSocketPoolTest { +enum HttpProxyType { + HTTP, + HTTPS +}; + +typedef ::testing::TestWithParam<HttpProxyType> TestWithHttpParam; + +class HttpProxyClientSocketPoolTest : public TestWithHttpParam { protected: HttpProxyClientSocketPoolTest() - : ignored_tcp_socket_params_(new TCPSocketParams( + : ssl_config_(), + ignored_tcp_socket_params_(new TCPSocketParams( HostPortPair("proxy", 80), MEDIUM, GURL(), false)), + ignored_ssl_socket_params_(new SSLSocketParams( + ignored_tcp_socket_params_, NULL, NULL, ProxyServer::SCHEME_DIRECT, + "host", ssl_config_, 0, false, false)), tcp_histograms_(new ClientSocketPoolHistograms("MockTCP")), tcp_socket_pool_(new MockTCPClientSocketPool(kMaxSockets, kMaxSocketsPerGroup, tcp_histograms_, &tcp_client_socket_factory_)), + ssl_socket_pool_(new MockSSLClientSocketPool(kMaxSockets, + kMaxSocketsPerGroup, tcp_histograms_, &tcp_client_socket_factory_)), http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()), session_(new HttpNetworkSession(new MockHostResolver, ProxyService::CreateNull(), @@ -46,16 +59,11 @@ class HttpProxyClientSocketPoolTest : public ClientSocketPoolTest { http_auth_handler_factory_.get(), NULL, NULL)), - notunnel_socket_params_(new HttpProxySocketParams( - ignored_tcp_socket_params_, GURL("http://host"), "", - HostPortPair("host", 80), NULL, false)), - tunnel_socket_params_(new HttpProxySocketParams( - ignored_tcp_socket_params_, GURL("http://host"), "", - HostPortPair("host", 80), session_, true)), http_proxy_histograms_( new ClientSocketPoolHistograms("HttpProxyUnitTest")), pool_(new HttpProxyClientSocketPool(kMaxSockets, kMaxSocketsPerGroup, - http_proxy_histograms_, NULL, tcp_socket_pool_, NULL)) { + http_proxy_histograms_, NULL, tcp_socket_pool_, ssl_socket_pool_, + NULL)) { } void AddAuthToCache() { @@ -65,32 +73,64 @@ class HttpProxyClientSocketPoolTest : public ClientSocketPoolTest { "Basic realm=MyRealm1", kFoo, kBar, "/"); } - int StartRequest(const std::string& group_name, RequestPriority priority) { - return StartRequestUsingPool( - pool_, group_name, priority, tunnel_socket_params_); + scoped_refptr<TCPSocketParams> GetTcpParams() { + if (GetParam() == HTTPS) + return scoped_refptr<TCPSocketParams>(); + return ignored_tcp_socket_params_; + } + + scoped_refptr<SSLSocketParams> GetSslParams() { + if (GetParam() == HTTP) + return scoped_refptr<SSLSocketParams>(); + return ignored_ssl_socket_params_; + } + + // Returns the a correctly constructed HttpProxyParms + // for the HTTP or HTTPS proxy. + scoped_refptr<HttpProxySocketParams> GetParams(bool tunnel) { + return scoped_refptr<HttpProxySocketParams>(new HttpProxySocketParams( + GetTcpParams(), GetSslParams(), GURL("http://host/"), "", + HostPortPair("host", 80), session_, tunnel)); + } + + scoped_refptr<HttpProxySocketParams> GetTunnelParams() { + return GetParams(true); } + scoped_refptr<HttpProxySocketParams> GetNoTunnelParams() { + return GetParams(false); + } + + SSLConfig ssl_config_; + scoped_refptr<TCPSocketParams> ignored_tcp_socket_params_; + scoped_refptr<SSLSocketParams> ignored_ssl_socket_params_; scoped_refptr<ClientSocketPoolHistograms> tcp_histograms_; MockClientSocketFactory tcp_client_socket_factory_; scoped_refptr<MockTCPClientSocketPool> tcp_socket_pool_; + scoped_refptr<MockSSLClientSocketPool> ssl_socket_pool_; MockClientSocketFactory socket_factory_; scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_; scoped_refptr<HttpNetworkSession> session_; - scoped_refptr<HttpProxySocketParams> notunnel_socket_params_; - scoped_refptr<HttpProxySocketParams> tunnel_socket_params_; scoped_refptr<ClientSocketPoolHistograms> http_proxy_histograms_; scoped_refptr<HttpProxyClientSocketPool> pool_; }; -TEST_F(HttpProxyClientSocketPoolTest, NoTunnel) { +//----------------------------------------------------------------------------- +// All tests are run with three different connection types: SPDY after NPN +// negotiation, SPDY without SSL, and SPDY with SSL. +INSTANTIATE_TEST_CASE_P(HttpProxyClientSocketPoolTests, + HttpProxyClientSocketPoolTest, + ::testing::Values(HTTP, HTTPS)); + +TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) { StaticSocketDataProvider data; data.set_connect_data(MockConnect(false, 0)); tcp_client_socket_factory_.AddSocketDataProvider(&data); ClientSocketHandle handle; - int rv = handle.Init("a", notunnel_socket_params_, LOW, NULL, pool_, + int rv = handle.Init("a", GetNoTunnelParams(), LOW, NULL, pool_, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(handle.is_initialized()); @@ -100,7 +140,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NoTunnel) { EXPECT_TRUE(tunnel_socket->IsConnected()); } -TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) { +TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) { MockWrite writes[] = { MockWrite("CONNECT host:80 HTTP/1.1\r\n" "Host: host\r\n" @@ -120,7 +160,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) { ClientSocketHandle handle; TestCompletionCallback callback; - int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_, + int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_FALSE(handle.is_initialized()); @@ -134,7 +174,7 @@ TEST_F(HttpProxyClientSocketPoolTest, NeedAuth) { EXPECT_FALSE(tunnel_socket->IsConnected()); } -TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) { +TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) { MockWrite writes[] = { MockWrite(false, "CONNECT host:80 HTTP/1.1\r\n" @@ -154,7 +194,7 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) { ClientSocketHandle handle; TestCompletionCallback callback; - int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_, + int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(handle.is_initialized()); @@ -164,7 +204,7 @@ TEST_F(HttpProxyClientSocketPoolTest, HaveAuth) { EXPECT_TRUE(tunnel_socket->IsConnected()); } -TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) { +TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) { MockWrite writes[] = { MockWrite("CONNECT host:80 HTTP/1.1\r\n" "Host: host\r\n" @@ -182,7 +222,7 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) { ClientSocketHandle handle; TestCompletionCallback callback; - int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_, + int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_FALSE(handle.is_initialized()); @@ -196,7 +236,7 @@ TEST_F(HttpProxyClientSocketPoolTest, AsyncHaveAuth) { EXPECT_TRUE(tunnel_socket->IsConnected()); } -TEST_F(HttpProxyClientSocketPoolTest, TCPError) { +TEST_P(HttpProxyClientSocketPoolTest, TCPError) { StaticSocketDataProvider data; data.set_connect_data(MockConnect(true, ERR_CONNECTION_CLOSED)); @@ -204,7 +244,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TCPError) { ClientSocketHandle handle; TestCompletionCallback callback; - int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_, + int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_FALSE(handle.is_initialized()); @@ -215,7 +255,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TCPError) { EXPECT_FALSE(handle.socket()); } -TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) { +TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) { MockWrite writes[] = { MockWrite("CONNECT host:80 HTTP/1.1\r\n" "Host: host\r\n" @@ -234,7 +274,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) { ClientSocketHandle handle; TestCompletionCallback callback; - int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_, + int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_FALSE(handle.is_initialized()); @@ -245,7 +285,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) { EXPECT_FALSE(handle.socket()); } -TEST_F(HttpProxyClientSocketPoolTest, TunnelSetupError) { +TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) { MockWrite writes[] = { MockWrite("CONNECT host:80 HTTP/1.1\r\n" "Host: host\r\n" @@ -263,7 +303,7 @@ TEST_F(HttpProxyClientSocketPoolTest, TunnelSetupError) { ClientSocketHandle handle; TestCompletionCallback callback; - int rv = handle.Init("a", tunnel_socket_params_, LOW, &callback, pool_, + int rv = handle.Init("a", GetTunnelParams(), LOW, &callback, pool_, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_FALSE(handle.is_initialized()); diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc index 8ca375b..567e353 100644 --- a/net/http/http_stream_request.cc +++ b/net/http/http_stream_request.cc @@ -395,7 +395,8 @@ int HttpStreamRequest::DoResolveProxyComplete(int result) { // Remove unsupported proxies from the list. proxy_info()->RemoveProxiesWithoutScheme( - ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP | + ProxyServer::SCHEME_DIRECT | + ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS | ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5); if (proxy_info()->is_empty()) { @@ -461,7 +462,7 @@ int HttpStreamRequest::DoInitConnection() { new TCPSocketParams(*proxy_host_port, request_info().priority, request_info().referrer, disable_resolver_cache); - if (proxy_info()->is_http()) { + if (proxy_info()->is_http() || proxy_info()->is_https()) { GURL authentication_url = request_info().url; if (using_ssl_ && !authentication_url.SchemeIs("https")) { // If a proxy tunnel connection needs to be established due to @@ -479,7 +480,15 @@ int HttpStreamRequest::DoInitConnection() { std::string user_agent; request_info().extra_headers.GetHeader(HttpRequestHeaders::kUserAgent, &user_agent); + scoped_refptr<SSLSocketParams> ssl_params; + if (proxy_info()->is_https()) + // Set ssl_params, and unset proxy_tcp_params + ssl_params = GenerateSslParams(proxy_tcp_params.release(), NULL, NULL, + ProxyServer::SCHEME_DIRECT, + want_spdy_over_npn); + http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, + ssl_params, authentication_url, user_agent, endpoint_, @@ -504,35 +513,10 @@ int HttpStreamRequest::DoInitConnection() { // Deal with SSL - which layers on top of any given proxy. if (using_ssl_) { - if (factory_->IsTLSIntolerantServer(request_info().url)) { - LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: " - << GetHostAndPort(request_info().url); - ssl_config()->ssl3_fallback = true; - ssl_config()->tls1_enabled = false; - } - - UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback", - static_cast<int>(ssl_config()->ssl3_fallback), 2); - - int load_flags = request_info().load_flags; - if (factory_->ignore_certificate_errors()) - load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; - if (request_info().load_flags & LOAD_VERIFY_EV_CERT) - ssl_config()->verify_ev_cert = true; - - if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP || - proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) { - ssl_config()->mitm_proxies_allowed = true; - } - scoped_refptr<SSLSocketParams> ssl_params = - new SSLSocketParams(tcp_params, http_proxy_params, socks_params, - proxy_info()->proxy_server().scheme(), - request_info().url.HostNoBrackets(), *ssl_config(), - load_flags, - force_spdy_always_ && force_spdy_over_ssl_, - want_spdy_over_npn); - + GenerateSslParams(tcp_params, http_proxy_params, socks_params, + proxy_info()->proxy_server().scheme(), + want_spdy_over_npn); scoped_refptr<SSLClientSocketPool> ssl_pool; if (proxy_info()->is_direct()) ssl_pool = session_->ssl_socket_pool(); @@ -545,7 +529,7 @@ int HttpStreamRequest::DoInitConnection() { } // Finally, get the connection started. - if (proxy_info()->is_http()) { + if (proxy_info()->is_http() || proxy_info()->is_https()) { return connection_->Init( connection_group, http_proxy_params, request_info().priority, &io_callback_, session_->GetSocketPoolForHTTPProxy(*proxy_host_port), @@ -743,6 +727,47 @@ int HttpStreamRequest::DoRestartTunnelAuthComplete(int result) { return ReconsiderProxyAfterError(result); } +// Returns a newly create SSLSocketParams, and sets several +// fields of ssl_config_. +scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSslParams( + scoped_refptr<TCPSocketParams> tcp_params, + scoped_refptr<HttpProxySocketParams> http_proxy_params, + scoped_refptr<SOCKSSocketParams> socks_params, + ProxyServer::Scheme proxy_scheme, + bool want_spdy_over_npn) { + + if (factory_->IsTLSIntolerantServer(request_info().url)) { + LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: " + << GetHostAndPort(request_info().url); + ssl_config()->ssl3_fallback = true; + ssl_config()->tls1_enabled = false; + } + + UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback", + static_cast<int>(ssl_config()->ssl3_fallback), 2); + + int load_flags = request_info().load_flags; + if (factory_->ignore_certificate_errors()) + load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; + if (request_info().load_flags & LOAD_VERIFY_EV_CERT) + ssl_config()->verify_ev_cert = true; + + if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP || + proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) { + ssl_config()->mitm_proxies_allowed = true; + } + + scoped_refptr<SSLSocketParams> ssl_params = + new SSLSocketParams(tcp_params, http_proxy_params, socks_params, + proxy_scheme, request_info().url.HostNoBrackets(), + *ssl_config(), load_flags, + force_spdy_always_ && force_spdy_over_ssl_, + want_spdy_over_npn); + + return ssl_params; +} + + void HttpStreamRequest::MarkBrokenAlternateProtocolAndFallback() { // We have to: // * Reset the endpoint to be the unmodified URL specified destination. @@ -915,4 +940,3 @@ void HttpStreamRequest::LogHttpConnectedMetrics( } } // namespace net - diff --git a/net/http/http_stream_request.h b/net/http/http_stream_request.h index 3039839..cd1551e 100644 --- a/net/http/http_stream_request.h +++ b/net/http/http_stream_request.h @@ -22,8 +22,12 @@ namespace net { class ClientSocketHandle; class HttpAuthController; class HttpNetworkSession; +class HttpProxySocketParams; class HttpStreamFactory; +class SOCKSSocketParams; +class SSLSocketParams; class StreamRequestDelegate; +class TCPSocketParams; // An HttpStreamRequest exists for each stream which is in progress of being // created for the StreamFactory. @@ -106,6 +110,15 @@ class HttpStreamRequest : public StreamFactory::StreamRequestJob { int DoRestartTunnelAuth(); int DoRestartTunnelAuthComplete(int result); + // Returns a newly create SSLSocketParams, and sets several + // fields of ssl_config_. + scoped_refptr<SSLSocketParams> GenerateSslParams( + scoped_refptr<TCPSocketParams> tcp_params, + scoped_refptr<HttpProxySocketParams> http_proxy_params, + scoped_refptr<SOCKSSocketParams> socks_params, + ProxyServer::Scheme proxy_scheme, + bool want_spdy_over_npn); + // AlternateProtocol API void MarkBrokenAlternateProtocolAndFallback(); |