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 |