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/http/http_basic_stream.h"
17 #include "net/http/http_network_session.h"
18 #include "net/http/http_request_info.h"
19 #include "net/http/http_response_headers.h"
20 #include "net/http/http_stream_parser.h"
21 #include "net/http/proxy_connect_redirect_http_stream.h"
22 #include "net/socket/client_socket_handle.h"
27 HttpProxyClientSocket::HttpProxyClientSocket(
28 ClientSocketHandle
* transport_socket
,
29 const GURL
& request_url
,
30 const std::string
& user_agent
,
31 const HostPortPair
& endpoint
,
32 const HostPortPair
& proxy_server
,
33 HttpAuthCache
* http_auth_cache
,
34 HttpAuthHandlerFactory
* http_auth_handler_factory
,
37 NextProto protocol_negotiated
,
39 : io_callback_(base::Bind(&HttpProxyClientSocket::OnIOComplete
,
40 base::Unretained(this))),
41 next_state_(STATE_NONE
),
42 transport_(transport_socket
),
45 new HttpAuthController(HttpAuth::AUTH_PROXY
,
46 GURL((is_https_proxy
? "https://" : "http://")
47 + proxy_server
.ToString()),
49 http_auth_handler_factory
)
52 using_spdy_(using_spdy
),
53 protocol_negotiated_(protocol_negotiated
),
54 is_https_proxy_(is_https_proxy
),
55 redirect_has_load_timing_info_(false),
56 net_log_(transport_socket
->socket()->NetLog()) {
57 // Synthesize the bits of a request that we actually use.
58 request_
.url
= request_url
;
59 request_
.method
= "GET";
60 if (!user_agent
.empty())
61 request_
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
65 HttpProxyClientSocket::~HttpProxyClientSocket() {
69 int HttpProxyClientSocket::RestartWithAuth(const CompletionCallback
& callback
) {
70 DCHECK_EQ(STATE_NONE
, next_state_
);
71 DCHECK(user_callback_
.is_null());
73 int rv
= PrepareForAuthRestart();
78 if (rv
== ERR_IO_PENDING
) {
79 if (!callback
.is_null())
80 user_callback_
= callback
;
86 const scoped_refptr
<HttpAuthController
>&
87 HttpProxyClientSocket::GetAuthController() const {
91 bool HttpProxyClientSocket::IsUsingSpdy() const {
95 NextProto
HttpProxyClientSocket::GetProtocolNegotiated() const {
96 return protocol_negotiated_
;
99 const HttpResponseInfo
* HttpProxyClientSocket::GetConnectResponseInfo() const {
100 return response_
.headers
.get() ? &response_
: NULL
;
103 HttpStream
* HttpProxyClientSocket::CreateConnectResponseStream() {
104 return new ProxyConnectRedirectHttpStream(
105 redirect_has_load_timing_info_
? &redirect_load_timing_info_
: NULL
);
109 int HttpProxyClientSocket::Connect(const CompletionCallback
& callback
) {
110 DCHECK(transport_
.get());
111 DCHECK(transport_
->socket());
112 DCHECK(user_callback_
.is_null());
114 // TODO(rch): figure out the right way to set up a tunnel with SPDY.
115 // This approach sends the complete HTTPS request to the proxy
116 // which allows the proxy to see "private" data. Instead, we should
117 // create an SSL tunnel to the origin server using the CONNECT method
118 // inside a single SPDY stream.
119 if (using_spdy_
|| !tunnel_
)
120 next_state_
= STATE_DONE
;
121 if (next_state_
== STATE_DONE
)
124 DCHECK_EQ(STATE_NONE
, next_state_
);
125 next_state_
= STATE_GENERATE_AUTH_TOKEN
;
128 if (rv
== ERR_IO_PENDING
)
129 user_callback_
= callback
;
133 void HttpProxyClientSocket::Disconnect() {
134 if (transport_
.get())
135 transport_
->socket()->Disconnect();
137 // Reset other states to make sure they aren't mistakenly used later.
138 // These are the states initialized by Connect().
139 next_state_
= STATE_NONE
;
140 user_callback_
.Reset();
143 bool HttpProxyClientSocket::IsConnected() const {
144 return next_state_
== STATE_DONE
&& transport_
->socket()->IsConnected();
147 bool HttpProxyClientSocket::IsConnectedAndIdle() const {
148 return next_state_
== STATE_DONE
&&
149 transport_
->socket()->IsConnectedAndIdle();
152 const BoundNetLog
& HttpProxyClientSocket::NetLog() const {
156 void HttpProxyClientSocket::SetSubresourceSpeculation() {
157 if (transport_
.get() && transport_
->socket()) {
158 transport_
->socket()->SetSubresourceSpeculation();
164 void HttpProxyClientSocket::SetOmniboxSpeculation() {
165 if (transport_
.get() && transport_
->socket()) {
166 transport_
->socket()->SetOmniboxSpeculation();
172 bool HttpProxyClientSocket::WasEverUsed() const {
173 if (transport_
.get() && transport_
->socket()) {
174 return transport_
->socket()->WasEverUsed();
180 bool HttpProxyClientSocket::UsingTCPFastOpen() const {
181 if (transport_
.get() && transport_
->socket()) {
182 return transport_
->socket()->UsingTCPFastOpen();
188 bool HttpProxyClientSocket::WasNpnNegotiated() const {
189 if (transport_
.get() && transport_
->socket()) {
190 return transport_
->socket()->WasNpnNegotiated();
196 NextProto
HttpProxyClientSocket::GetNegotiatedProtocol() const {
197 if (transport_
.get() && transport_
->socket()) {
198 return transport_
->socket()->GetNegotiatedProtocol();
201 return kProtoUnknown
;
204 bool HttpProxyClientSocket::GetSSLInfo(SSLInfo
* ssl_info
) {
205 if (transport_
.get() && transport_
->socket()) {
206 return transport_
->socket()->GetSSLInfo(ssl_info
);
212 int HttpProxyClientSocket::Read(IOBuffer
* buf
, int buf_len
,
213 const CompletionCallback
& callback
) {
214 DCHECK(user_callback_
.is_null());
215 if (next_state_
!= STATE_DONE
) {
216 // We're trying to read the body of the response but we're still trying
217 // to establish an SSL tunnel through the proxy. We can't read these
218 // bytes when establishing a tunnel because they might be controlled by
219 // an active network attacker. We don't worry about this for HTTP
220 // because an active network attacker can already control HTTP sessions.
221 // We reach this case when the user cancels a 407 proxy auth prompt.
222 // See http://crbug.com/8473.
223 DCHECK_EQ(407, response_
.headers
->response_code());
224 LogBlockedTunnelResponse();
226 return ERR_TUNNEL_CONNECTION_FAILED
;
229 return transport_
->socket()->Read(buf
, buf_len
, callback
);
232 int HttpProxyClientSocket::Write(IOBuffer
* buf
, int buf_len
,
233 const CompletionCallback
& callback
) {
234 DCHECK_EQ(STATE_DONE
, next_state_
);
235 DCHECK(user_callback_
.is_null());
237 return transport_
->socket()->Write(buf
, buf_len
, callback
);
240 int HttpProxyClientSocket::SetReceiveBufferSize(int32 size
) {
241 return transport_
->socket()->SetReceiveBufferSize(size
);
244 int HttpProxyClientSocket::SetSendBufferSize(int32 size
) {
245 return transport_
->socket()->SetSendBufferSize(size
);
248 int HttpProxyClientSocket::GetPeerAddress(IPEndPoint
* address
) const {
249 return transport_
->socket()->GetPeerAddress(address
);
252 int HttpProxyClientSocket::GetLocalAddress(IPEndPoint
* address
) const {
253 return transport_
->socket()->GetLocalAddress(address
);
256 int HttpProxyClientSocket::PrepareForAuthRestart() {
257 if (!response_
.headers
.get())
258 return ERR_CONNECTION_RESET
;
260 bool keep_alive
= false;
261 if (response_
.headers
->IsKeepAlive() &&
262 http_stream_parser_
->CanFindEndOfResponse()) {
263 if (!http_stream_parser_
->IsResponseBodyComplete()) {
264 next_state_
= STATE_DRAIN_BODY
;
265 drain_buf_
= new IOBuffer(kDrainBodyBufferSize
);
271 // We don't need to drain the response body, so we act as if we had drained
272 // the response body.
273 return DidDrainBodyForAuthRestart(keep_alive
);
276 int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive
) {
277 if (keep_alive
&& transport_
->socket()->IsConnectedAndIdle()) {
278 next_state_
= STATE_GENERATE_AUTH_TOKEN
;
279 transport_
->set_reuse_type(ClientSocketHandle::REUSED_IDLE
);
281 // This assumes that the underlying transport socket is a TCP socket,
282 // since only TCP sockets are restartable.
283 next_state_
= STATE_TCP_RESTART
;
284 transport_
->socket()->Disconnect();
287 // Reset the other member variables.
290 http_stream_parser_
.reset();
291 request_line_
.clear();
292 request_headers_
.Clear();
293 response_
= HttpResponseInfo();
297 void HttpProxyClientSocket::LogBlockedTunnelResponse() const {
298 ProxyClientSocket::LogBlockedTunnelResponse(
299 response_
.headers
->response_code(),
304 void HttpProxyClientSocket::DoCallback(int result
) {
305 DCHECK_NE(ERR_IO_PENDING
, result
);
306 DCHECK(!user_callback_
.is_null());
308 // Since Run() may result in Read being called,
309 // clear user_callback_ up front.
310 CompletionCallback c
= user_callback_
;
311 user_callback_
.Reset();
315 void HttpProxyClientSocket::OnIOComplete(int result
) {
316 DCHECK_NE(STATE_NONE
, next_state_
);
317 DCHECK_NE(STATE_DONE
, next_state_
);
318 int rv
= DoLoop(result
);
319 if (rv
!= ERR_IO_PENDING
)
323 int HttpProxyClientSocket::DoLoop(int last_io_result
) {
324 DCHECK_NE(next_state_
, STATE_NONE
);
325 DCHECK_NE(next_state_
, STATE_DONE
);
326 int rv
= last_io_result
;
328 State state
= next_state_
;
329 next_state_
= STATE_NONE
;
331 case STATE_GENERATE_AUTH_TOKEN
:
333 rv
= DoGenerateAuthToken();
335 case STATE_GENERATE_AUTH_TOKEN_COMPLETE
:
336 rv
= DoGenerateAuthTokenComplete(rv
);
338 case STATE_SEND_REQUEST
:
341 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
);
342 rv
= DoSendRequest();
344 case STATE_SEND_REQUEST_COMPLETE
:
345 rv
= DoSendRequestComplete(rv
);
346 net_log_
.EndEventWithNetErrorCode(
347 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST
, rv
);
349 case STATE_READ_HEADERS
:
352 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
);
353 rv
= DoReadHeaders();
355 case STATE_READ_HEADERS_COMPLETE
:
356 rv
= DoReadHeadersComplete(rv
);
357 net_log_
.EndEventWithNetErrorCode(
358 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS
, rv
);
360 case STATE_DRAIN_BODY
:
364 case STATE_DRAIN_BODY_COMPLETE
:
365 rv
= DoDrainBodyComplete(rv
);
367 case STATE_TCP_RESTART
:
371 case STATE_TCP_RESTART_COMPLETE
:
372 rv
= DoTCPRestartComplete(rv
);
377 NOTREACHED() << "bad state";
381 } while (rv
!= ERR_IO_PENDING
&& next_state_
!= STATE_NONE
&&
382 next_state_
!= STATE_DONE
);
386 int HttpProxyClientSocket::DoGenerateAuthToken() {
387 next_state_
= STATE_GENERATE_AUTH_TOKEN_COMPLETE
;
388 return auth_
->MaybeGenerateAuthToken(&request_
, io_callback_
, net_log_
);
391 int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result
) {
392 DCHECK_NE(ERR_IO_PENDING
, result
);
394 next_state_
= STATE_SEND_REQUEST
;
398 int HttpProxyClientSocket::DoSendRequest() {
399 next_state_
= STATE_SEND_REQUEST_COMPLETE
;
401 // This is constructed lazily (instead of within our Start method), so that
402 // we have proxy info available.
403 if (request_line_
.empty()) {
404 DCHECK(request_headers_
.IsEmpty());
405 HttpRequestHeaders authorization_headers
;
406 if (auth_
->HaveAuth())
407 auth_
->AddAuthorizationHeader(&authorization_headers
);
408 BuildTunnelRequest(request_
, authorization_headers
, endpoint_
,
409 &request_line_
, &request_headers_
);
412 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
413 base::Bind(&HttpRequestHeaders::NetLogCallback
,
414 base::Unretained(&request_headers_
),
418 parser_buf_
= new GrowableIOBuffer();
419 http_stream_parser_
.reset(new HttpStreamParser(
420 transport_
.get(), &request_
, parser_buf_
.get(), net_log_
));
421 return http_stream_parser_
->SendRequest(
422 request_line_
, request_headers_
, &response_
, io_callback_
);
425 int HttpProxyClientSocket::DoSendRequestComplete(int result
) {
429 next_state_
= STATE_READ_HEADERS
;
433 int HttpProxyClientSocket::DoReadHeaders() {
434 next_state_
= STATE_READ_HEADERS_COMPLETE
;
435 return http_stream_parser_
->ReadResponseHeaders(io_callback_
);
438 int HttpProxyClientSocket::DoReadHeadersComplete(int result
) {
442 // Require the "HTTP/1.x" status line for SSL CONNECT.
443 if (response_
.headers
->GetParsedHttpVersion() < HttpVersion(1, 0))
444 return ERR_TUNNEL_CONNECTION_FAILED
;
447 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
448 base::Bind(&HttpResponseHeaders::NetLogCallback
, response_
.headers
));
450 switch (response_
.headers
->response_code()) {
452 if (http_stream_parser_
->IsMoreDataBuffered())
453 // The proxy sent extraneous data after the headers.
454 return ERR_TUNNEL_CONNECTION_FAILED
;
456 next_state_
= STATE_DONE
;
459 // We aren't able to CONNECT to the remote host through the proxy. We
460 // need to be very suspicious about the response because an active network
461 // attacker can force us into this state by masquerading as the proxy.
462 // The only safe thing to do here is to fail the connection because our
463 // client is expecting an SSL protected response.
464 // See http://crbug.com/7338.
466 case 302: // Found / Moved Temporarily
467 // Attempt to follow redirects from HTTPS proxies, but only if we can
468 // sanitize the response. This still allows a rogue HTTPS proxy to
469 // redirect an HTTPS site load to a similar-looking site, but no longer
470 // allows it to impersonate the site the user requested.
471 if (is_https_proxy_
&& SanitizeProxyRedirect(&response_
, request_
.url
)) {
472 bool is_connection_reused
= http_stream_parser_
->IsConnectionReused();
473 redirect_has_load_timing_info_
=
474 transport_
->GetLoadTimingInfo(
475 is_connection_reused
, &redirect_load_timing_info_
);
477 http_stream_parser_
.reset();
478 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE
;
481 // We're not using an HTTPS proxy, or we couldn't sanitize the redirect.
482 LogBlockedTunnelResponse();
483 return ERR_TUNNEL_CONNECTION_FAILED
;
485 case 407: // Proxy Authentication Required
486 // We need this status code to allow proxy authentication. Our
487 // authentication code is smart enough to avoid being tricked by an
488 // active network attacker.
489 // The next state is intentionally not set as it should be STATE_NONE;
490 return HandleProxyAuthChallenge(auth_
.get(), &response_
, net_log_
);
493 // Ignore response to avoid letting the proxy impersonate the target
494 // server. (See http://crbug.com/137891.)
495 // We lose something by doing this. We have seen proxy 403, 404, and
496 // 501 response bodies that contain a useful error message. For
497 // example, Squid uses a 404 response to report the DNS error: "The
498 // domain name does not exist."
499 LogBlockedTunnelResponse();
500 return ERR_TUNNEL_CONNECTION_FAILED
;
504 int HttpProxyClientSocket::DoDrainBody() {
505 DCHECK(drain_buf_
.get());
506 DCHECK(transport_
->is_initialized());
507 next_state_
= STATE_DRAIN_BODY_COMPLETE
;
508 return http_stream_parser_
->ReadResponseBody(
509 drain_buf_
.get(), kDrainBodyBufferSize
, io_callback_
);
512 int HttpProxyClientSocket::DoDrainBodyComplete(int result
) {
516 if (http_stream_parser_
->IsResponseBodyComplete())
517 return DidDrainBodyForAuthRestart(true);
520 next_state_
= STATE_DRAIN_BODY
;
524 int HttpProxyClientSocket::DoTCPRestart() {
525 next_state_
= STATE_TCP_RESTART_COMPLETE
;
526 return transport_
->socket()->Connect(
527 base::Bind(&HttpProxyClientSocket::OnIOComplete
, base::Unretained(this)));
530 int HttpProxyClientSocket::DoTCPRestartComplete(int result
) {
534 next_state_
= STATE_GENERATE_AUTH_TOKEN
;