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