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.
5 #include "net/http/http_proxy_client_socket.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"
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
,
38 NextProto protocol_negotiated
,
39 ProxyDelegate
* proxy_delegate
,
41 : io_callback_(base::Bind(&HttpProxyClientSocket::OnIOComplete
,
42 base::Unretained(this))),
43 next_state_(STATE_NONE
),
44 transport_(transport_socket
),
47 new HttpAuthController(HttpAuth::AUTH_PROXY
,
48 GURL((is_https_proxy
? "https://" : "http://")
49 + proxy_server
.ToString()),
51 http_auth_handler_factory
)
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
,
69 HttpProxyClientSocket::~HttpProxyClientSocket() {
73 int HttpProxyClientSocket::RestartWithAuth(const CompletionCallback
& callback
) {
74 DCHECK_EQ(STATE_NONE
, next_state_
);
75 DCHECK(user_callback_
.is_null());
77 int rv
= PrepareForAuthRestart();
82 if (rv
== ERR_IO_PENDING
) {
83 if (!callback
.is_null())
84 user_callback_
= callback
;
90 const scoped_refptr
<HttpAuthController
>&
91 HttpProxyClientSocket::GetAuthController() const {
95 bool HttpProxyClientSocket::IsUsingSpdy() const {
99 NextProto
HttpProxyClientSocket::GetProtocolNegotiated() const {
100 return protocol_negotiated_
;
103 const HttpResponseInfo
* HttpProxyClientSocket::GetConnectResponseInfo() const {
104 return response_
.headers
.get() ? &response_
: NULL
;
107 HttpStream
* HttpProxyClientSocket::CreateConnectResponseStream() {
108 return new ProxyConnectRedirectHttpStream(
109 redirect_has_load_timing_info_
? &redirect_load_timing_info_
: NULL
);
113 int HttpProxyClientSocket::Connect(const CompletionCallback
& callback
) {
114 DCHECK(transport_
.get());
115 DCHECK(transport_
->socket());
116 DCHECK(user_callback_
.is_null());
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
)
128 DCHECK_EQ(STATE_NONE
, next_state_
);
129 next_state_
= STATE_GENERATE_AUTH_TOKEN
;
132 if (rv
== ERR_IO_PENDING
)
133 user_callback_
= callback
;
137 void HttpProxyClientSocket::Disconnect() {
138 if (transport_
.get())
139 transport_
->socket()->Disconnect();
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();
147 bool HttpProxyClientSocket::IsConnected() const {
148 return next_state_
== STATE_DONE
&& transport_
->socket()->IsConnected();
151 bool HttpProxyClientSocket::IsConnectedAndIdle() const {
152 return next_state_
== STATE_DONE
&&
153 transport_
->socket()->IsConnectedAndIdle();
156 const BoundNetLog
& HttpProxyClientSocket::NetLog() const {
160 void HttpProxyClientSocket::SetSubresourceSpeculation() {
161 if (transport_
.get() && transport_
->socket()) {
162 transport_
->socket()->SetSubresourceSpeculation();
168 void HttpProxyClientSocket::SetOmniboxSpeculation() {
169 if (transport_
.get() && transport_
->socket()) {
170 transport_
->socket()->SetOmniboxSpeculation();
176 bool HttpProxyClientSocket::WasEverUsed() const {
177 if (transport_
.get() && transport_
->socket()) {
178 return transport_
->socket()->WasEverUsed();
184 bool HttpProxyClientSocket::UsingTCPFastOpen() const {
185 if (transport_
.get() && transport_
->socket()) {
186 return transport_
->socket()->UsingTCPFastOpen();
192 bool HttpProxyClientSocket::WasNpnNegotiated() const {
193 if (transport_
.get() && transport_
->socket()) {
194 return transport_
->socket()->WasNpnNegotiated();
200 NextProto
HttpProxyClientSocket::GetNegotiatedProtocol() const {
201 if (transport_
.get() && transport_
->socket()) {
202 return transport_
->socket()->GetNegotiatedProtocol();
205 return kProtoUnknown
;
208 bool HttpProxyClientSocket::GetSSLInfo(SSLInfo
* ssl_info
) {
209 if (transport_
.get() && transport_
->socket()) {
210 return transport_
->socket()->GetSSLInfo(ssl_info
);
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();
230 return ERR_TUNNEL_CONNECTION_FAILED
;
233 return transport_
->socket()->Read(buf
, buf_len
, callback
);
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());
241 return transport_
->socket()->Write(buf
, buf_len
, callback
);
244 int HttpProxyClientSocket::SetReceiveBufferSize(int32 size
) {
245 return transport_
->socket()->SetReceiveBufferSize(size
);
248 int HttpProxyClientSocket::SetSendBufferSize(int32 size
) {
249 return transport_
->socket()->SetSendBufferSize(size
);
252 int HttpProxyClientSocket::GetPeerAddress(IPEndPoint
* address
) const {
253 return transport_
->socket()->GetPeerAddress(address
);
256 int HttpProxyClientSocket::GetLocalAddress(IPEndPoint
* address
) const {
257 return transport_
->socket()->GetLocalAddress(address
);
260 int HttpProxyClientSocket::PrepareForAuthRestart() {
261 if (!response_
.headers
.get())
262 return ERR_CONNECTION_RESET
;
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
);
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
);
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
);
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();
291 // Reset the other member variables.
294 http_stream_parser_
.reset();
295 request_line_
.clear();
296 request_headers_
.Clear();
297 response_
= HttpResponseInfo();
301 void HttpProxyClientSocket::LogBlockedTunnelResponse() const {
302 ProxyClientSocket::LogBlockedTunnelResponse(
303 response_
.headers
->response_code(),
308 void HttpProxyClientSocket::DoCallback(int result
) {
309 DCHECK_NE(ERR_IO_PENDING
, result
);
310 DCHECK(!user_callback_
.is_null());
312 // Since Run() may result in Read being called,
313 // clear user_callback_ up front.
314 CompletionCallback c
= user_callback_
;
315 user_callback_
.Reset();
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
)
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
;
332 State state
= next_state_
;
333 next_state_
= STATE_NONE
;
335 case STATE_GENERATE_AUTH_TOKEN
:
337 rv
= DoGenerateAuthToken();
339 case STATE_GENERATE_AUTH_TOKEN_COMPLETE
:
340 rv
= DoGenerateAuthTokenComplete(rv
);
342 case STATE_SEND_REQUEST
:
345 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
);
346 rv
= DoSendRequest();
348 case STATE_SEND_REQUEST_COMPLETE
:
349 rv
= DoSendRequestComplete(rv
);
350 net_log_
.EndEventWithNetErrorCode(
351 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
, rv
);
353 case STATE_READ_HEADERS
:
356 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
);
357 rv
= DoReadHeaders();
359 case STATE_READ_HEADERS_COMPLETE
:
360 rv
= DoReadHeadersComplete(rv
);
361 net_log_
.EndEventWithNetErrorCode(
362 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
, rv
);
364 case STATE_DRAIN_BODY
:
368 case STATE_DRAIN_BODY_COMPLETE
:
369 rv
= DoDrainBodyComplete(rv
);
371 case STATE_TCP_RESTART
:
375 case STATE_TCP_RESTART_COMPLETE
:
376 rv
= DoTCPRestartComplete(rv
);
381 NOTREACHED() << "bad state";
385 } while (rv
!= ERR_IO_PENDING
&& next_state_
!= STATE_NONE
&&
386 next_state_
!= STATE_DONE
);
390 int HttpProxyClientSocket::DoGenerateAuthToken() {
391 next_state_
= STATE_GENERATE_AUTH_TOKEN_COMPLETE
;
392 return auth_
->MaybeGenerateAuthToken(&request_
, io_callback_
, net_log_
);
395 int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result
) {
396 DCHECK_NE(ERR_IO_PENDING
, result
);
398 next_state_
= STATE_SEND_REQUEST
;
402 int HttpProxyClientSocket::DoSendRequest() {
403 next_state_
= STATE_SEND_REQUEST_COMPLETE
;
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
);
416 BuildTunnelRequest(request_
, authorization_headers
, endpoint_
,
417 &request_line_
, &request_headers_
);
420 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
421 base::Bind(&HttpRequestHeaders::NetLogCallback
,
422 base::Unretained(&request_headers_
),
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_
);
433 int HttpProxyClientSocket::DoSendRequestComplete(int result
) {
437 next_state_
= STATE_READ_HEADERS
;
441 int HttpProxyClientSocket::DoReadHeaders() {
442 next_state_
= STATE_READ_HEADERS_COMPLETE
;
443 return http_stream_parser_
->ReadResponseHeaders(io_callback_
);
446 int HttpProxyClientSocket::DoReadHeadersComplete(int result
) {
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
;
455 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
456 base::Bind(&HttpResponseHeaders::NetLogCallback
, response_
.headers
));
458 if (proxy_delegate_
) {
459 proxy_delegate_
->OnTunnelHeadersReceived(
460 HostPortPair::FromURL(request_
.url
),
465 switch (response_
.headers
->response_code()) {
467 if (http_stream_parser_
->IsMoreDataBuffered())
468 // The proxy sent extraneous data after the headers.
469 return ERR_TUNNEL_CONNECTION_FAILED
;
471 next_state_
= STATE_DONE
;
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.
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_
);
492 http_stream_parser_
.reset();
493 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE
;
496 // We're not using an HTTPS proxy, or we couldn't sanitize the redirect.
497 LogBlockedTunnelResponse();
498 return ERR_TUNNEL_CONNECTION_FAILED
;
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_
);
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
;
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_
);
527 int HttpProxyClientSocket::DoDrainBodyComplete(int result
) {
531 if (http_stream_parser_
->IsResponseBodyComplete())
532 return DidDrainBodyForAuthRestart(true);
535 next_state_
= STATE_DRAIN_BODY
;
539 int HttpProxyClientSocket::DoTCPRestart() {
540 next_state_
= STATE_TCP_RESTART_COMPLETE
;
541 return transport_
->socket()->Connect(
542 base::Bind(&HttpProxyClientSocket::OnIOComplete
, base::Unretained(this)));
545 int HttpProxyClientSocket::DoTCPRestartComplete(int result
) {
549 next_state_
= STATE_GENERATE_AUTH_TOKEN
;