15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_proxy_client_socket.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/host_port_pair.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/proxy_delegate.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_basic_stream.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_parser.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/http/proxy_connect_redirect_http_stream.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_handle.h" 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocket::HttpProxyClientSocket( 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSocketHandle* transport_socket, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& request_url, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_agent, 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HostPortPair& endpoint, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HostPortPair& proxy_server, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthCache* http_auth_cache, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthHandlerFactory* http_auth_handler_factory, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool tunnel, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool using_spdy, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NextProto protocol_negotiated, 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ProxyDelegate* proxy_delegate, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_https_proxy) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : io_callback_(base::Bind(&HttpProxyClientSocket::OnIOComplete, 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_(STATE_NONE), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_(transport_socket), 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) endpoint_(endpoint), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_(tunnel ? 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new HttpAuthController(HttpAuth::AUTH_PROXY, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL((is_https_proxy ? "https://" : "http://") 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + proxy_server.ToString()), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_auth_cache, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_auth_handler_factory) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : NULL), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tunnel_(tunnel), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using_spdy_(using_spdy), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol_negotiated_(protocol_negotiated), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_https_proxy_(is_https_proxy), 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch redirect_has_load_timing_info_(false), 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proxy_server_(proxy_server), 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proxy_delegate_(proxy_delegate), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_(transport_socket->socket()->NetLog()) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Synthesize the bits of a request that we actually use. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.url = request_url; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.method = "GET"; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!user_agent.empty()) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_agent); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocket::~HttpProxyClientSocket() { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Disconnect(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_NONE, next_state_); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(user_callback_.is_null()); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = PrepareForAuthRestart(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoLoop(OK); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!callback.is_null()) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_callback_ = callback; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const scoped_refptr<HttpAuthController>& 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocket::GetAuthController() const { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return auth_; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::IsUsingSpdy() const { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return using_spdy_; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto HttpProxyClientSocket::GetProtocolNegotiated() const { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return protocol_negotiated_; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const { 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return response_.headers.get() ? &response_ : NULL; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return new ProxyConnectRedirectHttpStream( 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch redirect_has_load_timing_info_ ? &redirect_load_timing_info_ : NULL); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::Connect(const CompletionCallback& callback) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(transport_.get()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(transport_->socket()); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(user_callback_.is_null()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rch): figure out the right way to set up a tunnel with SPDY. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This approach sends the complete HTTPS request to the proxy 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which allows the proxy to see "private" data. Instead, we should 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // create an SSL tunnel to the origin server using the CONNECT method 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inside a single SPDY stream. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (using_spdy_ || !tunnel_) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DONE; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_state_ == STATE_DONE) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_NONE, next_state_); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GENERATE_AUTH_TOKEN; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoLoop(OK); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_callback_ = callback; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::Disconnect() { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get()) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->Disconnect(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset other states to make sure they aren't mistakenly used later. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These are the states initialized by Connect(). 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_NONE; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_callback_.Reset(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::IsConnected() const { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return next_state_ == STATE_DONE && transport_->socket()->IsConnected(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::IsConnectedAndIdle() const { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return next_state_ == STATE_DONE && 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->IsConnectedAndIdle(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& HttpProxyClientSocket::NetLog() const { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_log_; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::SetSubresourceSpeculation() { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->SetSubresourceSpeculation(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::SetOmniboxSpeculation() { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->SetOmniboxSpeculation(); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::WasEverUsed() const { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->WasEverUsed(); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::UsingTCPFastOpen() const { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->UsingTCPFastOpen(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::WasNpnNegotiated() const { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->WasNpnNegotiated(); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto HttpProxyClientSocket::GetNegotiatedProtocol() const { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetNegotiatedProtocol(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kProtoUnknown; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetSSLInfo(ssl_info); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(user_callback_.is_null()); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_state_ != STATE_DONE) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're trying to read the body of the response but we're still trying 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to establish an SSL tunnel through the proxy. We can't read these 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes when establishing a tunnel because they might be controlled by 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an active network attacker. We don't worry about this for HTTP 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because an active network attacker can already control HTTP sessions. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We reach this case when the user cancels a 407 proxy auth prompt. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See http://crbug.com/8473. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(407, response_.headers->response_code()); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogBlockedTunnelResponse(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TUNNEL_CONNECTION_FAILED; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->Read(buf, buf_len, callback); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::Write(IOBuffer* buf, int buf_len, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_DONE, next_state_); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(user_callback_.is_null()); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->Write(buf, buf_len, callback); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint HttpProxyClientSocket::SetReceiveBufferSize(int32 size) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->SetReceiveBufferSize(size); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint HttpProxyClientSocket::SetSendBufferSize(int32 size) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->SetSendBufferSize(size); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::GetPeerAddress(IPEndPoint* address) const { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetPeerAddress(address); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetLocalAddress(address); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::PrepareForAuthRestart() { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response_.headers.get()) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CONNECTION_RESET; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool keep_alive = false; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_.headers->IsKeepAlive() && 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_stream_parser_->CanFindEndOfResponse()) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!http_stream_parser_->IsResponseBodyComplete()) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DRAIN_BODY; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drain_buf_ = new IOBuffer(kDrainBodyBufferSize); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_alive = true; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't need to drain the response body, so we act as if we had drained 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the response body. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DidDrainBodyForAuthRestart(keep_alive); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (keep_alive && transport_->socket()->IsConnectedAndIdle()) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GENERATE_AUTH_TOKEN; 28323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) transport_->set_reuse_type(ClientSocketHandle::REUSED_IDLE); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This assumes that the underlying transport socket is a TCP socket, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since only TCP sockets are restartable. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_TCP_RESTART; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->Disconnect(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the other member variables. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drain_buf_ = NULL; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser_buf_ = NULL; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_stream_parser_.reset(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_line_.clear(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_headers_.Clear(); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_ = HttpResponseInfo(); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::LogBlockedTunnelResponse() const { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyClientSocket::LogBlockedTunnelResponse( 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_.headers->response_code(), 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.url, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_https_proxy_); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::DoCallback(int result) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(ERR_IO_PENDING, result); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!user_callback_.is_null()); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since Run() may result in Read being called, 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clear user_callback_ up front. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = user_callback_; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_callback_.Reset(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(result); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::OnIOComplete(int result) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(STATE_NONE, next_state_); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(STATE_DONE, next_state_); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoLoop(result); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != ERR_IO_PENDING) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoCallback(rv); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoLoop(int last_io_result) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(next_state_, STATE_NONE); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(next_state_, STATE_DONE); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = last_io_result; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) State state = next_state_; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_NONE; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_GENERATE_AUTH_TOKEN: 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoGenerateAuthToken(); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_GENERATE_AUTH_TOKEN_COMPLETE: 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoGenerateAuthTokenComplete(rv); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_SEND_REQUEST: 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent( 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoSendRequest(); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_SEND_REQUEST_COMPLETE: 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoSendRequestComplete(rv); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode( 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_READ_HEADERS: 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent( 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoReadHeaders(); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_READ_HEADERS_COMPLETE: 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoReadHeadersComplete(rv); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode( 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_DRAIN_BODY: 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoDrainBody(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_DRAIN_BODY_COMPLETE: 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoDrainBodyComplete(rv); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_TCP_RESTART: 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoTCPRestart(); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_TCP_RESTART_COMPLETE: 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoTCPRestartComplete(rv); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_DONE: 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "bad state"; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = ERR_UNEXPECTED; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE && 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ != STATE_DONE); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoGenerateAuthToken() { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return auth_->MaybeGenerateAuthToken(&request_, io_callback_, net_log_); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(ERR_IO_PENDING, result); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == OK) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_SEND_REQUEST; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoSendRequest() { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_SEND_REQUEST_COMPLETE; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is constructed lazily (instead of within our Start method), so that 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we have proxy info available. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_line_.empty()) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request_headers_.IsEmpty()); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpRequestHeaders authorization_headers; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (auth_->HaveAuth()) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->AddAuthorizationHeader(&authorization_headers); 4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (proxy_delegate_) { 4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proxy_delegate_->OnBeforeTunnelRequest(proxy_server_, 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &authorization_headers); 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildTunnelRequest(request_, authorization_headers, endpoint_, 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &request_line_, &request_headers_); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HttpRequestHeaders::NetLogCallback, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(&request_headers_), 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &request_line_)); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser_buf_ = new GrowableIOBuffer(); 427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) http_stream_parser_.reset(new HttpStreamParser( 428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) transport_.get(), &request_, parser_buf_.get(), net_log_)); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return http_stream_parser_->SendRequest( 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_line_, request_headers_, &response_, io_callback_); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoSendRequestComplete(int result) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_READ_HEADERS; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoReadHeaders() { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_READ_HEADERS_COMPLETE; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return http_stream_parser_->ReadResponseHeaders(io_callback_); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoReadHeadersComplete(int result) { 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Require the "HTTP/1.x" status line for SSL CONNECT. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TUNNEL_CONNECTION_FAILED; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HttpResponseHeaders::NetLogCallback, response_.headers)); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (proxy_delegate_) { 4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proxy_delegate_->OnTunnelHeadersReceived( 4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci HostPortPair::FromURL(request_.url), 4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proxy_server_, 4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *response_.headers); 4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (response_.headers->response_code()) { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 200: // OK 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (http_stream_parser_->IsMoreDataBuffered()) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The proxy sent extraneous data after the headers. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TUNNEL_CONNECTION_FAILED; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DONE; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We aren't able to CONNECT to the remote host through the proxy. We 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // need to be very suspicious about the response because an active network 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attacker can force us into this state by masquerading as the proxy. 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The only safe thing to do here is to fail the connection because our 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // client is expecting an SSL protected response. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See http://crbug.com/7338. 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 302: // Found / Moved Temporarily 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attempt to follow redirects from HTTPS proxies, but only if we can 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sanitize the response. This still allows a rogue HTTPS proxy to 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirect an HTTPS site load to a similar-looking site, but no longer 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allows it to impersonate the site the user requested. 486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (is_https_proxy_ && SanitizeProxyRedirect(&response_, request_.url)) { 487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool is_connection_reused = http_stream_parser_->IsConnectionReused(); 488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch redirect_has_load_timing_info_ = 489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch transport_->GetLoadTimingInfo( 490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch is_connection_reused, &redirect_load_timing_info_); 491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch transport_.reset(); 492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch http_stream_parser_.reset(); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; 494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're not using an HTTPS proxy, or we couldn't sanitize the redirect. 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogBlockedTunnelResponse(); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TUNNEL_CONNECTION_FAILED; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 407: // Proxy Authentication Required 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need this status code to allow proxy authentication. Our 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // authentication code is smart enough to avoid being tricked by an 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // active network attacker. 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The next state is intentionally not set as it should be STATE_NONE; 505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore response to avoid letting the proxy impersonate the target 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // server. (See http://crbug.com/137891.) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We lose something by doing this. We have seen proxy 403, 404, and 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 501 response bodies that contain a useful error message. For 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // example, Squid uses a 404 response to report the DNS error: "The 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // domain name does not exist." 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogBlockedTunnelResponse(); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TUNNEL_CONNECTION_FAILED; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoDrainBody() { 520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(drain_buf_.get()); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(transport_->is_initialized()); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DRAIN_BODY_COMPLETE; 523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return http_stream_parser_->ReadResponseBody( 524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) drain_buf_.get(), kDrainBodyBufferSize, io_callback_); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoDrainBodyComplete(int result) { 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (http_stream_parser_->IsResponseBodyComplete()) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DidDrainBodyForAuthRestart(true); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep draining. 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DRAIN_BODY; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoTCPRestart() { 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_TCP_RESTART_COMPLETE; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->Connect( 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HttpProxyClientSocket::OnIOComplete, base::Unretained(this))); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoTCPRestartComplete(int result) { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != OK) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GENERATE_AUTH_TOKEN; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 554