1 // Copyright (c) 2006-2009 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_network_transaction.h"
6
7 #include "base/format_macros.h"
8 #include "base/scoped_ptr.h"
9 #include "base/compiler_specific.h"
10 #include "base/field_trial.h"
11 #include "base/histogram.h"
12 #include "base/stats_counters.h"
13 #include "base/string_util.h"
14 #include "base/trace_event.h"
15 #include "build/build_config.h"
16 #include "net/base/connection_type_histograms.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/load_flags.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/net_util.h"
21 #include "net/base/ssl_cert_request_info.h"
22 #include "net/base/upload_data_stream.h"
23 #include "net/flip/flip_session.h"
24 #include "net/flip/flip_session_pool.h"
25 #include "net/flip/flip_stream.h"
26 #include "net/http/http_auth.h"
27 #include "net/http/http_auth_handler.h"
28 #include "net/http/http_basic_stream.h"
29 #include "net/http/http_chunked_decoder.h"
30 #include "net/http/http_network_session.h"
31 #include "net/http/http_request_info.h"
32 #include "net/http/http_response_headers.h"
33 #include "net/http/http_response_info.h"
34 #include "net/http/http_util.h"
35 #include "net/socket/client_socket_factory.h"
36 #include "net/socket/socks5_client_socket.h"
37 #include "net/socket/socks_client_socket.h"
38 #include "net/socket/ssl_client_socket.h"
39
40 using base::Time;
41
42 namespace net {
43
44 namespace {
45
BuildRequestHeaders(const HttpRequestInfo * request_info,const std::string & authorization_headers,const UploadDataStream * upload_data_stream,bool using_proxy,std::string * request_headers)46 void BuildRequestHeaders(const HttpRequestInfo* request_info,
47 const std::string& authorization_headers,
48 const UploadDataStream* upload_data_stream,
49 bool using_proxy,
50 std::string* request_headers) {
51 const std::string path = using_proxy ?
52 HttpUtil::SpecForRequest(request_info->url) :
53 HttpUtil::PathForRequest(request_info->url);
54 *request_headers =
55 StringPrintf("%s %s HTTP/1.1\r\nHost: %s\r\n",
56 request_info->method.c_str(), path.c_str(),
57 GetHostAndOptionalPort(request_info->url).c_str());
58
59 // For compat with HTTP/1.0 servers and proxies:
60 if (using_proxy)
61 *request_headers += "Proxy-";
62 *request_headers += "Connection: keep-alive\r\n";
63
64 if (!request_info->user_agent.empty()) {
65 StringAppendF(request_headers, "User-Agent: %s\r\n",
66 request_info->user_agent.c_str());
67 }
68
69 // Our consumer should have made sure that this is a safe referrer. See for
70 // instance WebCore::FrameLoader::HideReferrer.
71 if (request_info->referrer.is_valid())
72 StringAppendF(request_headers, "Referer: %s\r\n",
73 request_info->referrer.spec().c_str());
74
75 // Add a content length header?
76 if (upload_data_stream) {
77 StringAppendF(request_headers, "Content-Length: %" PRIu64 "\r\n",
78 upload_data_stream->size());
79 } else if (request_info->method == "POST" || request_info->method == "PUT" ||
80 request_info->method == "HEAD") {
81 // An empty POST/PUT request still needs a content length. As for HEAD,
82 // IE and Safari also add a content length header. Presumably it is to
83 // support sending a HEAD request to an URL that only expects to be sent a
84 // POST or some other method that normally would have a message body.
85 *request_headers += "Content-Length: 0\r\n";
86 }
87
88 // Honor load flags that impact proxy caches.
89 if (request_info->load_flags & LOAD_BYPASS_CACHE) {
90 *request_headers += "Pragma: no-cache\r\nCache-Control: no-cache\r\n";
91 } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) {
92 *request_headers += "Cache-Control: max-age=0\r\n";
93 }
94
95 if (!authorization_headers.empty()) {
96 *request_headers += authorization_headers;
97 }
98
99 // TODO(darin): Need to prune out duplicate headers.
100
101 *request_headers += request_info->extra_headers;
102 *request_headers += "\r\n";
103 }
104
105 // The HTTP CONNECT method for establishing a tunnel connection is documented
106 // in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and
107 // 5.3.
BuildTunnelRequest(const HttpRequestInfo * request_info,const std::string & authorization_headers,std::string * request_headers)108 void BuildTunnelRequest(const HttpRequestInfo* request_info,
109 const std::string& authorization_headers,
110 std::string* request_headers) {
111 // RFC 2616 Section 9 says the Host request-header field MUST accompany all
112 // HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with
113 // HTTP/1.0 proxies such as Squid (required for NTLM authentication).
114 *request_headers = StringPrintf(
115 "CONNECT %s HTTP/1.1\r\nHost: %s\r\nProxy-Connection: keep-alive\r\n",
116 GetHostAndPort(request_info->url).c_str(),
117 GetHostAndOptionalPort(request_info->url).c_str());
118
119 if (!request_info->user_agent.empty())
120 StringAppendF(request_headers, "User-Agent: %s\r\n",
121 request_info->user_agent.c_str());
122
123 if (!authorization_headers.empty()) {
124 *request_headers += authorization_headers;
125 }
126
127 *request_headers += "\r\n";
128 }
129
130 } // namespace
131
132 //-----------------------------------------------------------------------------
133
134 std::string* HttpNetworkTransaction::g_next_protos = NULL;
135
HttpNetworkTransaction(HttpNetworkSession * session)136 HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
137 : pending_auth_target_(HttpAuth::AUTH_NONE),
138 ALLOW_THIS_IN_INITIALIZER_LIST(
139 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
140 user_callback_(NULL),
141 session_(session),
142 request_(NULL),
143 pac_request_(NULL),
144 connection_(new ClientSocketHandle),
145 reused_socket_(false),
146 headers_valid_(false),
147 logged_response_time(false),
148 using_ssl_(false),
149 proxy_mode_(kDirectConnection),
150 establishing_tunnel_(false),
151 embedded_identity_used_(false),
152 read_buf_len_(0),
153 next_state_(STATE_NONE) {
154 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
155 if (g_next_protos)
156 ssl_config_.next_protos = *g_next_protos;
157 }
158
159 // static
SetNextProtos(const std::string & next_protos)160 void HttpNetworkTransaction::SetNextProtos(const std::string& next_protos) {
161 delete g_next_protos;
162 g_next_protos = new std::string(next_protos);
163 }
164
Start(const HttpRequestInfo * request_info,CompletionCallback * callback,LoadLog * load_log)165 int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
166 CompletionCallback* callback,
167 LoadLog* load_log) {
168 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
169
170 load_log_ = load_log;
171 request_ = request_info;
172 start_time_ = base::Time::Now();
173
174 next_state_ = STATE_RESOLVE_PROXY;
175 int rv = DoLoop(OK);
176 if (rv == ERR_IO_PENDING)
177 user_callback_ = callback;
178 return rv;
179 }
180
RestartIgnoringLastError(CompletionCallback * callback)181 int HttpNetworkTransaction::RestartIgnoringLastError(
182 CompletionCallback* callback) {
183 if (connection_->socket()->IsConnectedAndIdle()) {
184 next_state_ = STATE_SEND_REQUEST;
185 } else {
186 connection_->socket()->Disconnect();
187 connection_->Reset();
188 next_state_ = STATE_INIT_CONNECTION;
189 }
190 int rv = DoLoop(OK);
191 if (rv == ERR_IO_PENDING)
192 user_callback_ = callback;
193 return rv;
194 }
195
RestartWithCertificate(X509Certificate * client_cert,CompletionCallback * callback)196 int HttpNetworkTransaction::RestartWithCertificate(
197 X509Certificate* client_cert,
198 CompletionCallback* callback) {
199 ssl_config_.client_cert = client_cert;
200 if (client_cert) {
201 session_->ssl_client_auth_cache()->Add(GetHostAndPort(request_->url),
202 client_cert);
203 }
204 ssl_config_.send_client_cert = true;
205 next_state_ = STATE_INIT_CONNECTION;
206 // Reset the other member variables.
207 // Note: this is necessary only with SSL renegotiation.
208 ResetStateForRestart();
209 int rv = DoLoop(OK);
210 if (rv == ERR_IO_PENDING)
211 user_callback_ = callback;
212 return rv;
213 }
214
RestartWithAuth(const std::wstring & username,const std::wstring & password,CompletionCallback * callback)215 int HttpNetworkTransaction::RestartWithAuth(
216 const std::wstring& username,
217 const std::wstring& password,
218 CompletionCallback* callback) {
219 HttpAuth::Target target = pending_auth_target_;
220 if (target == HttpAuth::AUTH_NONE) {
221 NOTREACHED();
222 return ERR_UNEXPECTED;
223 }
224
225 pending_auth_target_ = HttpAuth::AUTH_NONE;
226
227 DCHECK(auth_identity_[target].invalid ||
228 (username.empty() && password.empty()));
229
230 if (auth_identity_[target].invalid) {
231 // Update the username/password.
232 auth_identity_[target].source = HttpAuth::IDENT_SRC_EXTERNAL;
233 auth_identity_[target].invalid = false;
234 auth_identity_[target].username = username;
235 auth_identity_[target].password = password;
236 }
237
238 PrepareForAuthRestart(target);
239
240 DCHECK(user_callback_ == NULL);
241 int rv = DoLoop(OK);
242 if (rv == ERR_IO_PENDING)
243 user_callback_ = callback;
244
245 return rv;
246 }
247
PrepareForAuthRestart(HttpAuth::Target target)248 void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
249 DCHECK(HaveAuth(target));
250 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP);
251
252 // Add the auth entry to the cache before restarting. We don't know whether
253 // the identity is valid yet, but if it is valid we want other transactions
254 // to know about it. If an entry for (origin, handler->realm()) already
255 // exists, we update it.
256 //
257 // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE,
258 // auth_identity_[target] contains no identity because identity is not
259 // required yet.
260 //
261 // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in
262 // round 1 and round 2, which is redundant but correct. It would be nice
263 // to add an auth entry to the cache only once, preferrably in round 1.
264 // See http://crbug.com/21015.
265 bool has_auth_identity =
266 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE;
267 if (has_auth_identity) {
268 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target],
269 auth_identity_[target].username, auth_identity_[target].password,
270 AuthPath(target));
271 }
272
273 bool keep_alive = false;
274 // Even if the server says the connection is keep-alive, we have to be
275 // able to find the end of each response in order to reuse the connection.
276 if (GetResponseHeaders()->IsKeepAlive() &&
277 http_stream_->CanFindEndOfResponse()) {
278 // If the response body hasn't been completely read, we need to drain
279 // it first.
280 if (!http_stream_->IsResponseBodyComplete()) {
281 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
282 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
283 read_buf_len_ = kDrainBodyBufferSize;
284 return;
285 }
286 keep_alive = true;
287 }
288
289 // We don't need to drain the response body, so we act as if we had drained
290 // the response body.
291 DidDrainBodyForAuthRestart(keep_alive);
292 }
293
DidDrainBodyForAuthRestart(bool keep_alive)294 void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
295 if (keep_alive && connection_->socket()->IsConnectedAndIdle()) {
296 // We should call connection_->set_idle_time(), but this doesn't occur
297 // often enough to be worth the trouble.
298 next_state_ = STATE_SEND_REQUEST;
299 connection_->set_is_reused(true);
300 reused_socket_ = true;
301 } else {
302 next_state_ = STATE_INIT_CONNECTION;
303 connection_->socket()->Disconnect();
304 connection_->Reset();
305 }
306
307 // Reset the other member variables.
308 ResetStateForRestart();
309 }
310
Read(IOBuffer * buf,int buf_len,CompletionCallback * callback)311 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
312 CompletionCallback* callback) {
313 DCHECK(buf);
314 DCHECK_LT(0, buf_len);
315
316 State next_state = STATE_NONE;
317
318 // Are we using SPDY or HTTP?
319 if (spdy_stream_.get()) {
320 DCHECK(!http_stream_.get());
321 DCHECK(spdy_stream_->GetResponseInfo()->headers);
322 next_state = STATE_SPDY_READ_BODY;
323 } else {
324 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
325 DCHECK(headers.get());
326 next_state = STATE_READ_BODY;
327
328 if (!connection_->is_initialized())
329 return 0; // connection_->has been reset. Treat like EOF.
330
331 if (establishing_tunnel_) {
332 // We're trying to read the body of the response but we're still trying
333 // to establish an SSL tunnel through the proxy. We can't read these
334 // bytes when establishing a tunnel because they might be controlled by
335 // an active network attacker. We don't worry about this for HTTP
336 // because an active network attacker can already control HTTP sessions.
337 // We reach this case when the user cancels a 407 proxy auth prompt.
338 // See http://crbug.com/8473.
339 DCHECK_EQ(407, headers->response_code());
340 LogBlockedTunnelResponse(headers->response_code());
341 return ERR_TUNNEL_CONNECTION_FAILED;
342 }
343 }
344
345 read_buf_ = buf;
346 read_buf_len_ = buf_len;
347
348 next_state_ = next_state;
349 int rv = DoLoop(OK);
350 if (rv == ERR_IO_PENDING)
351 user_callback_ = callback;
352 return rv;
353 }
354
GetResponseInfo() const355 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
356 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
357 response_.cert_request_info) ? &response_ : NULL;
358 }
359
GetLoadState() const360 LoadState HttpNetworkTransaction::GetLoadState() const {
361 // TODO(wtc): Define a new LoadState value for the
362 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
363 switch (next_state_) {
364 case STATE_RESOLVE_PROXY_COMPLETE:
365 return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
366 case STATE_INIT_CONNECTION_COMPLETE:
367 return connection_->GetLoadState();
368 case STATE_SEND_REQUEST_COMPLETE:
369 return LOAD_STATE_SENDING_REQUEST;
370 case STATE_READ_HEADERS_COMPLETE:
371 return LOAD_STATE_WAITING_FOR_RESPONSE;
372 case STATE_READ_BODY_COMPLETE:
373 return LOAD_STATE_READING_RESPONSE;
374 default:
375 return LOAD_STATE_IDLE;
376 }
377 }
378
GetUploadProgress() const379 uint64 HttpNetworkTransaction::GetUploadProgress() const {
380 if (!http_stream_.get())
381 return 0;
382
383 return http_stream_->GetUploadProgress();
384 }
385
~HttpNetworkTransaction()386 HttpNetworkTransaction::~HttpNetworkTransaction() {
387 // If we still have an open socket, then make sure to disconnect it so it
388 // won't call us back and we don't try to reuse it later on.
389 if (connection_.get() && connection_->is_initialized())
390 connection_->socket()->Disconnect();
391
392 if (pac_request_)
393 session_->proxy_service()->CancelPacRequest(pac_request_);
394
395 if (spdy_stream_.get())
396 spdy_stream_->Cancel();
397 }
398
DoCallback(int rv)399 void HttpNetworkTransaction::DoCallback(int rv) {
400 DCHECK(rv != ERR_IO_PENDING);
401 DCHECK(user_callback_);
402
403 // Since Run may result in Read being called, clear user_callback_ up front.
404 CompletionCallback* c = user_callback_;
405 user_callback_ = NULL;
406 c->Run(rv);
407 }
408
OnIOComplete(int result)409 void HttpNetworkTransaction::OnIOComplete(int result) {
410 int rv = DoLoop(result);
411 if (rv != ERR_IO_PENDING)
412 DoCallback(rv);
413 }
414
DoLoop(int result)415 int HttpNetworkTransaction::DoLoop(int result) {
416 DCHECK(next_state_ != STATE_NONE);
417
418 int rv = result;
419 do {
420 State state = next_state_;
421 next_state_ = STATE_NONE;
422 switch (state) {
423 case STATE_RESOLVE_PROXY:
424 DCHECK_EQ(OK, rv);
425 TRACE_EVENT_BEGIN("http.resolve_proxy", request_, request_->url.spec());
426 rv = DoResolveProxy();
427 break;
428 case STATE_RESOLVE_PROXY_COMPLETE:
429 rv = DoResolveProxyComplete(rv);
430 TRACE_EVENT_END("http.resolve_proxy", request_, request_->url.spec());
431 break;
432 case STATE_INIT_CONNECTION:
433 DCHECK_EQ(OK, rv);
434 TRACE_EVENT_BEGIN("http.init_conn", request_, request_->url.spec());
435 rv = DoInitConnection();
436 break;
437 case STATE_INIT_CONNECTION_COMPLETE:
438 rv = DoInitConnectionComplete(rv);
439 TRACE_EVENT_END("http.init_conn", request_, request_->url.spec());
440 break;
441 case STATE_SOCKS_CONNECT:
442 DCHECK_EQ(OK, rv);
443 TRACE_EVENT_BEGIN("http.socks_connect", request_, request_->url.spec());
444 rv = DoSOCKSConnect();
445 break;
446 case STATE_SOCKS_CONNECT_COMPLETE:
447 rv = DoSOCKSConnectComplete(rv);
448 TRACE_EVENT_END("http.socks_connect", request_, request_->url.spec());
449 break;
450 case STATE_SSL_CONNECT:
451 DCHECK_EQ(OK, rv);
452 TRACE_EVENT_BEGIN("http.ssl_connect", request_, request_->url.spec());
453 rv = DoSSLConnect();
454 break;
455 case STATE_SSL_CONNECT_COMPLETE:
456 rv = DoSSLConnectComplete(rv);
457 TRACE_EVENT_END("http.ssl_connect", request_, request_->url.spec());
458 break;
459 case STATE_SEND_REQUEST:
460 DCHECK_EQ(OK, rv);
461 TRACE_EVENT_BEGIN("http.send_request", request_, request_->url.spec());
462 LoadLog::BeginEvent(load_log_,
463 LoadLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST);
464 rv = DoSendRequest();
465 break;
466 case STATE_SEND_REQUEST_COMPLETE:
467 rv = DoSendRequestComplete(rv);
468 TRACE_EVENT_END("http.send_request", request_, request_->url.spec());
469 LoadLog::EndEvent(load_log_,
470 LoadLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST);
471 break;
472 case STATE_READ_HEADERS:
473 DCHECK_EQ(OK, rv);
474 TRACE_EVENT_BEGIN("http.read_headers", request_, request_->url.spec());
475 LoadLog::BeginEvent(load_log_,
476 LoadLog::TYPE_HTTP_TRANSACTION_READ_HEADERS);
477 rv = DoReadHeaders();
478 break;
479 case STATE_READ_HEADERS_COMPLETE:
480 rv = DoReadHeadersComplete(rv);
481 TRACE_EVENT_END("http.read_headers", request_, request_->url.spec());
482 LoadLog::EndEvent(load_log_,
483 LoadLog::TYPE_HTTP_TRANSACTION_READ_HEADERS);
484 break;
485 case STATE_READ_BODY:
486 DCHECK_EQ(OK, rv);
487 TRACE_EVENT_BEGIN("http.read_body", request_, request_->url.spec());
488 LoadLog::BeginEvent(load_log_,
489 LoadLog::TYPE_HTTP_TRANSACTION_READ_BODY);
490 rv = DoReadBody();
491 break;
492 case STATE_READ_BODY_COMPLETE:
493 rv = DoReadBodyComplete(rv);
494 TRACE_EVENT_END("http.read_body", request_, request_->url.spec());
495 LoadLog::EndEvent(load_log_,
496 LoadLog::TYPE_HTTP_TRANSACTION_READ_BODY);
497 break;
498 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
499 DCHECK_EQ(OK, rv);
500 TRACE_EVENT_BEGIN("http.drain_body_for_auth_restart",
501 request_, request_->url.spec());
502 LoadLog::BeginEvent(
503 load_log_,
504 LoadLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART);
505 rv = DoDrainBodyForAuthRestart();
506 break;
507 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
508 rv = DoDrainBodyForAuthRestartComplete(rv);
509 TRACE_EVENT_END("http.drain_body_for_auth_restart",
510 request_, request_->url.spec());
511 LoadLog::EndEvent(
512 load_log_,
513 LoadLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART);
514 break;
515 case STATE_SPDY_SEND_REQUEST:
516 DCHECK_EQ(OK, rv);
517 TRACE_EVENT_BEGIN("http.send_request", request_, request_->url.spec());
518 LoadLog::BeginEvent(load_log_,
519 LoadLog::TYPE_FLIP_TRANSACTION_SEND_REQUEST);
520 rv = DoSpdySendRequest();
521 break;
522 case STATE_SPDY_SEND_REQUEST_COMPLETE:
523 rv = DoSpdySendRequestComplete(rv);
524 TRACE_EVENT_END("http.send_request", request_, request_->url.spec());
525 LoadLog::EndEvent(load_log_,
526 LoadLog::TYPE_FLIP_TRANSACTION_SEND_REQUEST);
527 break;
528 case STATE_SPDY_READ_HEADERS:
529 DCHECK_EQ(OK, rv);
530 TRACE_EVENT_BEGIN("http.read_headers", request_, request_->url.spec());
531 LoadLog::BeginEvent(load_log_,
532 LoadLog::TYPE_FLIP_TRANSACTION_READ_HEADERS);
533 rv = DoSpdyReadHeaders();
534 break;
535 case STATE_SPDY_READ_HEADERS_COMPLETE:
536 rv = DoSpdyReadHeadersComplete(rv);
537 TRACE_EVENT_END("http.read_headers", request_, request_->url.spec());
538 LoadLog::EndEvent(load_log_,
539 LoadLog::TYPE_FLIP_TRANSACTION_READ_HEADERS);
540 break;
541 case STATE_SPDY_READ_BODY:
542 DCHECK_EQ(OK, rv);
543 TRACE_EVENT_BEGIN("http.read_body", request_, request_->url.spec());
544 LoadLog::BeginEvent(load_log_,
545 LoadLog::TYPE_FLIP_TRANSACTION_READ_BODY);
546 rv = DoSpdyReadBody();
547 break;
548 case STATE_SPDY_READ_BODY_COMPLETE:
549 rv = DoSpdyReadBodyComplete(rv);
550 TRACE_EVENT_END("http.read_body", request_, request_->url.spec());
551 LoadLog::EndEvent(load_log_,
552 LoadLog::TYPE_FLIP_TRANSACTION_READ_BODY);
553 break;
554 default:
555 NOTREACHED() << "bad state";
556 rv = ERR_FAILED;
557 break;
558 }
559 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
560
561 return rv;
562 }
563
DoResolveProxy()564 int HttpNetworkTransaction::DoResolveProxy() {
565 DCHECK(!pac_request_);
566
567 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
568
569 if (request_->load_flags & LOAD_BYPASS_PROXY) {
570 proxy_info_.UseDirect();
571 return OK;
572 }
573
574 return session_->proxy_service()->ResolveProxy(
575 request_->url, &proxy_info_, &io_callback_, &pac_request_, load_log_);
576 }
577
DoResolveProxyComplete(int result)578 int HttpNetworkTransaction::DoResolveProxyComplete(int result) {
579
580 pac_request_ = NULL;
581
582 if (result != OK) {
583 DLOG(ERROR) << "Failed to resolve proxy: " << result;
584 // Fall-back to direct when there were runtime errors in the PAC script,
585 // or some other failure with the settings.
586 proxy_info_.UseDirect();
587 }
588
589 // Remove unsupported proxies from the list.
590 proxy_info_.RemoveProxiesWithoutScheme(
591 ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP |
592 ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
593
594 // There are four possible outcomes of having run the ProxyService:
595 // (1) The ProxyService decided we should connect through a proxy.
596 // (2) The ProxyService decided we should direct-connect.
597 // (3) The ProxyService decided we should give up, as there are no more
598 // proxies to try (this is more likely to happen during
599 // ReconsiderProxyAfterError()).
600 // (4) The ProxyService failed (which can happen if the PAC script
601 // we were configured with threw a runtime exception).
602 //
603 // It is important that we fail the connection in case (3) rather than
604 // falling-back to a direct connection, since sending traffic through
605 // a proxy may be integral to the user's privacy/security model.
606 //
607 // For example if a user had configured traffic to go through the TOR
608 // anonymizing proxy to protect their privacy, it would be bad if we
609 // silently fell-back to direct connect if the proxy server were to
610 // become unreachable.
611 //
612 // In case (4) it is less obvious what the right thing to do is. On the
613 // one hand, for consistency it would be natural to hard-fail as well.
614 // However, both Firefox 3.5 and Internet Explorer 8 will silently fall-back
615 // to DIRECT in this case, so we will do the same for compatibility.
616 //
617 // For more information, see:
618 // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
619
620 if (proxy_info_.is_empty()) {
621 // No proxies/direct to choose from. This happens when we don't support any
622 // of the proxies in the returned list.
623 return ERR_NO_SUPPORTED_PROXIES;
624 }
625
626 next_state_ = STATE_INIT_CONNECTION;
627 return OK;
628 }
629
DoInitConnection()630 int HttpNetworkTransaction::DoInitConnection() {
631 DCHECK(!connection_->is_initialized());
632 DCHECK(proxy_info_.proxy_server().is_valid());
633
634 next_state_ = STATE_INIT_CONNECTION_COMPLETE;
635
636 using_ssl_ = request_->url.SchemeIs("https");
637
638 if (proxy_info_.is_direct())
639 proxy_mode_ = kDirectConnection;
640 else if (proxy_info_.proxy_server().is_socks())
641 proxy_mode_ = kSOCKSProxy;
642 else if (using_ssl_)
643 proxy_mode_ = kHTTPProxyUsingTunnel;
644 else
645 proxy_mode_ = kHTTPProxy;
646
647 // Build the string used to uniquely identify connections of this type.
648 // Determine the host and port to connect to.
649 std::string connection_group;
650 std::string host;
651 int port;
652 if (proxy_mode_ != kDirectConnection) {
653 ProxyServer proxy_server = proxy_info_.proxy_server();
654 connection_group = "proxy/" + proxy_server.ToURI() + "/";
655 host = proxy_server.HostNoBrackets();
656 port = proxy_server.port();
657 } else {
658 host = request_->url.HostNoBrackets();
659 port = request_->url.EffectiveIntPort();
660 }
661
662 // Use the fixed testing ports if they've been provided.
663 if (using_ssl_) {
664 if (session_->fixed_https_port() != 0)
665 port = session_->fixed_https_port();
666 } else if (session_->fixed_http_port() != 0) {
667 port = session_->fixed_http_port();
668 }
669
670 // For a connection via HTTP proxy not using CONNECT, the connection
671 // is to the proxy server only. For all other cases
672 // (direct, HTTP proxy CONNECT, SOCKS), the connection is upto the
673 // url endpoint. Hence we append the url data into the connection_group.
674 if (proxy_mode_ != kHTTPProxy)
675 connection_group.append(request_->url.GetOrigin().spec());
676
677 DCHECK(!connection_group.empty());
678
679 HostResolver::RequestInfo resolve_info(host, port);
680 resolve_info.set_priority(request_->priority);
681
682 // The referrer is used by the DNS prefetch system to correlate resolutions
683 // with the page that triggered them. It doesn't impact the actual addresses
684 // that we resolve to.
685 resolve_info.set_referrer(request_->referrer);
686
687 // If the user is refreshing the page, bypass the host cache.
688 if (request_->load_flags & LOAD_BYPASS_CACHE ||
689 request_->load_flags & LOAD_DISABLE_CACHE) {
690 resolve_info.set_allow_cached_response(false);
691 }
692
693 // Check first if we have a flip session for this group. If so, then go
694 // straight to using that.
695 if (session_->flip_session_pool()->HasSession(resolve_info))
696 return OK;
697
698 int rv = connection_->Init(connection_group, resolve_info, request_->priority,
699 &io_callback_, session_->tcp_socket_pool(),
700 load_log_);
701 return rv;
702 }
703
DoInitConnectionComplete(int result)704 int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
705 if (result < 0) {
706 UpdateConnectionTypeHistograms(CONNECTION_HTTP, false);
707 return ReconsiderProxyAfterError(result);
708 }
709
710 DCHECK_EQ(OK, result);
711
712 // If we don't have an initialized connection, that means we have a flip
713 // connection waiting for us.
714 if (!connection_->is_initialized()) {
715 next_state_ = STATE_SPDY_SEND_REQUEST;
716 return OK;
717 }
718
719 LogTCPConnectedMetrics(*connection_);
720
721 // Set the reused_socket_ flag to indicate that we are using a keep-alive
722 // connection. This flag is used to handle errors that occur while we are
723 // trying to reuse a keep-alive connection.
724 reused_socket_ = connection_->is_reused();
725 if (reused_socket_) {
726 next_state_ = STATE_SEND_REQUEST;
727 } else {
728 // Now we have a TCP connected socket. Perform other connection setup as
729 // needed.
730 UpdateConnectionTypeHistograms(CONNECTION_HTTP, true);
731 if (proxy_mode_ == kSOCKSProxy)
732 next_state_ = STATE_SOCKS_CONNECT;
733 else if (using_ssl_ && proxy_mode_ == kDirectConnection) {
734 next_state_ = STATE_SSL_CONNECT;
735 } else {
736 next_state_ = STATE_SEND_REQUEST;
737 if (proxy_mode_ == kHTTPProxyUsingTunnel)
738 establishing_tunnel_ = true;
739 }
740 }
741
742 return OK;
743 }
744
DoSOCKSConnect()745 int HttpNetworkTransaction::DoSOCKSConnect() {
746 DCHECK_EQ(kSOCKSProxy, proxy_mode_);
747
748 next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
749
750 // Add a SOCKS connection on top of our existing transport socket.
751 ClientSocket* s = connection_->release_socket();
752 HostResolver::RequestInfo req_info(request_->url.HostNoBrackets(),
753 request_->url.EffectiveIntPort());
754 req_info.set_referrer(request_->referrer);
755 req_info.set_priority(request_->priority);
756
757 if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5)
758 s = new SOCKS5ClientSocket(s, req_info);
759 else
760 s = new SOCKSClientSocket(s, req_info, session_->host_resolver());
761 connection_->set_socket(s);
762 return connection_->socket()->Connect(&io_callback_, load_log_);
763 }
764
DoSOCKSConnectComplete(int result)765 int HttpNetworkTransaction::DoSOCKSConnectComplete(int result) {
766 DCHECK_EQ(kSOCKSProxy, proxy_mode_);
767
768 if (result == OK) {
769 if (using_ssl_) {
770 next_state_ = STATE_SSL_CONNECT;
771 } else {
772 next_state_ = STATE_SEND_REQUEST;
773 }
774 } else {
775 result = ReconsiderProxyAfterError(result);
776 }
777 return result;
778 }
779
DoSSLConnect()780 int HttpNetworkTransaction::DoSSLConnect() {
781 next_state_ = STATE_SSL_CONNECT_COMPLETE;
782
783 if (request_->load_flags & LOAD_VERIFY_EV_CERT)
784 ssl_config_.verify_ev_cert = true;
785
786 ssl_connect_start_time_ = base::TimeTicks::Now();
787
788 // Add a SSL socket on top of our existing transport socket.
789 ClientSocket* s = connection_->release_socket();
790 s = session_->socket_factory()->CreateSSLClientSocket(
791 s, request_->url.HostNoBrackets(), ssl_config_);
792 connection_->set_socket(s);
793 return connection_->socket()->Connect(&io_callback_, load_log_);
794 }
795
DoSSLConnectComplete(int result)796 int HttpNetworkTransaction::DoSSLConnectComplete(int result) {
797 SSLClientSocket* ssl_socket =
798 reinterpret_cast<SSLClientSocket*>(connection_->socket());
799
800 SSLClientSocket::NextProtoStatus status =
801 SSLClientSocket::kNextProtoUnsupported;
802 std::string proto;
803 // GetNextProto will fail and and trigger a NOTREACHED if we pass in a socket
804 // that hasn't had SSL_ImportFD called on it. If we get a certificate error
805 // here, then we know that we called SSL_ImportFD.
806 if (result == OK || IsCertificateError(result))
807 status = ssl_socket->GetNextProto(&proto);
808 static const char kSpdyProto[] = "spdy";
809 const bool use_spdy = (status == SSLClientSocket::kNextProtoNegotiated &&
810 proto == kSpdyProto);
811
812 if (IsCertificateError(result)) {
813 if (use_spdy) {
814 // TODO(agl/willchan/wtc): We currently ignore certificate errors for
815 // spdy but we shouldn't. http://crbug.com/32020
816 result = OK;
817 } else {
818 result = HandleCertificateError(result);
819 }
820 }
821
822 if (result == OK) {
823 DCHECK(ssl_connect_start_time_ != base::TimeTicks());
824 base::TimeDelta connect_duration =
825 base::TimeTicks::Now() - ssl_connect_start_time_;
826
827 if (use_spdy) {
828 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency",
829 connect_duration,
830 base::TimeDelta::FromMilliseconds(1),
831 base::TimeDelta::FromMinutes(10),
832 100);
833
834 UpdateConnectionTypeHistograms(CONNECTION_SPDY, true);
835 next_state_ = STATE_SPDY_SEND_REQUEST;
836 } else {
837 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency",
838 connect_duration,
839 base::TimeDelta::FromMilliseconds(1),
840 base::TimeDelta::FromMinutes(10),
841 100);
842
843 next_state_ = STATE_SEND_REQUEST;
844 }
845 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
846 result = HandleCertificateRequest(result);
847 } else {
848 result = HandleSSLHandshakeError(result);
849 }
850 return result;
851 }
852
DoSendRequest()853 int HttpNetworkTransaction::DoSendRequest() {
854 next_state_ = STATE_SEND_REQUEST_COMPLETE;
855
856 UploadDataStream* request_body = NULL;
857 if (!establishing_tunnel_ && request_->upload_data)
858 request_body = new UploadDataStream(request_->upload_data);
859
860 // This is constructed lazily (instead of within our Start method), so that
861 // we have proxy info available.
862 if (request_headers_.empty()) {
863 // Figure out if we can/should add Proxy-Authentication & Authentication
864 // headers.
865 bool have_proxy_auth =
866 ShouldApplyProxyAuth() &&
867 (HaveAuth(HttpAuth::AUTH_PROXY) ||
868 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY));
869 bool have_server_auth =
870 ShouldApplyServerAuth() &&
871 (HaveAuth(HttpAuth::AUTH_SERVER) ||
872 SelectPreemptiveAuth(HttpAuth::AUTH_SERVER));
873
874 std::string authorization_headers;
875
876 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization
877 // header with no credentials), we should return an error to prevent
878 // entering an infinite auth restart loop. See http://crbug.com/21050.
879 if (have_proxy_auth)
880 authorization_headers.append(
881 BuildAuthorizationHeader(HttpAuth::AUTH_PROXY));
882 if (have_server_auth)
883 authorization_headers.append(
884 BuildAuthorizationHeader(HttpAuth::AUTH_SERVER));
885
886 if (establishing_tunnel_) {
887 BuildTunnelRequest(request_, authorization_headers, &request_headers_);
888 } else {
889 BuildRequestHeaders(request_, authorization_headers, request_body,
890 proxy_mode_ == kHTTPProxy, &request_headers_);
891 }
892 }
893
894 headers_valid_ = false;
895 http_stream_.reset(new HttpBasicStream(connection_.get(), load_log_));
896
897 return http_stream_->SendRequest(request_, request_headers_,
898 request_body, &response_, &io_callback_);
899 }
900
DoSendRequestComplete(int result)901 int HttpNetworkTransaction::DoSendRequestComplete(int result) {
902 if (result < 0)
903 return HandleIOError(result);
904
905 next_state_ = STATE_READ_HEADERS;
906
907 return OK;
908 }
909
DoReadHeaders()910 int HttpNetworkTransaction::DoReadHeaders() {
911 next_state_ = STATE_READ_HEADERS_COMPLETE;
912
913 return http_stream_->ReadResponseHeaders(&io_callback_);
914 }
915
HandleConnectionClosedBeforeEndOfHeaders()916 int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
917 if (establishing_tunnel_) {
918 // The connection was closed before the tunnel could be established.
919 return ERR_TUNNEL_CONNECTION_FAILED;
920 }
921
922 if (!response_.headers) {
923 // The connection was closed before any data was sent. Likely an error
924 // rather than empty HTTP/0.9 response.
925 return ERR_EMPTY_RESPONSE;
926 }
927
928 return OK;
929 }
930
DoReadHeadersComplete(int result)931 int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
932 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
933 // due to SSL renegotiation.
934 if (using_ssl_) {
935 if (IsCertificateError(result)) {
936 // We don't handle a certificate error during SSL renegotiation, so we
937 // have to return an error that's not in the certificate error range
938 // (-2xx).
939 LOG(ERROR) << "Got a server certificate with error " << result
940 << " during SSL renegotiation";
941 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
942 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
943 result = HandleCertificateRequest(result);
944 if (result == OK)
945 return result;
946 }
947 }
948
949 if (result < 0 && result != ERR_CONNECTION_CLOSED)
950 return HandleIOError(result);
951
952 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
953 ResetConnectionAndRequestForResend();
954 return OK;
955 }
956
957 // After we call RestartWithAuth a new response_time will be recorded, and
958 // we need to be cautious about incorrectly logging the duration across the
959 // authentication activity.
960 if (!logged_response_time) {
961 LogTransactionConnectedMetrics();
962 logged_response_time = true;
963 }
964
965 if (result == ERR_CONNECTION_CLOSED) {
966 int rv = HandleConnectionClosedBeforeEndOfHeaders();
967 if (rv != OK)
968 return rv;
969 // TODO(wtc): Traditionally this code has returned 0 when reading a closed
970 // socket. That is partially corrected in classes that we call, but
971 // callers need to be updated.
972 result = 0;
973 }
974
975 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
976 // Require the "HTTP/1.x" status line for SSL CONNECT.
977 if (establishing_tunnel_)
978 return ERR_TUNNEL_CONNECTION_FAILED;
979
980 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
981 // indicates a buggy server. See:
982 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
983 if (request_->method == "PUT")
984 return ERR_METHOD_NOT_SUPPORTED;
985 }
986
987 if (establishing_tunnel_) {
988 switch (response_.headers->response_code()) {
989 case 200: // OK
990 if (http_stream_->IsMoreDataBuffered()) {
991 // The proxy sent extraneous data after the headers.
992 return ERR_TUNNEL_CONNECTION_FAILED;
993 }
994 next_state_ = STATE_SSL_CONNECT;
995 // Reset for the real request and response headers.
996 request_headers_.clear();
997 http_stream_.reset(new HttpBasicStream(connection_.get(), load_log_));
998 headers_valid_ = false;
999 establishing_tunnel_ = false;
1000 return OK;
1001
1002 // We aren't able to CONNECT to the remote host through the proxy. We
1003 // need to be very suspicious about the response because an active network
1004 // attacker can force us into this state by masquerading as the proxy.
1005 // The only safe thing to do here is to fail the connection because our
1006 // client is expecting an SSL protected response.
1007 // See http://crbug.com/7338.
1008 case 407: // Proxy Authentication Required
1009 // We need this status code to allow proxy authentication. Our
1010 // authentication code is smart enough to avoid being tricked by an
1011 // active network attacker.
1012 break;
1013 default:
1014 // For all other status codes, we conservatively fail the CONNECT
1015 // request.
1016 // We lose something by doing this. We have seen proxy 403, 404, and
1017 // 501 response bodies that contain a useful error message. For
1018 // example, Squid uses a 404 response to report the DNS error: "The
1019 // domain name does not exist."
1020 LogBlockedTunnelResponse(response_.headers->response_code());
1021 return ERR_TUNNEL_CONNECTION_FAILED;
1022 }
1023 }
1024
1025 // Check for an intermediate 100 Continue response. An origin server is
1026 // allowed to send this response even if we didn't ask for it, so we just
1027 // need to skip over it.
1028 // We treat any other 1xx in this same way (although in practice getting
1029 // a 1xx that isn't a 100 is rare).
1030 if (response_.headers->response_code() / 100 == 1) {
1031 response_.headers = new HttpResponseHeaders("");
1032 next_state_ = STATE_READ_HEADERS;
1033 return OK;
1034 }
1035
1036 int rv = HandleAuthChallenge();
1037 if (rv != OK)
1038 return rv;
1039
1040 if (using_ssl_ && !establishing_tunnel_) {
1041 SSLClientSocket* ssl_socket =
1042 reinterpret_cast<SSLClientSocket*>(connection_->socket());
1043 ssl_socket->GetSSLInfo(&response_.ssl_info);
1044 }
1045
1046 headers_valid_ = true;
1047 return OK;
1048 }
1049
DoReadBody()1050 int HttpNetworkTransaction::DoReadBody() {
1051 DCHECK(read_buf_);
1052 DCHECK_GT(read_buf_len_, 0);
1053 DCHECK(connection_->is_initialized());
1054
1055 next_state_ = STATE_READ_BODY_COMPLETE;
1056 return http_stream_->ReadResponseBody(read_buf_, read_buf_len_,
1057 &io_callback_);
1058 }
1059
DoReadBodyComplete(int result)1060 int HttpNetworkTransaction::DoReadBodyComplete(int result) {
1061 // We are done with the Read call.
1062 DCHECK(!establishing_tunnel_) <<
1063 "We should never read a response body of a tunnel.";
1064
1065 bool done = false, keep_alive = false;
1066 if (result < 0) {
1067 // Error or closed connection while reading the socket.
1068 done = true;
1069 // TODO(wtc): Traditionally this code has returned 0 when reading a closed
1070 // socket. That is partially corrected in classes that we call, but
1071 // callers need to be updated.
1072 if (result == ERR_CONNECTION_CLOSED)
1073 result = 0;
1074 } else if (http_stream_->IsResponseBodyComplete()) {
1075 done = true;
1076 keep_alive = GetResponseHeaders()->IsKeepAlive();
1077 }
1078
1079 // Clean up connection_->if we are done.
1080 if (done) {
1081 LogTransactionMetrics();
1082 if (!keep_alive)
1083 connection_->socket()->Disconnect();
1084 connection_->Reset();
1085 // The next Read call will return 0 (EOF).
1086 }
1087
1088 // Clear these to avoid leaving around old state.
1089 read_buf_ = NULL;
1090 read_buf_len_ = 0;
1091
1092 return result;
1093 }
1094
DoDrainBodyForAuthRestart()1095 int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
1096 // This method differs from DoReadBody only in the next_state_. So we just
1097 // call DoReadBody and override the next_state_. Perhaps there is a more
1098 // elegant way for these two methods to share code.
1099 int rv = DoReadBody();
1100 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
1101 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
1102 return rv;
1103 }
1104
1105 // TODO(wtc): This method and the DoReadBodyComplete method are almost
1106 // the same. Figure out a good way for these two methods to share code.
DoDrainBodyForAuthRestartComplete(int result)1107 int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
1108 // keep_alive defaults to true because the very reason we're draining the
1109 // response body is to reuse the connection for auth restart.
1110 bool done = false, keep_alive = true;
1111 if (result < 0) {
1112 // Error or closed connection while reading the socket.
1113 done = true;
1114 keep_alive = false;
1115 } else if (http_stream_->IsResponseBodyComplete()) {
1116 done = true;
1117 }
1118
1119 if (done) {
1120 DidDrainBodyForAuthRestart(keep_alive);
1121 } else {
1122 // Keep draining.
1123 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
1124 }
1125
1126 return OK;
1127 }
1128
DoSpdySendRequest()1129 int HttpNetworkTransaction::DoSpdySendRequest() {
1130 next_state_ = STATE_SPDY_SEND_REQUEST_COMPLETE;
1131 CHECK(!spdy_stream_.get());
1132
1133 // First we get a SPDY session. Theoretically, we've just negotiated one, but
1134 // if one already exists, then screw it, use the existing one! Otherwise,
1135 // use the existing TCP socket.
1136
1137 HostResolver::RequestInfo req_info(request_->url.HostNoBrackets(),
1138 request_->url.EffectiveIntPort());
1139 req_info.set_priority(request_->priority);
1140 const scoped_refptr<FlipSessionPool> spdy_pool =
1141 session_->flip_session_pool();
1142 scoped_refptr<FlipSession> spdy_session;
1143
1144 if (spdy_pool->HasSession(req_info)) {
1145 spdy_session = spdy_pool->Get(req_info, session_);
1146 } else {
1147 spdy_session = spdy_pool->GetFlipSessionFromSocket(
1148 req_info, session_, connection_.release());
1149 }
1150
1151 CHECK(spdy_session.get());
1152
1153 UploadDataStream* upload_data = request_->upload_data ?
1154 new UploadDataStream(request_->upload_data) : NULL;
1155 headers_valid_ = false;
1156 spdy_stream_ = spdy_session->GetOrCreateStream(
1157 *request_, upload_data, load_log_);
1158 return spdy_stream_->SendRequest(upload_data, &response_, &io_callback_);
1159 }
1160
DoSpdySendRequestComplete(int result)1161 int HttpNetworkTransaction::DoSpdySendRequestComplete(int result) {
1162 if (result < 0)
1163 return result;
1164
1165 next_state_ = STATE_SPDY_READ_HEADERS;
1166 return OK;
1167 }
1168
DoSpdyReadHeaders()1169 int HttpNetworkTransaction::DoSpdyReadHeaders() {
1170 next_state_ = STATE_SPDY_READ_HEADERS_COMPLETE;
1171 return spdy_stream_->ReadResponseHeaders(&io_callback_);
1172 }
1173
DoSpdyReadHeadersComplete(int result)1174 int HttpNetworkTransaction::DoSpdyReadHeadersComplete(int result) {
1175 // TODO(willchan): Flesh out the support for HTTP authentication here.
1176 if (result == OK)
1177 headers_valid_ = true;
1178 return result;
1179 }
1180
DoSpdyReadBody()1181 int HttpNetworkTransaction::DoSpdyReadBody() {
1182 next_state_ = STATE_SPDY_READ_BODY_COMPLETE;
1183
1184 return spdy_stream_->ReadResponseBody(
1185 read_buf_, read_buf_len_, &io_callback_);
1186 }
1187
DoSpdyReadBodyComplete(int result)1188 int HttpNetworkTransaction::DoSpdyReadBodyComplete(int result) {
1189 read_buf_ = NULL;
1190 read_buf_len_ = 0;
1191
1192 if (result <= 0)
1193 spdy_stream_ = NULL;
1194
1195 return result;
1196 }
1197
LogTCPConnectedMetrics(const ClientSocketHandle & handle)1198 void HttpNetworkTransaction::LogTCPConnectedMetrics(
1199 const ClientSocketHandle& handle) {
1200 const base::TimeDelta time_to_obtain_connected_socket =
1201 base::TimeTicks::Now() - handle.init_time();
1202
1203 static const bool use_late_binding_histogram =
1204 !FieldTrial::MakeName("", "SocketLateBinding").empty();
1205
1206 if (handle.reuse_type() == ClientSocketHandle::UNUSED) {
1207 UMA_HISTOGRAM_CUSTOM_TIMES(
1208 "Net.HttpConnectionLatency",
1209 time_to_obtain_connected_socket,
1210 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1211 100);
1212 }
1213
1214 UMA_HISTOGRAM_ENUMERATION("Net.TCPSocketType", handle.reuse_type(),
1215 ClientSocketHandle::NUM_TYPES);
1216
1217 if (use_late_binding_histogram) {
1218 UMA_HISTOGRAM_ENUMERATION(
1219 FieldTrial::MakeName("Net.TCPSocketType", "SocketLateBinding"),
1220 handle.reuse_type(), ClientSocketHandle::NUM_TYPES);
1221 }
1222
1223 UMA_HISTOGRAM_CLIPPED_TIMES(
1224 "Net.TransportSocketRequestTime",
1225 time_to_obtain_connected_socket,
1226 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1227 100);
1228
1229 if (use_late_binding_histogram) {
1230 UMA_HISTOGRAM_CUSTOM_TIMES(
1231 FieldTrial::MakeName("Net.TransportSocketRequestTime",
1232 "SocketLateBinding").data(),
1233 time_to_obtain_connected_socket,
1234 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1235 100);
1236 }
1237
1238 switch (handle.reuse_type()) {
1239 case ClientSocketHandle::UNUSED:
1240 break;
1241 case ClientSocketHandle::UNUSED_IDLE:
1242 UMA_HISTOGRAM_CUSTOM_TIMES(
1243 "Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1244 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1245 base::TimeDelta::FromMinutes(6), 100);
1246 if (use_late_binding_histogram) {
1247 UMA_HISTOGRAM_CUSTOM_TIMES(
1248 FieldTrial::MakeName("Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1249 "SocketLateBinding").data(),
1250 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1251 base::TimeDelta::FromMinutes(6), 100);
1252 }
1253 break;
1254 case ClientSocketHandle::REUSED_IDLE:
1255 UMA_HISTOGRAM_CUSTOM_TIMES(
1256 "Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1257 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1258 base::TimeDelta::FromMinutes(6), 100);
1259 if (use_late_binding_histogram) {
1260 UMA_HISTOGRAM_CUSTOM_TIMES(
1261 FieldTrial::MakeName("Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1262 "SocketLateBinding").data(),
1263 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1264 base::TimeDelta::FromMinutes(6), 100);
1265 }
1266 break;
1267 default:
1268 NOTREACHED();
1269 break;
1270 }
1271 }
1272
LogIOErrorMetrics(const ClientSocketHandle & handle)1273 void HttpNetworkTransaction::LogIOErrorMetrics(
1274 const ClientSocketHandle& handle) {
1275 static const bool use_late_binding_histogram =
1276 !FieldTrial::MakeName("", "SocketLateBinding").empty();
1277
1278 UMA_HISTOGRAM_ENUMERATION("Net.IOError_SocketReuseType",
1279 handle.reuse_type(), ClientSocketHandle::NUM_TYPES);
1280
1281 if (use_late_binding_histogram) {
1282 UMA_HISTOGRAM_ENUMERATION(
1283 FieldTrial::MakeName("Net.IOError_SocketReuseType",
1284 "SocketLateBinding"),
1285 handle.reuse_type(), ClientSocketHandle::NUM_TYPES);
1286 }
1287
1288 switch (handle.reuse_type()) {
1289 case ClientSocketHandle::UNUSED:
1290 break;
1291 case ClientSocketHandle::UNUSED_IDLE:
1292 UMA_HISTOGRAM_CUSTOM_TIMES(
1293 "Net.SocketIdleTimeOnIOError2_UnusedSocket",
1294 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1295 base::TimeDelta::FromMinutes(6), 100);
1296 if (use_late_binding_histogram) {
1297 UMA_HISTOGRAM_CUSTOM_TIMES(
1298 FieldTrial::MakeName("Net.SocketIdleTimeOnIOError2_UnusedSocket",
1299 "SocketLateBinding").data(),
1300 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1301 base::TimeDelta::FromMinutes(6), 100);
1302 }
1303 break;
1304 case ClientSocketHandle::REUSED_IDLE:
1305 UMA_HISTOGRAM_CUSTOM_TIMES(
1306 "Net.SocketIdleTimeOnIOError2_ReusedSocket",
1307 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1308 base::TimeDelta::FromMinutes(6), 100);
1309 if (use_late_binding_histogram) {
1310 UMA_HISTOGRAM_CUSTOM_TIMES(
1311 FieldTrial::MakeName("Net.SocketIdleTimeOnIOError2_ReusedSocket",
1312 "SocketLateBinding").data(),
1313 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1314 base::TimeDelta::FromMinutes(6), 100);
1315 }
1316 break;
1317 default:
1318 NOTREACHED();
1319 break;
1320 }
1321 }
1322
LogTransactionConnectedMetrics() const1323 void HttpNetworkTransaction::LogTransactionConnectedMetrics() const {
1324 base::TimeDelta total_duration = response_.response_time - start_time_;
1325
1326 UMA_HISTOGRAM_CLIPPED_TIMES(
1327 "Net.Transaction_Connected_Under_10",
1328 total_duration,
1329 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1330 100);
1331
1332 static const bool use_late_binding_histogram =
1333 !FieldTrial::MakeName("", "SocketLateBinding").empty();
1334
1335 if (use_late_binding_histogram) {
1336 UMA_HISTOGRAM_CUSTOM_TIMES(
1337 FieldTrial::MakeName("Net.Transaction_Connected_Under_10",
1338 "SocketLateBinding").data(),
1339 total_duration,
1340 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1341 100);
1342 }
1343
1344 if (!reused_socket_) {
1345 UMA_HISTOGRAM_CLIPPED_TIMES(
1346 "Net.Transaction_Connected_New",
1347 total_duration,
1348 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1349 100);
1350 }
1351
1352 // Currently, non-zero priority requests are frame or sub-frame resource
1353 // types. This will change when we also prioritize certain subresources like
1354 // css, js, etc.
1355 if (request_->priority) {
1356 UMA_HISTOGRAM_CLIPPED_TIMES(
1357 "Net.Priority_High_Latency",
1358 total_duration,
1359 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1360 100);
1361 } else {
1362 UMA_HISTOGRAM_CLIPPED_TIMES(
1363 "Net.Priority_Low_Latency",
1364 total_duration,
1365 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1366 100);
1367 }
1368 }
1369
LogTransactionMetrics() const1370 void HttpNetworkTransaction::LogTransactionMetrics() const {
1371 base::TimeDelta duration = base::Time::Now() -
1372 response_.request_time;
1373 if (60 < duration.InMinutes())
1374 return;
1375
1376 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1377
1378 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration);
1379 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Under_10", duration,
1380 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1381 100);
1382 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Total_Under_10",
1383 total_duration, base::TimeDelta::FromMilliseconds(1),
1384 base::TimeDelta::FromMinutes(10), 100);
1385 if (!reused_socket_) {
1386 UMA_HISTOGRAM_CLIPPED_TIMES(
1387 "Net.Transaction_Latency_Total_New_Connection_Under_10",
1388 total_duration, base::TimeDelta::FromMilliseconds(1),
1389 base::TimeDelta::FromMinutes(10), 100);
1390 }
1391 }
1392
LogBlockedTunnelResponse(int response_code) const1393 void HttpNetworkTransaction::LogBlockedTunnelResponse(
1394 int response_code) const {
1395 LOG(WARNING) << "Blocked proxy response with status " << response_code
1396 << " to CONNECT request for "
1397 << GetHostAndPort(request_->url) << ".";
1398 }
1399
HandleCertificateError(int error)1400 int HttpNetworkTransaction::HandleCertificateError(int error) {
1401 DCHECK(using_ssl_);
1402
1403 const int kCertFlags = LOAD_IGNORE_CERT_COMMON_NAME_INVALID |
1404 LOAD_IGNORE_CERT_DATE_INVALID |
1405 LOAD_IGNORE_CERT_AUTHORITY_INVALID |
1406 LOAD_IGNORE_CERT_WRONG_USAGE;
1407 if (request_->load_flags & kCertFlags) {
1408 switch (error) {
1409 case ERR_CERT_COMMON_NAME_INVALID:
1410 if (request_->load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID)
1411 error = OK;
1412 break;
1413 case ERR_CERT_DATE_INVALID:
1414 if (request_->load_flags & LOAD_IGNORE_CERT_DATE_INVALID)
1415 error = OK;
1416 break;
1417 case ERR_CERT_AUTHORITY_INVALID:
1418 if (request_->load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID)
1419 error = OK;
1420 break;
1421 }
1422 }
1423
1424 if (error != OK) {
1425 SSLClientSocket* ssl_socket =
1426 reinterpret_cast<SSLClientSocket*>(connection_->socket());
1427 ssl_socket->GetSSLInfo(&response_.ssl_info);
1428
1429 // Add the bad certificate to the set of allowed certificates in the
1430 // SSL info object. This data structure will be consulted after calling
1431 // RestartIgnoringLastError(). And the user will be asked interactively
1432 // before RestartIgnoringLastError() is ever called.
1433 SSLConfig::CertAndStatus bad_cert;
1434 bad_cert.cert = response_.ssl_info.cert;
1435 bad_cert.cert_status = response_.ssl_info.cert_status;
1436 ssl_config_.allowed_bad_certs.push_back(bad_cert);
1437 }
1438 return error;
1439 }
1440
HandleCertificateRequest(int error)1441 int HttpNetworkTransaction::HandleCertificateRequest(int error) {
1442 // Assert that the socket did not send a client certificate.
1443 // Note: If we got a reused socket, it was created with some other
1444 // transaction's ssl_config_, so we need to disable this assertion. We can
1445 // get a certificate request on a reused socket when the server requested
1446 // renegotiation (rehandshake).
1447 // TODO(wtc): add a GetSSLParams method to SSLClientSocket so we can query
1448 // the SSL parameters it was created with and get rid of the reused_socket_
1449 // test.
1450 DCHECK(reused_socket_ || !ssl_config_.send_client_cert);
1451
1452 response_.cert_request_info = new SSLCertRequestInfo;
1453 SSLClientSocket* ssl_socket =
1454 reinterpret_cast<SSLClientSocket*>(connection_->socket());
1455 ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info);
1456
1457 // Close the connection while the user is selecting a certificate to send
1458 // to the server.
1459 connection_->socket()->Disconnect();
1460 connection_->Reset();
1461
1462 // If the user selected one of the certificate in client_certs for this
1463 // server before, use it automatically.
1464 X509Certificate* client_cert = session_->ssl_client_auth_cache()->
1465 Lookup(GetHostAndPort(request_->url));
1466 if (client_cert) {
1467 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
1468 response_.cert_request_info->client_certs;
1469 for (size_t i = 0; i < client_certs.size(); ++i) {
1470 if (client_cert->fingerprint().Equals(client_certs[i]->fingerprint())) {
1471 ssl_config_.client_cert = client_cert;
1472 ssl_config_.send_client_cert = true;
1473 next_state_ = STATE_INIT_CONNECTION;
1474 // Reset the other member variables.
1475 // Note: this is necessary only with SSL renegotiation.
1476 ResetStateForRestart();
1477 return OK;
1478 }
1479 }
1480 }
1481 return error;
1482 }
1483
HandleSSLHandshakeError(int error)1484 int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
1485 if (ssl_config_.send_client_cert &&
1486 (error == ERR_SSL_PROTOCOL_ERROR ||
1487 error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) {
1488 session_->ssl_client_auth_cache()->Remove(GetHostAndPort(request_->url));
1489 }
1490
1491 switch (error) {
1492 case ERR_SSL_PROTOCOL_ERROR:
1493 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
1494 if (ssl_config_.tls1_enabled) {
1495 // This could be a TLS-intolerant server or an SSL 3.0 server that
1496 // chose a TLS-only cipher suite. Turn off TLS 1.0 and retry.
1497 ssl_config_.tls1_enabled = false;
1498 connection_->socket()->Disconnect();
1499 connection_->Reset();
1500 next_state_ = STATE_INIT_CONNECTION;
1501 error = OK;
1502 }
1503 break;
1504 }
1505 return error;
1506 }
1507
1508 // This method determines whether it is safe to resend the request after an
1509 // IO error. It can only be called in response to request header or body
1510 // write errors or response header read errors. It should not be used in
1511 // other cases, such as a Connect error.
HandleIOError(int error)1512 int HttpNetworkTransaction::HandleIOError(int error) {
1513 switch (error) {
1514 // If we try to reuse a connection that the server is in the process of
1515 // closing, we may end up successfully writing out our request (or a
1516 // portion of our request) only to find a connection error when we try to
1517 // read from (or finish writing to) the socket.
1518 case ERR_CONNECTION_RESET:
1519 case ERR_CONNECTION_CLOSED:
1520 case ERR_CONNECTION_ABORTED:
1521 LogIOErrorMetrics(*connection_);
1522 if (ShouldResendRequest(error)) {
1523 ResetConnectionAndRequestForResend();
1524 error = OK;
1525 }
1526 break;
1527 }
1528 return error;
1529 }
1530
ResetStateForRestart()1531 void HttpNetworkTransaction::ResetStateForRestart() {
1532 pending_auth_target_ = HttpAuth::AUTH_NONE;
1533 read_buf_ = NULL;
1534 read_buf_len_ = 0;
1535 http_stream_.reset();
1536 headers_valid_ = false;
1537 request_headers_.clear();
1538 response_ = HttpResponseInfo();
1539 }
1540
GetResponseHeaders() const1541 HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
1542 return response_.headers;
1543 }
1544
ShouldResendRequest(int error) const1545 bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
1546 // NOTE: we resend a request only if we reused a keep-alive connection.
1547 // This automatically prevents an infinite resend loop because we'll run
1548 // out of the cached keep-alive connections eventually.
1549 if (establishing_tunnel_ ||
1550 !connection_->ShouldResendFailedRequest(error) ||
1551 GetResponseHeaders()) { // We have received some response headers.
1552 return false;
1553 }
1554 return true;
1555 }
1556
ResetConnectionAndRequestForResend()1557 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
1558 connection_->socket()->Disconnect();
1559 connection_->Reset();
1560 // We need to clear request_headers_ because it contains the real request
1561 // headers, but we may need to resend the CONNECT request first to recreate
1562 // the SSL tunnel.
1563 request_headers_.clear();
1564 next_state_ = STATE_INIT_CONNECTION; // Resend the request.
1565 }
1566
ReconsiderProxyAfterError(int error)1567 int HttpNetworkTransaction::ReconsiderProxyAfterError(int error) {
1568 DCHECK(!pac_request_);
1569
1570 // A failure to resolve the hostname or any error related to establishing a
1571 // TCP connection could be grounds for trying a new proxy configuration.
1572 //
1573 // Why do this when a hostname cannot be resolved? Some URLs only make sense
1574 // to proxy servers. The hostname in those URLs might fail to resolve if we
1575 // are still using a non-proxy config. We need to check if a proxy config
1576 // now exists that corresponds to a proxy server that could load the URL.
1577 //
1578 switch (error) {
1579 case ERR_NAME_NOT_RESOLVED:
1580 case ERR_INTERNET_DISCONNECTED:
1581 case ERR_ADDRESS_UNREACHABLE:
1582 case ERR_CONNECTION_CLOSED:
1583 case ERR_CONNECTION_RESET:
1584 case ERR_CONNECTION_REFUSED:
1585 case ERR_CONNECTION_ABORTED:
1586 case ERR_TIMED_OUT:
1587 case ERR_TUNNEL_CONNECTION_FAILED:
1588 break;
1589 default:
1590 return error;
1591 }
1592
1593 if (request_->load_flags & LOAD_BYPASS_PROXY) {
1594 return error;
1595 }
1596
1597 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1598 request_->url, &proxy_info_, &io_callback_, &pac_request_, load_log_);
1599 if (rv == OK || rv == ERR_IO_PENDING) {
1600 // If the error was during connection setup, there is no socket to
1601 // disconnect.
1602 if (connection_->socket())
1603 connection_->socket()->Disconnect();
1604 connection_->Reset();
1605 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1606 } else {
1607 // If ReconsiderProxyAfterError() failed synchronously, it means
1608 // there was nothing left to fall-back to, so fail the transaction
1609 // with the last connection error we got.
1610 // TODO(eroman): This is a confusing contract, make it more obvious.
1611 rv = error;
1612 }
1613
1614 return rv;
1615 }
1616
ShouldApplyProxyAuth() const1617 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
1618 return (proxy_mode_ == kHTTPProxy) || establishing_tunnel_;
1619 }
1620
ShouldApplyServerAuth() const1621 bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
1622 return !establishing_tunnel_ &&
1623 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
1624 }
1625
BuildAuthorizationHeader(HttpAuth::Target target) const1626 std::string HttpNetworkTransaction::BuildAuthorizationHeader(
1627 HttpAuth::Target target) const {
1628 DCHECK(HaveAuth(target));
1629
1630 // Add a Authorization/Proxy-Authorization header line.
1631 std::string credentials = auth_handler_[target]->GenerateCredentials(
1632 auth_identity_[target].username,
1633 auth_identity_[target].password,
1634 request_,
1635 &proxy_info_);
1636
1637 return HttpAuth::GetAuthorizationHeaderName(target) +
1638 ": " + credentials + "\r\n";
1639 }
1640
AuthOrigin(HttpAuth::Target target) const1641 GURL HttpNetworkTransaction::AuthOrigin(HttpAuth::Target target) const {
1642 return target == HttpAuth::AUTH_PROXY ?
1643 GURL("http://" + proxy_info_.proxy_server().host_and_port()) :
1644 request_->url.GetOrigin();
1645 }
1646
AuthPath(HttpAuth::Target target) const1647 std::string HttpNetworkTransaction::AuthPath(HttpAuth::Target target)
1648 const {
1649 // Proxy authentication realms apply to all paths. So we will use
1650 // empty string in place of an absolute path.
1651 return target == HttpAuth::AUTH_PROXY ?
1652 std::string() : request_->url.path();
1653 }
1654
1655 // static
AuthTargetString(HttpAuth::Target target)1656 std::string HttpNetworkTransaction::AuthTargetString(
1657 HttpAuth::Target target) {
1658 return target == HttpAuth::AUTH_PROXY ? "proxy" : "server";
1659 }
1660
InvalidateRejectedAuthFromCache(HttpAuth::Target target,const GURL & auth_origin)1661 void HttpNetworkTransaction::InvalidateRejectedAuthFromCache(
1662 HttpAuth::Target target,
1663 const GURL& auth_origin) {
1664 DCHECK(HaveAuth(target));
1665
1666 // TODO(eroman): this short-circuit can be relaxed. If the realm of
1667 // the preemptively used auth entry matches the realm of the subsequent
1668 // challenge, then we can invalidate the preemptively used entry.
1669 // Otherwise as-is we may send the failed credentials one extra time.
1670 if (auth_identity_[target].source == HttpAuth::IDENT_SRC_PATH_LOOKUP)
1671 return;
1672
1673 // Clear the cache entry for the identity we just failed on.
1674 // Note: we require the username/password to match before invalidating
1675 // since the entry in the cache may be newer than what we used last time.
1676 session_->auth_cache()->Remove(auth_origin,
1677 auth_handler_[target]->realm(),
1678 auth_identity_[target].username,
1679 auth_identity_[target].password);
1680 }
1681
SelectPreemptiveAuth(HttpAuth::Target target)1682 bool HttpNetworkTransaction::SelectPreemptiveAuth(HttpAuth::Target target) {
1683 DCHECK(!HaveAuth(target));
1684
1685 // Don't do preemptive authorization if the URL contains a username/password,
1686 // since we must first be challenged in order to use the URL's identity.
1687 if (request_->url.has_username())
1688 return false;
1689
1690 // SelectPreemptiveAuth() is on the critical path for each request, so it
1691 // is expected to be fast. LookupByPath() is fast in the common case, since
1692 // the number of http auth cache entries is expected to be very small.
1693 // (For most users in fact, it will be 0.)
1694
1695 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByPath(
1696 AuthOrigin(target), AuthPath(target));
1697
1698 // We don't support preemptive authentication for connection-based
1699 // authentication schemes because they can't reuse entry->handler().
1700 // Hopefully we can remove this limitation in the future.
1701 if (entry && !entry->handler()->is_connection_based()) {
1702 auth_identity_[target].source = HttpAuth::IDENT_SRC_PATH_LOOKUP;
1703 auth_identity_[target].invalid = false;
1704 auth_identity_[target].username = entry->username();
1705 auth_identity_[target].password = entry->password();
1706 auth_handler_[target] = entry->handler();
1707 return true;
1708 }
1709 return false;
1710 }
1711
SelectNextAuthIdentityToTry(HttpAuth::Target target,const GURL & auth_origin)1712 bool HttpNetworkTransaction::SelectNextAuthIdentityToTry(
1713 HttpAuth::Target target,
1714 const GURL& auth_origin) {
1715 DCHECK(auth_handler_[target]);
1716 DCHECK(auth_identity_[target].invalid);
1717
1718 // Try to use the username/password encoded into the URL first.
1719 if (target == HttpAuth::AUTH_SERVER && request_->url.has_username() &&
1720 !embedded_identity_used_) {
1721 auth_identity_[target].source = HttpAuth::IDENT_SRC_URL;
1722 auth_identity_[target].invalid = false;
1723 // Extract the username:password from the URL.
1724 GetIdentityFromURL(request_->url,
1725 &auth_identity_[target].username,
1726 &auth_identity_[target].password);
1727 embedded_identity_used_ = true;
1728 // TODO(eroman): If the password is blank, should we also try combining
1729 // with a password from the cache?
1730 return true;
1731 }
1732
1733 // Check the auth cache for a realm entry.
1734 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByRealm(
1735 auth_origin, auth_handler_[target]->realm());
1736
1737 if (entry) {
1738 // Disallow re-using of identity if the scheme of the originating challenge
1739 // does not match. This protects against the following situation:
1740 // 1. Browser prompts user to sign into DIGEST realm="Foo".
1741 // 2. Since the auth-scheme is not BASIC, the user is reasured that it
1742 // will not be sent over the wire in clear text. So they use their
1743 // most trusted password.
1744 // 3. Next, the browser receives a challenge for BASIC realm="Foo". This
1745 // is the same realm that we have a cached identity for. However if
1746 // we use that identity, it would get sent over the wire in
1747 // clear text (which isn't what the user agreed to when entering it).
1748 if (entry->handler()->scheme() != auth_handler_[target]->scheme()) {
1749 LOG(WARNING) << "The scheme of realm " << auth_handler_[target]->realm()
1750 << " has changed from " << entry->handler()->scheme()
1751 << " to " << auth_handler_[target]->scheme();
1752 return false;
1753 }
1754
1755 auth_identity_[target].source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
1756 auth_identity_[target].invalid = false;
1757 auth_identity_[target].username = entry->username();
1758 auth_identity_[target].password = entry->password();
1759 return true;
1760 }
1761 return false;
1762 }
1763
AuthChallengeLogMessage() const1764 std::string HttpNetworkTransaction::AuthChallengeLogMessage() const {
1765 std::string msg;
1766 std::string header_val;
1767 void* iter = NULL;
1768 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
1769 while (headers->EnumerateHeader(&iter, "proxy-authenticate", &header_val)) {
1770 msg.append("\n Has header Proxy-Authenticate: ");
1771 msg.append(header_val);
1772 }
1773
1774 iter = NULL;
1775 while (headers->EnumerateHeader(&iter, "www-authenticate", &header_val)) {
1776 msg.append("\n Has header WWW-Authenticate: ");
1777 msg.append(header_val);
1778 }
1779
1780 // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate
1781 // authentication with a "Proxy-Support: Session-Based-Authentication"
1782 // response header.
1783 iter = NULL;
1784 while (headers->EnumerateHeader(&iter, "proxy-support", &header_val)) {
1785 msg.append("\n Has header Proxy-Support: ");
1786 msg.append(header_val);
1787 }
1788
1789 return msg;
1790 }
1791
HandleAuthChallenge()1792 int HttpNetworkTransaction::HandleAuthChallenge() {
1793 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
1794 DCHECK(headers);
1795
1796 int status = headers->response_code();
1797 if (status != 401 && status != 407)
1798 return OK;
1799 HttpAuth::Target target = status == 407 ?
1800 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
1801 GURL auth_origin = AuthOrigin(target);
1802
1803 LOG(INFO) << "The " << AuthTargetString(target) << " "
1804 << auth_origin << " requested auth"
1805 << AuthChallengeLogMessage();
1806
1807 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1808 return ERR_UNEXPECTED_PROXY_AUTH;
1809
1810 // The auth we tried just failed, hence it can't be valid. Remove it from
1811 // the cache so it won't be used again.
1812 // TODO(wtc): IsFinalRound is not the right condition. In a multi-round
1813 // auth sequence, the server may fail the auth in round 1 if our first
1814 // authorization header is broken. We should inspect response_.headers to
1815 // determine if the server already failed the auth or wants us to continue.
1816 // See http://crbug.com/21015.
1817 if (HaveAuth(target) && auth_handler_[target]->IsFinalRound()) {
1818 InvalidateRejectedAuthFromCache(target, auth_origin);
1819 auth_handler_[target] = NULL;
1820 auth_identity_[target] = HttpAuth::Identity();
1821 }
1822
1823 auth_identity_[target].invalid = true;
1824
1825 if (target != HttpAuth::AUTH_SERVER ||
1826 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA)) {
1827 // Find the best authentication challenge that we support.
1828 HttpAuth::ChooseBestChallenge(headers, target, auth_origin,
1829 &auth_handler_[target]);
1830 }
1831
1832 if (!auth_handler_[target]) {
1833 if (establishing_tunnel_) {
1834 LOG(ERROR) << "Can't perform auth to the " << AuthTargetString(target)
1835 << " " << auth_origin << " when establishing a tunnel"
1836 << AuthChallengeLogMessage();
1837
1838 // We are establishing a tunnel, we can't show the error page because an
1839 // active network attacker could control its contents. Instead, we just
1840 // fail to establish the tunnel.
1841 DCHECK(target == HttpAuth::AUTH_PROXY);
1842 return ERR_PROXY_AUTH_REQUESTED;
1843 }
1844 // We found no supported challenge -- let the transaction continue
1845 // so we end up displaying the error page.
1846 return OK;
1847 }
1848
1849 if (auth_handler_[target]->NeedsIdentity()) {
1850 // Pick a new auth identity to try, by looking to the URL and auth cache.
1851 // If an identity to try is found, it is saved to auth_identity_[target].
1852 SelectNextAuthIdentityToTry(target, auth_origin);
1853 } else {
1854 // Proceed with the existing identity or a null identity.
1855 //
1856 // TODO(wtc): Add a safeguard against infinite transaction restarts, if
1857 // the server keeps returning "NTLM".
1858 auth_identity_[target].invalid = false;
1859 }
1860
1861 // Make a note that we are waiting for auth. This variable is inspected
1862 // when the client calls RestartWithAuth() to pick up where we left off.
1863 pending_auth_target_ = target;
1864
1865 if (auth_identity_[target].invalid) {
1866 // We have exhausted all identity possibilities, all we can do now is
1867 // pass the challenge information back to the client.
1868 PopulateAuthChallenge(target, auth_origin);
1869 }
1870 return OK;
1871 }
1872
PopulateAuthChallenge(HttpAuth::Target target,const GURL & auth_origin)1873 void HttpNetworkTransaction::PopulateAuthChallenge(HttpAuth::Target target,
1874 const GURL& auth_origin) {
1875 // Populates response_.auth_challenge with the authentication challenge info.
1876 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo().
1877
1878 AuthChallengeInfo* auth_info = new AuthChallengeInfo;
1879 auth_info->is_proxy = target == HttpAuth::AUTH_PROXY;
1880 auth_info->host_and_port = ASCIIToWide(GetHostAndPort(auth_origin));
1881 auth_info->scheme = ASCIIToWide(auth_handler_[target]->scheme());
1882 // TODO(eroman): decode realm according to RFC 2047.
1883 auth_info->realm = ASCIIToWide(auth_handler_[target]->realm());
1884 response_.auth_challenge = auth_info;
1885 }
1886
1887 } // namespace net
1888