1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_proxy_client_socket.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/auth.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_port_pair.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/io_buffer.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h" 1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/http/http_basic_stream.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_net_log_params.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_network_session.h" 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_proxy_utils.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_request_info.h" 20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_response_headers.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_stream_parser.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket/client_socket_handle.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net { 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHttpProxyClientSocket::HttpProxyClientSocket( 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ClientSocketHandle* transport_socket, 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const GURL& request_url, 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& user_agent, 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const HostPortPair& endpoint, 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const HostPortPair& proxy_server, 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HttpAuthCache* http_auth_cache, 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HttpAuthHandlerFactory* http_auth_handler_factory, 343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool tunnel, 3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool using_spdy, 3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool is_https_proxy) 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : ALLOW_THIS_IN_INITIALIZER_LIST( 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch io_callback_(this, &HttpProxyClientSocket::OnIOComplete)), 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_(STATE_NONE), 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_(NULL), 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transport_(transport_socket), 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch endpoint_(endpoint), 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick auth_(tunnel ? 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick new HttpAuthController(HttpAuth::AUTH_PROXY, 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL("http://" + proxy_server.ToString()), 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick http_auth_cache, 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick http_auth_handler_factory) 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : NULL), 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tunnel_(tunnel), 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick using_spdy_(using_spdy), 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen is_https_proxy_(is_https_proxy), 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_(transport_socket->socket()->NetLog()) { 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Synthesize the bits of a request that we actually use. 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request_.url = request_url; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request_.method = "GET"; 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!user_agent.empty()) 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_agent); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHttpProxyClientSocket::~HttpProxyClientSocket() { 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Disconnect(); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint HttpProxyClientSocket::RestartWithAuth(CompletionCallback* callback) { 6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(STATE_NONE, next_state_); 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!user_callback_); 6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = PrepareForAuthRestart(); 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != OK) 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = DoLoop(OK); 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv == ERR_IO_PENDING) 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_callback_ = callback; 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const { 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return response_.headers ? &response_ : NULL; 8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 8394dee9037a31fbf43ed22eaa2a84fb4e7cd5569eKristian MonsenHttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { 8494dee9037a31fbf43ed22eaa2a84fb4e7cd5569eKristian Monsen return new HttpBasicStream(transport_.release(), 8594dee9037a31fbf43ed22eaa2a84fb4e7cd5569eKristian Monsen http_stream_parser_.release(), false); 8694dee9037a31fbf43ed22eaa2a84fb4e7cd5569eKristian Monsen} 8794dee9037a31fbf43ed22eaa2a84fb4e7cd5569eKristian Monsen 887b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 897b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): handle the case when wait_for_connect is true 907b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// (sync requests) 917b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 927b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint HttpProxyClientSocket::Connect(CompletionCallback* callback 937b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 947b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen , bool wait_for_connect 95e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , bool valid_uid 96e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , uid_t calling_uid 977b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 987b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen ) { 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(transport_.get()); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(transport_->socket()); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!user_callback_); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(rch): figure out the right way to set up a tunnel with SPDY. 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This approach sends the complete HTTPS request to the proxy 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // which allows the proxy to see "private" data. Instead, we should 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // create an SSL tunnel to the origin server using the CONNECT method 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // inside a single SPDY stream. 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (using_spdy_ || !tunnel_) 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_DONE; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (next_state_ == STATE_DONE) 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(STATE_NONE, next_state_); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_GENERATE_AUTH_TOKEN; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = DoLoop(OK); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv == ERR_IO_PENDING) 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = callback; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HttpProxyClientSocket::Disconnect() { 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (transport_.get()) 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen transport_->socket()->Disconnect(); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Reset other states to make sure they aren't mistakenly used later. 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These are the states initialized by Connect(). 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_NONE; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = NULL; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpProxyClientSocket::IsConnected() const { 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return next_state_ == STATE_DONE && transport_->socket()->IsConnected(); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpProxyClientSocket::IsConnectedAndIdle() const { 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return next_state_ == STATE_DONE && 1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick transport_->socket()->IsConnectedAndIdle(); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst BoundNetLog& HttpProxyClientSocket::NetLog() const { 14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return net_log_; 14321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpProxyClientSocket::SetSubresourceSpeculation() { 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick transport_->socket()->SetSubresourceSpeculation(); 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpProxyClientSocket::SetOmniboxSpeculation() { 1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick transport_->socket()->SetOmniboxSpeculation(); 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool HttpProxyClientSocket::WasEverUsed() const { 1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return transport_->socket()->WasEverUsed(); 1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool HttpProxyClientSocket::UsingTCPFastOpen() const { 170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (transport_.get() && transport_->socket()) { 171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return transport_->socket()->UsingTCPFastOpen(); 172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NOTREACHED(); 174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len, 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CompletionCallback* callback) { 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!user_callback_); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (next_state_ != STATE_DONE) { 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're trying to read the body of the response but we're still trying 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to establish an SSL tunnel through the proxy. We can't read these 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bytes when establishing a tunnel because they might be controlled by 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // an active network attacker. We don't worry about this for HTTP 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // because an active network attacker can already control HTTP sessions. 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We reach this case when the user cancels a 407 proxy auth prompt. 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See http://crbug.com/8473. 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(407, response_.headers->response_code()); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogBlockedTunnelResponse(response_.headers->response_code()); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_TUNNEL_CONNECTION_FAILED; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->Read(buf, buf_len, callback); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::Write(IOBuffer* buf, int buf_len, 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompletionCallback* callback) { 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(STATE_DONE, next_state_); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!user_callback_); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->Write(buf, buf_len, callback); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpProxyClientSocket::SetReceiveBufferSize(int32 size) { 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->SetReceiveBufferSize(size); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpProxyClientSocket::SetSendBufferSize(int32 size) { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->SetSendBufferSize(size); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::GetPeerAddress(AddressList* address) const { 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->GetPeerAddress(address); 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return transport_->socket()->GetLocalAddress(address); 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint HttpProxyClientSocket::PrepareForAuthRestart() { 22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!response_.headers.get()) 22372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_CONNECTION_RESET; 22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool keep_alive = false; 22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (response_.headers->IsKeepAlive() && 22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen http_stream_parser_->CanFindEndOfResponse()) { 22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!http_stream_parser_->IsResponseBodyComplete()) { 22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen next_state_ = STATE_DRAIN_BODY; 23072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen drain_buf_ = new IOBuffer(kDrainBodyBufferSize); 23172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OK; 23272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 23372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen keep_alive = true; 23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 23572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We don't need to drain the response body, so we act as if we had drained 23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the response body. 23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DidDrainBodyForAuthRestart(keep_alive); 23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) { 24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (keep_alive && transport_->socket()->IsConnectedAndIdle()) { 24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen next_state_ = STATE_GENERATE_AUTH_TOKEN; 24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_->set_is_reused(true); 24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This assumes that the underlying transport socket is a TCP socket, 24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // since only TCP sockets are restartable. 24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen next_state_ = STATE_TCP_RESTART; 24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_->socket()->Disconnect(); 25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Reset the other member variables. 25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen drain_buf_ = NULL; 25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parser_buf_ = NULL; 25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen http_stream_parser_.reset(); 25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_line_.clear(); 25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_headers_.Clear(); 25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen response_ = HttpResponseInfo(); 25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OK; 26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint HttpProxyClientSocket::HandleAuthChallenge() { 26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(response_.headers); 26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_); 26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen response_.auth_challenge = auth_->auth_info(); 26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv == OK) 26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_PROXY_AUTH_REQUESTED; 26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { 27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(WARNING) << "Blocked proxy response with status " << response_code 27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << " to CONNECT request for " 27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << GetHostAndPort(request_.url) << "."; 27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HttpProxyClientSocket::DoCallback(int result) { 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(ERR_IO_PENDING, result); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(user_callback_); 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since Run() may result in Read being called, 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // clear user_callback_ up front. 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompletionCallback* c = user_callback_; 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = NULL; 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch c->Run(result); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HttpProxyClientSocket::OnIOComplete(int result) { 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(STATE_NONE, next_state_); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(STATE_DONE, next_state_); 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = DoLoop(result); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != ERR_IO_PENDING) 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoCallback(rv); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoLoop(int last_io_result) { 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(next_state_, STATE_NONE); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(next_state_, STATE_DONE); 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = last_io_result; 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch do { 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch State state = next_state_; 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_NONE; 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state) { 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_GENERATE_AUTH_TOKEN: 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(OK, rv); 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoGenerateAuthToken(); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_GENERATE_AUTH_TOKEN_COMPLETE: 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoGenerateAuthTokenComplete(rv); 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_SEND_REQUEST: 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(OK, rv); 31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.BeginEvent( 31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, NULL); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoSendRequest(); 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_SEND_REQUEST_COMPLETE: 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoSendRequestComplete(rv); 32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode( 32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_READ_HEADERS: 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(OK, rv); 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.BeginEvent( 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, NULL); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoReadHeaders(); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_READ_HEADERS_COMPLETE: 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoReadHeadersComplete(rv); 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode( 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv); 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_DRAIN_BODY: 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(OK, rv); 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoDrainBody(); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_DRAIN_BODY_COMPLETE: 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = DoDrainBodyComplete(rv); 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case STATE_TCP_RESTART: 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(OK, rv); 3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rv = DoTCPRestart(); 3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case STATE_TCP_RESTART_COMPLETE: 3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rv = DoTCPRestartComplete(rv); 3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATE_DONE: 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "bad state"; 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = ERR_UNEXPECTED; 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE && 3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ != STATE_DONE); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoGenerateAuthToken() { 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return auth_->MaybeGenerateAuthToken(&request_, &io_callback_, net_log_); 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) { 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(ERR_IO_PENDING, result); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result == OK) 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_SEND_REQUEST; 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoSendRequest() { 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_SEND_REQUEST_COMPLETE; 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is constructed lazily (instead of within our Start method), so that 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we have proxy info available. 3784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (request_line_.empty()) { 3794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DCHECK(request_headers_.IsEmpty()); 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HttpRequestHeaders authorization_headers; 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (auth_->HaveAuth()) 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_->AddAuthorizationHeader(&authorization_headers); 383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BuildTunnelRequest(request_, authorization_headers, endpoint_, 3844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch &request_line_, &request_headers_); 385731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (net_log_.IsLoggingAllEvents()) { 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.AddEvent( 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 388513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new NetLogHttpRequestParameter( 3894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch request_line_, request_headers_))); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick parser_buf_ = new GrowableIOBuffer(); 3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick http_stream_parser_.reset( 3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick new HttpStreamParser(transport_.get(), &request_, parser_buf_, net_log_)); 3964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return http_stream_parser_->SendRequest(request_line_, request_headers_, NULL, 3973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &response_, &io_callback_); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoSendRequestComplete(int result) { 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result < 0) 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_READ_HEADERS; 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoReadHeaders() { 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_READ_HEADERS_COMPLETE; 4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return http_stream_parser_->ReadResponseHeaders(&io_callback_); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoReadHeadersComplete(int result) { 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result < 0) 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Require the "HTTP/1.x" status line for SSL CONNECT. 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_TUNNEL_CONNECTION_FAILED; 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 421731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (net_log_.IsLoggingAllEvents()) { 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.AddEvent( 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 424513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers))); 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (response_.headers->response_code()) { 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 200: // OK 4293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (http_stream_parser_->IsMoreDataBuffered()) 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The proxy sent extraneous data after the headers. 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_TUNNEL_CONNECTION_FAILED; 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_DONE; 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We aren't able to CONNECT to the remote host through the proxy. We 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // need to be very suspicious about the response because an active network 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // attacker can force us into this state by masquerading as the proxy. 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The only safe thing to do here is to fail the connection because our 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // client is expecting an SSL protected response. 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See http://crbug.com/7338. 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 407: // Proxy Authentication Required 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need this status code to allow proxy authentication. Our 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // authentication code is smart enough to avoid being tricked by an 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // active network attacker. 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The next state is intentionally not set as it should be STATE_NONE; 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return HandleAuthChallenge(); 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 45021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (is_https_proxy_) 45121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For all other status codes, we conservatively fail the CONNECT 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // request. 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We lose something by doing this. We have seen proxy 403, 404, and 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 501 response bodies that contain a useful error message. For 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // example, Squid uses a 404 response to report the DNS error: "The 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // domain name does not exist." 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogBlockedTunnelResponse(response_.headers->response_code()); 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_TUNNEL_CONNECTION_FAILED; 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoDrainBody() { 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(drain_buf_); 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(transport_->is_initialized()); 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_DRAIN_BODY_COMPLETE; 4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return http_stream_parser_->ReadResponseBody(drain_buf_, kDrainBodyBufferSize, 4683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &io_callback_); 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoDrainBodyComplete(int result) { 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result < 0) 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (http_stream_parser_->IsResponseBodyComplete()) 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DidDrainBodyForAuthRestart(true); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Keep draining. 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_DRAIN_BODY; 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4837b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 4847b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): Check if we can find out if Connect should block 485e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma// TODO(ashishsharma): Perhaps make ignore_limits, calling_uid, valid_uid part of ClientSocket 4867b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 4873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpProxyClientSocket::DoTCPRestart() { 4883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_TCP_RESTART_COMPLETE; 4897b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen return transport_->socket()->Connect(&io_callback_ 4907b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 4917b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen , false 492e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , false 493e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , 0 4947b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 4957b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen ); 4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpProxyClientSocket::DoTCPRestartComplete(int result) { 4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result != OK) 5003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return result; 5013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_GENERATE_AUTH_TOKEN; 5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return result; 5043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace net 507