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