1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/http/http_proxy_client_socket.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "net/base/auth.h" 12 #include "net/base/host_port_pair.h" 13 #include "net/base/io_buffer.h" 14 #include "net/base/net_log.h" 15 #include "net/base/net_util.h" 16 #include "net/http/http_basic_stream.h" 17 #include "net/http/http_network_session.h" 18 #include "net/http/http_request_info.h" 19 #include "net/http/http_response_headers.h" 20 #include "net/http/http_stream_parser.h" 21 #include "net/http/proxy_connect_redirect_http_stream.h" 22 #include "net/socket/client_socket_handle.h" 23 #include "url/gurl.h" 24 25 namespace net { 26 27 HttpProxyClientSocket::HttpProxyClientSocket( 28 ClientSocketHandle* transport_socket, 29 const GURL& request_url, 30 const std::string& user_agent, 31 const HostPortPair& endpoint, 32 const HostPortPair& proxy_server, 33 HttpAuthCache* http_auth_cache, 34 HttpAuthHandlerFactory* http_auth_handler_factory, 35 bool tunnel, 36 bool using_spdy, 37 NextProto protocol_negotiated, 38 bool is_https_proxy) 39 : io_callback_(base::Bind(&HttpProxyClientSocket::OnIOComplete, 40 base::Unretained(this))), 41 next_state_(STATE_NONE), 42 transport_(transport_socket), 43 endpoint_(endpoint), 44 auth_(tunnel ? 45 new HttpAuthController(HttpAuth::AUTH_PROXY, 46 GURL((is_https_proxy ? "https://" : "http://") 47 + proxy_server.ToString()), 48 http_auth_cache, 49 http_auth_handler_factory) 50 : NULL), 51 tunnel_(tunnel), 52 using_spdy_(using_spdy), 53 protocol_negotiated_(protocol_negotiated), 54 is_https_proxy_(is_https_proxy), 55 redirect_has_load_timing_info_(false), 56 net_log_(transport_socket->socket()->NetLog()) { 57 // Synthesize the bits of a request that we actually use. 58 request_.url = request_url; 59 request_.method = "GET"; 60 if (!user_agent.empty()) 61 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 62 user_agent); 63 } 64 65 HttpProxyClientSocket::~HttpProxyClientSocket() { 66 Disconnect(); 67 } 68 69 int HttpProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) { 70 DCHECK_EQ(STATE_NONE, next_state_); 71 DCHECK(user_callback_.is_null()); 72 73 int rv = PrepareForAuthRestart(); 74 if (rv != OK) 75 return rv; 76 77 rv = DoLoop(OK); 78 if (rv == ERR_IO_PENDING) { 79 if (!callback.is_null()) 80 user_callback_ = callback; 81 } 82 83 return rv; 84 } 85 86 const scoped_refptr<HttpAuthController>& 87 HttpProxyClientSocket::GetAuthController() const { 88 return auth_; 89 } 90 91 bool HttpProxyClientSocket::IsUsingSpdy() const { 92 return using_spdy_; 93 } 94 95 NextProto HttpProxyClientSocket::GetProtocolNegotiated() const { 96 return protocol_negotiated_; 97 } 98 99 const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const { 100 return response_.headers.get() ? &response_ : NULL; 101 } 102 103 HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { 104 return new ProxyConnectRedirectHttpStream( 105 redirect_has_load_timing_info_ ? &redirect_load_timing_info_ : NULL); 106 } 107 108 109 int HttpProxyClientSocket::Connect(const CompletionCallback& callback) { 110 DCHECK(transport_.get()); 111 DCHECK(transport_->socket()); 112 DCHECK(user_callback_.is_null()); 113 114 // TODO(rch): figure out the right way to set up a tunnel with SPDY. 115 // This approach sends the complete HTTPS request to the proxy 116 // which allows the proxy to see "private" data. Instead, we should 117 // create an SSL tunnel to the origin server using the CONNECT method 118 // inside a single SPDY stream. 119 if (using_spdy_ || !tunnel_) 120 next_state_ = STATE_DONE; 121 if (next_state_ == STATE_DONE) 122 return OK; 123 124 DCHECK_EQ(STATE_NONE, next_state_); 125 next_state_ = STATE_GENERATE_AUTH_TOKEN; 126 127 int rv = DoLoop(OK); 128 if (rv == ERR_IO_PENDING) 129 user_callback_ = callback; 130 return rv; 131 } 132 133 void HttpProxyClientSocket::Disconnect() { 134 if (transport_.get()) 135 transport_->socket()->Disconnect(); 136 137 // Reset other states to make sure they aren't mistakenly used later. 138 // These are the states initialized by Connect(). 139 next_state_ = STATE_NONE; 140 user_callback_.Reset(); 141 } 142 143 bool HttpProxyClientSocket::IsConnected() const { 144 return next_state_ == STATE_DONE && transport_->socket()->IsConnected(); 145 } 146 147 bool HttpProxyClientSocket::IsConnectedAndIdle() const { 148 return next_state_ == STATE_DONE && 149 transport_->socket()->IsConnectedAndIdle(); 150 } 151 152 const BoundNetLog& HttpProxyClientSocket::NetLog() const { 153 return net_log_; 154 } 155 156 void HttpProxyClientSocket::SetSubresourceSpeculation() { 157 if (transport_.get() && transport_->socket()) { 158 transport_->socket()->SetSubresourceSpeculation(); 159 } else { 160 NOTREACHED(); 161 } 162 } 163 164 void HttpProxyClientSocket::SetOmniboxSpeculation() { 165 if (transport_.get() && transport_->socket()) { 166 transport_->socket()->SetOmniboxSpeculation(); 167 } else { 168 NOTREACHED(); 169 } 170 } 171 172 bool HttpProxyClientSocket::WasEverUsed() const { 173 if (transport_.get() && transport_->socket()) { 174 return transport_->socket()->WasEverUsed(); 175 } 176 NOTREACHED(); 177 return false; 178 } 179 180 bool HttpProxyClientSocket::UsingTCPFastOpen() const { 181 if (transport_.get() && transport_->socket()) { 182 return transport_->socket()->UsingTCPFastOpen(); 183 } 184 NOTREACHED(); 185 return false; 186 } 187 188 bool HttpProxyClientSocket::WasNpnNegotiated() const { 189 if (transport_.get() && transport_->socket()) { 190 return transport_->socket()->WasNpnNegotiated(); 191 } 192 NOTREACHED(); 193 return false; 194 } 195 196 NextProto HttpProxyClientSocket::GetNegotiatedProtocol() const { 197 if (transport_.get() && transport_->socket()) { 198 return transport_->socket()->GetNegotiatedProtocol(); 199 } 200 NOTREACHED(); 201 return kProtoUnknown; 202 } 203 204 bool HttpProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) { 205 if (transport_.get() && transport_->socket()) { 206 return transport_->socket()->GetSSLInfo(ssl_info); 207 } 208 NOTREACHED(); 209 return false; 210 } 211 212 int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len, 213 const CompletionCallback& callback) { 214 DCHECK(user_callback_.is_null()); 215 if (next_state_ != STATE_DONE) { 216 // We're trying to read the body of the response but we're still trying 217 // to establish an SSL tunnel through the proxy. We can't read these 218 // bytes when establishing a tunnel because they might be controlled by 219 // an active network attacker. We don't worry about this for HTTP 220 // because an active network attacker can already control HTTP sessions. 221 // We reach this case when the user cancels a 407 proxy auth prompt. 222 // See http://crbug.com/8473. 223 DCHECK_EQ(407, response_.headers->response_code()); 224 LogBlockedTunnelResponse(); 225 226 return ERR_TUNNEL_CONNECTION_FAILED; 227 } 228 229 return transport_->socket()->Read(buf, buf_len, callback); 230 } 231 232 int HttpProxyClientSocket::Write(IOBuffer* buf, int buf_len, 233 const CompletionCallback& callback) { 234 DCHECK_EQ(STATE_DONE, next_state_); 235 DCHECK(user_callback_.is_null()); 236 237 return transport_->socket()->Write(buf, buf_len, callback); 238 } 239 240 bool HttpProxyClientSocket::SetReceiveBufferSize(int32 size) { 241 return transport_->socket()->SetReceiveBufferSize(size); 242 } 243 244 bool HttpProxyClientSocket::SetSendBufferSize(int32 size) { 245 return transport_->socket()->SetSendBufferSize(size); 246 } 247 248 int HttpProxyClientSocket::GetPeerAddress(IPEndPoint* address) const { 249 return transport_->socket()->GetPeerAddress(address); 250 } 251 252 int HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { 253 return transport_->socket()->GetLocalAddress(address); 254 } 255 256 int HttpProxyClientSocket::PrepareForAuthRestart() { 257 if (!response_.headers.get()) 258 return ERR_CONNECTION_RESET; 259 260 bool keep_alive = false; 261 if (response_.headers->IsKeepAlive() && 262 http_stream_parser_->CanFindEndOfResponse()) { 263 if (!http_stream_parser_->IsResponseBodyComplete()) { 264 next_state_ = STATE_DRAIN_BODY; 265 drain_buf_ = new IOBuffer(kDrainBodyBufferSize); 266 return OK; 267 } 268 keep_alive = true; 269 } 270 271 // We don't need to drain the response body, so we act as if we had drained 272 // the response body. 273 return DidDrainBodyForAuthRestart(keep_alive); 274 } 275 276 int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) { 277 if (keep_alive && transport_->socket()->IsConnectedAndIdle()) { 278 next_state_ = STATE_GENERATE_AUTH_TOKEN; 279 transport_->set_is_reused(true); 280 } else { 281 // This assumes that the underlying transport socket is a TCP socket, 282 // since only TCP sockets are restartable. 283 next_state_ = STATE_TCP_RESTART; 284 transport_->socket()->Disconnect(); 285 } 286 287 // Reset the other member variables. 288 drain_buf_ = NULL; 289 parser_buf_ = NULL; 290 http_stream_parser_.reset(); 291 request_line_.clear(); 292 request_headers_.Clear(); 293 response_ = HttpResponseInfo(); 294 return OK; 295 } 296 297 void HttpProxyClientSocket::LogBlockedTunnelResponse() const { 298 ProxyClientSocket::LogBlockedTunnelResponse( 299 response_.headers->response_code(), 300 request_.url, 301 is_https_proxy_); 302 } 303 304 void HttpProxyClientSocket::DoCallback(int result) { 305 DCHECK_NE(ERR_IO_PENDING, result); 306 DCHECK(!user_callback_.is_null()); 307 308 // Since Run() may result in Read being called, 309 // clear user_callback_ up front. 310 CompletionCallback c = user_callback_; 311 user_callback_.Reset(); 312 c.Run(result); 313 } 314 315 void HttpProxyClientSocket::OnIOComplete(int result) { 316 DCHECK_NE(STATE_NONE, next_state_); 317 DCHECK_NE(STATE_DONE, next_state_); 318 int rv = DoLoop(result); 319 if (rv != ERR_IO_PENDING) 320 DoCallback(rv); 321 } 322 323 int HttpProxyClientSocket::DoLoop(int last_io_result) { 324 DCHECK_NE(next_state_, STATE_NONE); 325 DCHECK_NE(next_state_, STATE_DONE); 326 int rv = last_io_result; 327 do { 328 State state = next_state_; 329 next_state_ = STATE_NONE; 330 switch (state) { 331 case STATE_GENERATE_AUTH_TOKEN: 332 DCHECK_EQ(OK, rv); 333 rv = DoGenerateAuthToken(); 334 break; 335 case STATE_GENERATE_AUTH_TOKEN_COMPLETE: 336 rv = DoGenerateAuthTokenComplete(rv); 337 break; 338 case STATE_SEND_REQUEST: 339 DCHECK_EQ(OK, rv); 340 net_log_.BeginEvent( 341 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST); 342 rv = DoSendRequest(); 343 break; 344 case STATE_SEND_REQUEST_COMPLETE: 345 rv = DoSendRequestComplete(rv); 346 net_log_.EndEventWithNetErrorCode( 347 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv); 348 break; 349 case STATE_READ_HEADERS: 350 DCHECK_EQ(OK, rv); 351 net_log_.BeginEvent( 352 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS); 353 rv = DoReadHeaders(); 354 break; 355 case STATE_READ_HEADERS_COMPLETE: 356 rv = DoReadHeadersComplete(rv); 357 net_log_.EndEventWithNetErrorCode( 358 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv); 359 break; 360 case STATE_DRAIN_BODY: 361 DCHECK_EQ(OK, rv); 362 rv = DoDrainBody(); 363 break; 364 case STATE_DRAIN_BODY_COMPLETE: 365 rv = DoDrainBodyComplete(rv); 366 break; 367 case STATE_TCP_RESTART: 368 DCHECK_EQ(OK, rv); 369 rv = DoTCPRestart(); 370 break; 371 case STATE_TCP_RESTART_COMPLETE: 372 rv = DoTCPRestartComplete(rv); 373 break; 374 case STATE_DONE: 375 break; 376 default: 377 NOTREACHED() << "bad state"; 378 rv = ERR_UNEXPECTED; 379 break; 380 } 381 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE && 382 next_state_ != STATE_DONE); 383 return rv; 384 } 385 386 int HttpProxyClientSocket::DoGenerateAuthToken() { 387 next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; 388 return auth_->MaybeGenerateAuthToken(&request_, io_callback_, net_log_); 389 } 390 391 int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) { 392 DCHECK_NE(ERR_IO_PENDING, result); 393 if (result == OK) 394 next_state_ = STATE_SEND_REQUEST; 395 return result; 396 } 397 398 int HttpProxyClientSocket::DoSendRequest() { 399 next_state_ = STATE_SEND_REQUEST_COMPLETE; 400 401 // This is constructed lazily (instead of within our Start method), so that 402 // we have proxy info available. 403 if (request_line_.empty()) { 404 DCHECK(request_headers_.IsEmpty()); 405 HttpRequestHeaders authorization_headers; 406 if (auth_->HaveAuth()) 407 auth_->AddAuthorizationHeader(&authorization_headers); 408 BuildTunnelRequest(request_, authorization_headers, endpoint_, 409 &request_line_, &request_headers_); 410 411 net_log_.AddEvent( 412 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 413 base::Bind(&HttpRequestHeaders::NetLogCallback, 414 base::Unretained(&request_headers_), 415 &request_line_)); 416 } 417 418 parser_buf_ = new GrowableIOBuffer(); 419 http_stream_parser_.reset(new HttpStreamParser( 420 transport_.get(), &request_, parser_buf_.get(), net_log_)); 421 return http_stream_parser_->SendRequest( 422 request_line_, request_headers_, &response_, io_callback_); 423 } 424 425 int HttpProxyClientSocket::DoSendRequestComplete(int result) { 426 if (result < 0) 427 return result; 428 429 next_state_ = STATE_READ_HEADERS; 430 return OK; 431 } 432 433 int HttpProxyClientSocket::DoReadHeaders() { 434 next_state_ = STATE_READ_HEADERS_COMPLETE; 435 return http_stream_parser_->ReadResponseHeaders(io_callback_); 436 } 437 438 int HttpProxyClientSocket::DoReadHeadersComplete(int result) { 439 if (result < 0) 440 return result; 441 442 // Require the "HTTP/1.x" status line for SSL CONNECT. 443 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) 444 return ERR_TUNNEL_CONNECTION_FAILED; 445 446 net_log_.AddEvent( 447 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 448 base::Bind(&HttpResponseHeaders::NetLogCallback, response_.headers)); 449 450 switch (response_.headers->response_code()) { 451 case 200: // OK 452 if (http_stream_parser_->IsMoreDataBuffered()) 453 // The proxy sent extraneous data after the headers. 454 return ERR_TUNNEL_CONNECTION_FAILED; 455 456 next_state_ = STATE_DONE; 457 return OK; 458 459 // We aren't able to CONNECT to the remote host through the proxy. We 460 // need to be very suspicious about the response because an active network 461 // attacker can force us into this state by masquerading as the proxy. 462 // The only safe thing to do here is to fail the connection because our 463 // client is expecting an SSL protected response. 464 // See http://crbug.com/7338. 465 466 case 302: // Found / Moved Temporarily 467 // Attempt to follow redirects from HTTPS proxies, but only if we can 468 // sanitize the response. This still allows a rogue HTTPS proxy to 469 // redirect an HTTPS site load to a similar-looking site, but no longer 470 // allows it to impersonate the site the user requested. 471 if (is_https_proxy_ && SanitizeProxyRedirect(&response_, request_.url)) { 472 bool is_connection_reused = http_stream_parser_->IsConnectionReused(); 473 redirect_has_load_timing_info_ = 474 transport_->GetLoadTimingInfo( 475 is_connection_reused, &redirect_load_timing_info_); 476 transport_.reset(); 477 http_stream_parser_.reset(); 478 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; 479 } 480 481 // We're not using an HTTPS proxy, or we couldn't sanitize the redirect. 482 LogBlockedTunnelResponse(); 483 return ERR_TUNNEL_CONNECTION_FAILED; 484 485 case 407: // Proxy Authentication Required 486 // We need this status code to allow proxy authentication. Our 487 // authentication code is smart enough to avoid being tricked by an 488 // active network attacker. 489 // The next state is intentionally not set as it should be STATE_NONE; 490 return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_); 491 492 default: 493 // Ignore response to avoid letting the proxy impersonate the target 494 // server. (See http://crbug.com/137891.) 495 // We lose something by doing this. We have seen proxy 403, 404, and 496 // 501 response bodies that contain a useful error message. For 497 // example, Squid uses a 404 response to report the DNS error: "The 498 // domain name does not exist." 499 LogBlockedTunnelResponse(); 500 return ERR_TUNNEL_CONNECTION_FAILED; 501 } 502 } 503 504 int HttpProxyClientSocket::DoDrainBody() { 505 DCHECK(drain_buf_.get()); 506 DCHECK(transport_->is_initialized()); 507 next_state_ = STATE_DRAIN_BODY_COMPLETE; 508 return http_stream_parser_->ReadResponseBody( 509 drain_buf_.get(), kDrainBodyBufferSize, io_callback_); 510 } 511 512 int HttpProxyClientSocket::DoDrainBodyComplete(int result) { 513 if (result < 0) 514 return result; 515 516 if (http_stream_parser_->IsResponseBodyComplete()) 517 return DidDrainBodyForAuthRestart(true); 518 519 // Keep draining. 520 next_state_ = STATE_DRAIN_BODY; 521 return OK; 522 } 523 524 int HttpProxyClientSocket::DoTCPRestart() { 525 next_state_ = STATE_TCP_RESTART_COMPLETE; 526 return transport_->socket()->Connect( 527 base::Bind(&HttpProxyClientSocket::OnIOComplete, base::Unretained(this))); 528 } 529 530 int HttpProxyClientSocket::DoTCPRestartComplete(int result) { 531 if (result != OK) 532 return result; 533 534 next_state_ = STATE_GENERATE_AUTH_TOKEN; 535 return result; 536 } 537 538 } // namespace net 539