Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / http / http_proxy_client_socket.cc
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.
4
5 #include "net/http/http_proxy_client_socket.h"
6
7 #include "base/bind.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"
24 #include "url/gurl.h"
25
26 namespace net {
27
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,
36     bool tunnel,
37     bool using_spdy,
38     NextProto protocol_negotiated,
39     ProxyDelegate* proxy_delegate,
40     bool is_https_proxy)
41     : io_callback_(base::Bind(&HttpProxyClientSocket::OnIOComplete,
42                               base::Unretained(this))),
43       next_state_(STATE_NONE),
44       transport_(transport_socket),
45       endpoint_(endpoint),
46       auth_(tunnel ?
47           new HttpAuthController(HttpAuth::AUTH_PROXY,
48                                  GURL((is_https_proxy ? "https://" : "http://")
49                                       + proxy_server.ToString()),
50                                  http_auth_cache,
51                                  http_auth_handler_factory)
52           : NULL),
53       tunnel_(tunnel),
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,
66                                      user_agent);
67 }
68
69 HttpProxyClientSocket::~HttpProxyClientSocket() {
70   Disconnect();
71 }
72
73 int HttpProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) {
74   DCHECK_EQ(STATE_NONE, next_state_);
75   DCHECK(user_callback_.is_null());
76
77   int rv = PrepareForAuthRestart();
78   if (rv != OK)
79     return rv;
80
81   rv = DoLoop(OK);
82   if (rv == ERR_IO_PENDING) {
83     if (!callback.is_null())
84       user_callback_ =  callback;
85   }
86
87   return rv;
88 }
89
90 const scoped_refptr<HttpAuthController>&
91 HttpProxyClientSocket::GetAuthController() const {
92   return auth_;
93 }
94
95 bool HttpProxyClientSocket::IsUsingSpdy() const {
96   return using_spdy_;
97 }
98
99 NextProto HttpProxyClientSocket::GetProtocolNegotiated() const {
100   return protocol_negotiated_;
101 }
102
103 const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const {
104   return response_.headers.get() ? &response_ : NULL;
105 }
106
107 HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() {
108   return new ProxyConnectRedirectHttpStream(
109       redirect_has_load_timing_info_ ? &redirect_load_timing_info_ : NULL);
110 }
111
112
113 int HttpProxyClientSocket::Connect(const CompletionCallback& callback) {
114   DCHECK(transport_.get());
115   DCHECK(transport_->socket());
116   DCHECK(user_callback_.is_null());
117
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)
126     return OK;
127
128   DCHECK_EQ(STATE_NONE, next_state_);
129   next_state_ = STATE_GENERATE_AUTH_TOKEN;
130
131   int rv = DoLoop(OK);
132   if (rv == ERR_IO_PENDING)
133     user_callback_ = callback;
134   return rv;
135 }
136
137 void HttpProxyClientSocket::Disconnect() {
138   if (transport_.get())
139     transport_->socket()->Disconnect();
140
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();
145 }
146
147 bool HttpProxyClientSocket::IsConnected() const {
148   return next_state_ == STATE_DONE && transport_->socket()->IsConnected();
149 }
150
151 bool HttpProxyClientSocket::IsConnectedAndIdle() const {
152   return next_state_ == STATE_DONE &&
153     transport_->socket()->IsConnectedAndIdle();
154 }
155
156 const BoundNetLog& HttpProxyClientSocket::NetLog() const {
157   return net_log_;
158 }
159
160 void HttpProxyClientSocket::SetSubresourceSpeculation() {
161   if (transport_.get() && transport_->socket()) {
162     transport_->socket()->SetSubresourceSpeculation();
163   } else {
164     NOTREACHED();
165   }
166 }
167
168 void HttpProxyClientSocket::SetOmniboxSpeculation() {
169   if (transport_.get() && transport_->socket()) {
170     transport_->socket()->SetOmniboxSpeculation();
171   } else {
172     NOTREACHED();
173   }
174 }
175
176 bool HttpProxyClientSocket::WasEverUsed() const {
177   if (transport_.get() && transport_->socket()) {
178     return transport_->socket()->WasEverUsed();
179   }
180   NOTREACHED();
181   return false;
182 }
183
184 bool HttpProxyClientSocket::UsingTCPFastOpen() const {
185   if (transport_.get() && transport_->socket()) {
186     return transport_->socket()->UsingTCPFastOpen();
187   }
188   NOTREACHED();
189   return false;
190 }
191
192 bool HttpProxyClientSocket::WasNpnNegotiated() const {
193   if (transport_.get() && transport_->socket()) {
194     return transport_->socket()->WasNpnNegotiated();
195   }
196   NOTREACHED();
197   return false;
198 }
199
200 NextProto HttpProxyClientSocket::GetNegotiatedProtocol() const {
201   if (transport_.get() && transport_->socket()) {
202     return transport_->socket()->GetNegotiatedProtocol();
203   }
204   NOTREACHED();
205   return kProtoUnknown;
206 }
207
208 bool HttpProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
209   if (transport_.get() && transport_->socket()) {
210     return transport_->socket()->GetSSLInfo(ssl_info);
211   }
212   NOTREACHED();
213   return false;
214 }
215
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();
229
230     return ERR_TUNNEL_CONNECTION_FAILED;
231   }
232
233   return transport_->socket()->Read(buf, buf_len, callback);
234 }
235
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());
240
241   return transport_->socket()->Write(buf, buf_len, callback);
242 }
243
244 int HttpProxyClientSocket::SetReceiveBufferSize(int32 size) {
245   return transport_->socket()->SetReceiveBufferSize(size);
246 }
247
248 int HttpProxyClientSocket::SetSendBufferSize(int32 size) {
249   return transport_->socket()->SetSendBufferSize(size);
250 }
251
252 int HttpProxyClientSocket::GetPeerAddress(IPEndPoint* address) const {
253   return transport_->socket()->GetPeerAddress(address);
254 }
255
256 int HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
257   return transport_->socket()->GetLocalAddress(address);
258 }
259
260 int HttpProxyClientSocket::PrepareForAuthRestart() {
261   if (!response_.headers.get())
262     return ERR_CONNECTION_RESET;
263
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);
270       return OK;
271     }
272     keep_alive = true;
273   }
274
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);
278 }
279
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);
284   } else {
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();
289   }
290
291   // Reset the other member variables.
292   drain_buf_ = NULL;
293   parser_buf_ = NULL;
294   http_stream_parser_.reset();
295   request_line_.clear();
296   request_headers_.Clear();
297   response_ = HttpResponseInfo();
298   return OK;
299 }
300
301 void HttpProxyClientSocket::LogBlockedTunnelResponse() const {
302   ProxyClientSocket::LogBlockedTunnelResponse(
303       response_.headers->response_code(),
304       request_.url,
305       is_https_proxy_);
306 }
307
308 void HttpProxyClientSocket::DoCallback(int result) {
309   DCHECK_NE(ERR_IO_PENDING, result);
310   DCHECK(!user_callback_.is_null());
311
312   // Since Run() may result in Read being called,
313   // clear user_callback_ up front.
314   CompletionCallback c = user_callback_;
315   user_callback_.Reset();
316   c.Run(result);
317 }
318
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)
324     DoCallback(rv);
325 }
326
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;
331   do {
332     State state = next_state_;
333     next_state_ = STATE_NONE;
334     switch (state) {
335       case STATE_GENERATE_AUTH_TOKEN:
336         DCHECK_EQ(OK, rv);
337         rv = DoGenerateAuthToken();
338         break;
339       case STATE_GENERATE_AUTH_TOKEN_COMPLETE:
340         rv = DoGenerateAuthTokenComplete(rv);
341         break;
342       case STATE_SEND_REQUEST:
343         DCHECK_EQ(OK, rv);
344         net_log_.BeginEvent(
345             NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST);
346         rv = DoSendRequest();
347         break;
348       case STATE_SEND_REQUEST_COMPLETE:
349         rv = DoSendRequestComplete(rv);
350         net_log_.EndEventWithNetErrorCode(
351             NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
352         break;
353       case STATE_READ_HEADERS:
354         DCHECK_EQ(OK, rv);
355         net_log_.BeginEvent(
356             NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS);
357         rv = DoReadHeaders();
358         break;
359       case STATE_READ_HEADERS_COMPLETE:
360         rv = DoReadHeadersComplete(rv);
361         net_log_.EndEventWithNetErrorCode(
362             NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
363         break;
364       case STATE_DRAIN_BODY:
365         DCHECK_EQ(OK, rv);
366         rv = DoDrainBody();
367         break;
368       case STATE_DRAIN_BODY_COMPLETE:
369         rv = DoDrainBodyComplete(rv);
370         break;
371       case STATE_TCP_RESTART:
372         DCHECK_EQ(OK, rv);
373         rv = DoTCPRestart();
374         break;
375       case STATE_TCP_RESTART_COMPLETE:
376         rv = DoTCPRestartComplete(rv);
377         break;
378       case STATE_DONE:
379         break;
380       default:
381         NOTREACHED() << "bad state";
382         rv = ERR_UNEXPECTED;
383         break;
384     }
385   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE &&
386            next_state_ != STATE_DONE);
387   return rv;
388 }
389
390 int HttpProxyClientSocket::DoGenerateAuthToken() {
391   next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
392   return auth_->MaybeGenerateAuthToken(&request_, io_callback_, net_log_);
393 }
394
395 int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) {
396   DCHECK_NE(ERR_IO_PENDING, result);
397   if (result == OK)
398     next_state_ = STATE_SEND_REQUEST;
399   return result;
400 }
401
402 int HttpProxyClientSocket::DoSendRequest() {
403   next_state_ = STATE_SEND_REQUEST_COMPLETE;
404
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);
415     }
416     BuildTunnelRequest(request_, authorization_headers, endpoint_,
417                        &request_line_, &request_headers_);
418
419     net_log_.AddEvent(
420         NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
421         base::Bind(&HttpRequestHeaders::NetLogCallback,
422                    base::Unretained(&request_headers_),
423                    &request_line_));
424   }
425
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_);
431 }
432
433 int HttpProxyClientSocket::DoSendRequestComplete(int result) {
434   if (result < 0)
435     return result;
436
437   next_state_ = STATE_READ_HEADERS;
438   return OK;
439 }
440
441 int HttpProxyClientSocket::DoReadHeaders() {
442   next_state_ = STATE_READ_HEADERS_COMPLETE;
443   return http_stream_parser_->ReadResponseHeaders(io_callback_);
444 }
445
446 int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
447   if (result < 0)
448     return result;
449
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;
453
454   net_log_.AddEvent(
455       NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
456       base::Bind(&HttpResponseHeaders::NetLogCallback, response_.headers));
457
458   if (proxy_delegate_) {
459     proxy_delegate_->OnTunnelHeadersReceived(
460         HostPortPair::FromURL(request_.url),
461         proxy_server_,
462         *response_.headers);
463   }
464
465   switch (response_.headers->response_code()) {
466     case 200:  // OK
467       if (http_stream_parser_->IsMoreDataBuffered())
468         // The proxy sent extraneous data after the headers.
469         return ERR_TUNNEL_CONNECTION_FAILED;
470
471       next_state_ = STATE_DONE;
472       return OK;
473
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.
480
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_);
491         transport_.reset();
492         http_stream_parser_.reset();
493         return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
494       }
495
496       // We're not using an HTTPS proxy, or we couldn't sanitize the redirect.
497       LogBlockedTunnelResponse();
498       return ERR_TUNNEL_CONNECTION_FAILED;
499
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_);
506
507     default:
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;
516   }
517 }
518
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_);
525 }
526
527 int HttpProxyClientSocket::DoDrainBodyComplete(int result) {
528   if (result < 0)
529     return result;
530
531   if (http_stream_parser_->IsResponseBodyComplete())
532     return DidDrainBodyForAuthRestart(true);
533
534   // Keep draining.
535   next_state_ = STATE_DRAIN_BODY;
536   return OK;
537 }
538
539 int HttpProxyClientSocket::DoTCPRestart() {
540   next_state_ = STATE_TCP_RESTART_COMPLETE;
541   return transport_->socket()->Connect(
542       base::Bind(&HttpProxyClientSocket::OnIOComplete, base::Unretained(this)));
543 }
544
545 int HttpProxyClientSocket::DoTCPRestartComplete(int result) {
546   if (result != OK)
547     return result;
548
549   next_state_ = STATE_GENERATE_AUTH_TOKEN;
550   return result;
551 }
552
553 }  // namespace net