| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_proxy_client_socket.h" | 5 #include "net/http/http_proxy_client_socket.h" |
| 6 | 6 |
| 7 #include "base/string_util.h" | 7 #include "base/string_util.h" |
| 8 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
| 9 #include "googleurl/src/gurl.h" | 9 #include "googleurl/src/gurl.h" |
| 10 #include "net/base/auth.h" | 10 #include "net/base/auth.h" |
| 11 #include "net/base/host_port_pair.h" | 11 #include "net/base/host_port_pair.h" |
| 12 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
| 13 #include "net/base/net_log.h" | 13 #include "net/base/net_log.h" |
| 14 #include "net/base/net_util.h" | 14 #include "net/base/net_util.h" |
| 15 #include "net/http/http_basic_stream.h" |
| 15 #include "net/http/http_net_log_params.h" | 16 #include "net/http/http_net_log_params.h" |
| 16 #include "net/http/http_network_session.h" | 17 #include "net/http/http_network_session.h" |
| 17 #include "net/http/http_proxy_utils.h" | 18 #include "net/http/http_proxy_utils.h" |
| 18 #include "net/http/http_request_info.h" | 19 #include "net/http/http_request_info.h" |
| 19 #include "net/http/http_response_headers.h" | 20 #include "net/http/http_response_headers.h" |
| 20 #include "net/http/http_stream_parser.h" | 21 #include "net/http/http_stream_parser.h" |
| 21 #include "net/socket/client_socket_handle.h" | 22 #include "net/socket/client_socket_handle.h" |
| 22 | 23 |
| 23 namespace net { | 24 namespace net { |
| 24 | 25 |
| 25 HttpProxyClientSocket::HttpProxyClientSocket( | 26 HttpProxyClientSocket::HttpProxyClientSocket( |
| 26 ClientSocketHandle* transport_socket, | 27 ClientSocketHandle* transport_socket, |
| 27 const GURL& request_url, | 28 const GURL& request_url, |
| 28 const std::string& user_agent, | 29 const std::string& user_agent, |
| 29 const HostPortPair& endpoint, | 30 const HostPortPair& endpoint, |
| 30 const HostPortPair& proxy_server, | 31 const HostPortPair& proxy_server, |
| 31 HttpAuthCache* http_auth_cache, | 32 HttpAuthCache* http_auth_cache, |
| 32 HttpAuthHandlerFactory* http_auth_handler_factory, | 33 HttpAuthHandlerFactory* http_auth_handler_factory, |
| 33 bool tunnel, | 34 bool tunnel, |
| 34 bool using_spdy) | 35 bool using_spdy, |
| 36 bool is_https_proxy) |
| 35 : ALLOW_THIS_IN_INITIALIZER_LIST( | 37 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 36 io_callback_(this, &HttpProxyClientSocket::OnIOComplete)), | 38 io_callback_(this, &HttpProxyClientSocket::OnIOComplete)), |
| 37 next_state_(STATE_NONE), | 39 next_state_(STATE_NONE), |
| 38 user_callback_(NULL), | 40 user_callback_(NULL), |
| 39 transport_(transport_socket), | 41 transport_(transport_socket), |
| 40 endpoint_(endpoint), | 42 endpoint_(endpoint), |
| 41 auth_(tunnel ? | 43 auth_(tunnel ? |
| 42 new HttpAuthController(HttpAuth::AUTH_PROXY, | 44 new HttpAuthController(HttpAuth::AUTH_PROXY, |
| 43 GURL("http://" + proxy_server.ToString()), | 45 GURL("http://" + proxy_server.ToString()), |
| 44 http_auth_cache, | 46 http_auth_cache, |
| 45 http_auth_handler_factory) | 47 http_auth_handler_factory) |
| 46 : NULL), | 48 : NULL), |
| 47 tunnel_(tunnel), | 49 tunnel_(tunnel), |
| 48 using_spdy_(using_spdy), | 50 using_spdy_(using_spdy), |
| 51 is_https_proxy_(is_https_proxy), |
| 49 net_log_(transport_socket->socket()->NetLog()) { | 52 net_log_(transport_socket->socket()->NetLog()) { |
| 50 // Synthesize the bits of a request that we actually use. | 53 // Synthesize the bits of a request that we actually use. |
| 51 request_.url = request_url; | 54 request_.url = request_url; |
| 52 request_.method = "GET"; | 55 request_.method = "GET"; |
| 53 if (!user_agent.empty()) | 56 if (!user_agent.empty()) |
| 54 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, | 57 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, |
| 55 user_agent); | 58 user_agent); |
| 56 } | 59 } |
| 57 | 60 |
| 58 HttpProxyClientSocket::~HttpProxyClientSocket() { | 61 HttpProxyClientSocket::~HttpProxyClientSocket() { |
| 59 Disconnect(); | 62 Disconnect(); |
| 60 } | 63 } |
| 61 | 64 |
| 65 HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { |
| 66 return new HttpBasicStream(transport_.release(), |
| 67 http_stream_parser_.release(), false); |
| 68 } |
| 69 |
| 70 |
| 62 int HttpProxyClientSocket::Connect(CompletionCallback* callback) { | 71 int HttpProxyClientSocket::Connect(CompletionCallback* callback) { |
| 63 DCHECK(transport_.get()); | 72 DCHECK(transport_.get()); |
| 64 DCHECK(transport_->socket()); | 73 DCHECK(transport_->socket()); |
| 65 DCHECK(!user_callback_); | 74 DCHECK(!user_callback_); |
| 66 | 75 |
| 67 // TODO(rch): figure out the right way to set up a tunnel with SPDY. | 76 // TODO(rch): figure out the right way to set up a tunnel with SPDY. |
| 68 // This approach sends the complete HTTPS request to the proxy | 77 // This approach sends the complete HTTPS request to the proxy |
| 69 // which allows the proxy to see "private" data. Instead, we should | 78 // which allows the proxy to see "private" data. Instead, we should |
| 70 // create an SSL tunnel to the origin server using the CONNECT method | 79 // create an SSL tunnel to the origin server using the CONNECT method |
| 71 // inside a single SPDY stream. | 80 // inside a single SPDY stream. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 return OK; | 147 return OK; |
| 139 } | 148 } |
| 140 | 149 |
| 141 void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { | 150 void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { |
| 142 LOG(WARNING) << "Blocked proxy response with status " << response_code | 151 LOG(WARNING) << "Blocked proxy response with status " << response_code |
| 143 << " to CONNECT request for " | 152 << " to CONNECT request for " |
| 144 << GetHostAndPort(request_.url) << "."; | 153 << GetHostAndPort(request_.url) << "."; |
| 145 } | 154 } |
| 146 | 155 |
| 147 void HttpProxyClientSocket::Disconnect() { | 156 void HttpProxyClientSocket::Disconnect() { |
| 148 transport_->socket()->Disconnect(); | 157 if (transport_.get()) |
| 158 transport_->socket()->Disconnect(); |
| 149 | 159 |
| 150 // Reset other states to make sure they aren't mistakenly used later. | 160 // Reset other states to make sure they aren't mistakenly used later. |
| 151 // These are the states initialized by Connect(). | 161 // These are the states initialized by Connect(). |
| 152 next_state_ = STATE_NONE; | 162 next_state_ = STATE_NONE; |
| 153 user_callback_ = NULL; | 163 user_callback_ = NULL; |
| 154 } | 164 } |
| 155 | 165 |
| 156 bool HttpProxyClientSocket::IsConnected() const { | 166 bool HttpProxyClientSocket::IsConnected() const { |
| 157 return next_state_ == STATE_DONE && transport_->socket()->IsConnected(); | 167 return next_state_ == STATE_DONE && transport_->socket()->IsConnected(); |
| 158 } | 168 } |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 // client is expecting an SSL protected response. | 408 // client is expecting an SSL protected response. |
| 399 // See http://crbug.com/7338. | 409 // See http://crbug.com/7338. |
| 400 case 407: // Proxy Authentication Required | 410 case 407: // Proxy Authentication Required |
| 401 // We need this status code to allow proxy authentication. Our | 411 // We need this status code to allow proxy authentication. Our |
| 402 // authentication code is smart enough to avoid being tricked by an | 412 // authentication code is smart enough to avoid being tricked by an |
| 403 // active network attacker. | 413 // active network attacker. |
| 404 // The next state is intentionally not set as it should be STATE_NONE; | 414 // The next state is intentionally not set as it should be STATE_NONE; |
| 405 return HandleAuthChallenge(); | 415 return HandleAuthChallenge(); |
| 406 | 416 |
| 407 default: | 417 default: |
| 418 if (is_https_proxy_) |
| 419 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; |
| 408 // For all other status codes, we conservatively fail the CONNECT | 420 // For all other status codes, we conservatively fail the CONNECT |
| 409 // request. | 421 // request. |
| 410 // We lose something by doing this. We have seen proxy 403, 404, and | 422 // We lose something by doing this. We have seen proxy 403, 404, and |
| 411 // 501 response bodies that contain a useful error message. For | 423 // 501 response bodies that contain a useful error message. For |
| 412 // example, Squid uses a 404 response to report the DNS error: "The | 424 // example, Squid uses a 404 response to report the DNS error: "The |
| 413 // domain name does not exist." | 425 // domain name does not exist." |
| 414 LogBlockedTunnelResponse(response_.headers->response_code()); | 426 LogBlockedTunnelResponse(response_.headers->response_code()); |
| 415 return ERR_TUNNEL_CONNECTION_FAILED; | 427 return ERR_TUNNEL_CONNECTION_FAILED; |
| 416 } | 428 } |
| 417 } | 429 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 | 466 |
| 455 int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_); | 467 int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_); |
| 456 response_.auth_challenge = auth_->auth_info(); | 468 response_.auth_challenge = auth_->auth_info(); |
| 457 if (rv == OK) | 469 if (rv == OK) |
| 458 return ERR_PROXY_AUTH_REQUESTED; | 470 return ERR_PROXY_AUTH_REQUESTED; |
| 459 | 471 |
| 460 return rv; | 472 return rv; |
| 461 } | 473 } |
| 462 | 474 |
| 463 } // namespace net | 475 } // namespace net |
| OLD | NEW |