Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1179)

Side by Side Diff: net/http/http_network_transaction.cc

Issue 2870030: Implement SSLClientSocketPool. (Closed)
Patch Set: Rebase and fix mac compile error Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_network_transaction.h" 5 #include "net/http/http_network_transaction.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/field_trial.h" 8 #include "base/field_trial.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/histogram.h" 10 #include "base/histogram.h"
(...skipping 22 matching lines...) Expand all
33 #include "net/http/http_proxy_client_socket_pool.h" 33 #include "net/http/http_proxy_client_socket_pool.h"
34 #include "net/http/http_request_headers.h" 34 #include "net/http/http_request_headers.h"
35 #include "net/http/http_request_info.h" 35 #include "net/http/http_request_info.h"
36 #include "net/http/http_response_headers.h" 36 #include "net/http/http_response_headers.h"
37 #include "net/http/http_response_info.h" 37 #include "net/http/http_response_info.h"
38 #include "net/http/http_util.h" 38 #include "net/http/http_util.h"
39 #include "net/http/url_security_manager.h" 39 #include "net/http/url_security_manager.h"
40 #include "net/socket/client_socket_factory.h" 40 #include "net/socket/client_socket_factory.h"
41 #include "net/socket/socks_client_socket_pool.h" 41 #include "net/socket/socks_client_socket_pool.h"
42 #include "net/socket/ssl_client_socket.h" 42 #include "net/socket/ssl_client_socket.h"
43 #include "net/socket/ssl_client_socket_pool.h"
43 #include "net/socket/tcp_client_socket_pool.h" 44 #include "net/socket/tcp_client_socket_pool.h"
44 #include "net/spdy/spdy_http_stream.h" 45 #include "net/spdy/spdy_http_stream.h"
45 #include "net/spdy/spdy_session.h" 46 #include "net/spdy/spdy_session.h"
46 #include "net/spdy/spdy_session_pool.h" 47 #include "net/spdy/spdy_session_pool.h"
47 48
48 using base::Time; 49 using base::Time;
49 50
50 namespace net { 51 namespace net {
51 52
52 namespace { 53 namespace {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 253
253 next_state_ = STATE_RESOLVE_PROXY; 254 next_state_ = STATE_RESOLVE_PROXY;
254 int rv = DoLoop(OK); 255 int rv = DoLoop(OK);
255 if (rv == ERR_IO_PENDING) 256 if (rv == ERR_IO_PENDING)
256 user_callback_ = callback; 257 user_callback_ = callback;
257 return rv; 258 return rv;
258 } 259 }
259 260
260 int HttpNetworkTransaction::RestartIgnoringLastError( 261 int HttpNetworkTransaction::RestartIgnoringLastError(
261 CompletionCallback* callback) { 262 CompletionCallback* callback) {
262 if (connection_->socket()->IsConnectedAndIdle()) { 263 if (connection_->socket() && connection_->socket()->IsConnectedAndIdle()) {
263 // TODO(wtc): Should we update any of the connection histograms that we 264 // TODO(wtc): Should we update any of the connection histograms that we
264 // update in DoSSLConnectComplete if |result| is OK? 265 // update in DoSSLConnectComplete if |result| is OK?
265 if (using_spdy_) { 266 if (using_spdy_) {
266 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620 267 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620
267 next_state_ = STATE_SPDY_SEND_REQUEST; 268 next_state_ = STATE_SPDY_SEND_REQUEST;
268 } else { 269 } else {
269 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; 270 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
270 } 271 }
271 } else { 272 } else {
272 connection_->socket()->Disconnect(); 273 if (connection_->socket())
274 connection_->socket()->Disconnect();
273 connection_->Reset(); 275 connection_->Reset();
274 next_state_ = STATE_INIT_CONNECTION; 276 next_state_ = STATE_INIT_CONNECTION;
275 } 277 }
276 int rv = DoLoop(OK); 278 int rv = DoLoop(OK);
277 if (rv == ERR_IO_PENDING) 279 if (rv == ERR_IO_PENDING)
278 user_callback_ = callback; 280 user_callback_ = callback;
279 return rv; 281 return rv;
280 } 282 }
281 283
282 int HttpNetworkTransaction::RestartWithCertificate( 284 int HttpNetworkTransaction::RestartWithCertificate(
(...skipping 23 matching lines...) Expand all
306 if (target == HttpAuth::AUTH_NONE) { 308 if (target == HttpAuth::AUTH_NONE) {
307 NOTREACHED(); 309 NOTREACHED();
308 return ERR_UNEXPECTED; 310 return ERR_UNEXPECTED;
309 } 311 }
310 pending_auth_target_ = HttpAuth::AUTH_NONE; 312 pending_auth_target_ = HttpAuth::AUTH_NONE;
311 313
312 auth_controllers_[target]->ResetAuth(username, password); 314 auth_controllers_[target]->ResetAuth(username, password);
313 315
314 if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) { 316 if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) {
315 DCHECK(establishing_tunnel_); 317 DCHECK(establishing_tunnel_);
318 next_state_ = STATE_INIT_CONNECTION;
316 ResetStateForRestart(); 319 ResetStateForRestart();
317 next_state_ = STATE_TUNNEL_RESTART_WITH_AUTH;
318 } else { 320 } else {
319 PrepareForAuthRestart(target); 321 PrepareForAuthRestart(target);
320 } 322 }
321 323
322 DCHECK(user_callback_ == NULL); 324 DCHECK(user_callback_ == NULL);
323 int rv = DoLoop(OK); 325 int rv = DoLoop(OK);
324 if (rv == ERR_IO_PENDING) 326 if (rv == ERR_IO_PENDING)
325 user_callback_ = callback; 327 user_callback_ = callback;
326 328
327 return rv; 329 return rv;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 ResetStateForRestart(); 371 ResetStateForRestart();
370 } 372 }
371 373
372 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len, 374 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
373 CompletionCallback* callback) { 375 CompletionCallback* callback) {
374 DCHECK(buf); 376 DCHECK(buf);
375 DCHECK_LT(0, buf_len); 377 DCHECK_LT(0, buf_len);
376 378
377 State next_state = STATE_NONE; 379 State next_state = STATE_NONE;
378 380
379 // Are we using SPDY or HTTP?
380 if (using_spdy_) {
381 DCHECK(!http_stream_.get());
382 DCHECK(spdy_http_stream_->GetResponseInfo()->headers);
383 next_state = STATE_SPDY_READ_BODY;
384 } else {
385 DCHECK(!spdy_http_stream_.get());
386 next_state = STATE_READ_BODY;
387
388 if (!connection_->is_initialized())
389 return 0; // connection_->has been reset. Treat like EOF.
390 }
391
392 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders(); 381 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
393 DCHECK(headers.get()); 382 if (headers_valid_ && headers.get() && establishing_tunnel_) {
394 if (establishing_tunnel_) {
395 // We're trying to read the body of the response but we're still trying 383 // We're trying to read the body of the response but we're still trying
396 // to establish an SSL tunnel through the proxy. We can't read these 384 // to establish an SSL tunnel through the proxy. We can't read these
397 // bytes when establishing a tunnel because they might be controlled by 385 // bytes when establishing a tunnel because they might be controlled by
398 // an active network attacker. We don't worry about this for HTTP 386 // an active network attacker. We don't worry about this for HTTP
399 // because an active network attacker can already control HTTP sessions. 387 // because an active network attacker can already control HTTP sessions.
400 // We reach this case when the user cancels a 407 proxy auth prompt. 388 // We reach this case when the user cancels a 407 proxy auth prompt.
401 // See http://crbug.com/8473. 389 // See http://crbug.com/8473.
402 DCHECK(proxy_info_.is_http()); 390 DCHECK(proxy_info_.is_http());
403 DCHECK_EQ(headers->response_code(), 407); 391 DCHECK_EQ(headers->response_code(), 407);
404 LOG(WARNING) << "Blocked proxy response with status " 392 LOG(WARNING) << "Blocked proxy response with status "
405 << headers->response_code() << " to CONNECT request for " 393 << headers->response_code() << " to CONNECT request for "
406 << GetHostAndPort(request_->url) << "."; 394 << GetHostAndPort(request_->url) << ".";
407 return ERR_TUNNEL_CONNECTION_FAILED; 395 return ERR_TUNNEL_CONNECTION_FAILED;
408 } 396 }
409 397
398 // Are we using SPDY or HTTP?
399 if (using_spdy_) {
400 DCHECK(!http_stream_.get());
401 DCHECK(spdy_http_stream_->GetResponseInfo()->headers);
402 next_state = STATE_SPDY_READ_BODY;
403 } else {
404 DCHECK(!spdy_http_stream_.get());
405 next_state = STATE_READ_BODY;
406
407 if (!connection_->is_initialized())
408 return 0; // |*connection_| has been reset. Treat like EOF.
409 }
410
410 read_buf_ = buf; 411 read_buf_ = buf;
411 read_buf_len_ = buf_len; 412 read_buf_len_ = buf_len;
412 413
413 next_state_ = next_state; 414 next_state_ = next_state;
414 int rv = DoLoop(OK); 415 int rv = DoLoop(OK);
415 if (rv == ERR_IO_PENDING) 416 if (rv == ERR_IO_PENDING)
416 user_callback_ = callback; 417 user_callback_ = callback;
417 return rv; 418 return rv;
418 } 419 }
419 420
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 case STATE_RESOLVE_PROXY_COMPLETE: 510 case STATE_RESOLVE_PROXY_COMPLETE:
510 rv = DoResolveProxyComplete(rv); 511 rv = DoResolveProxyComplete(rv);
511 break; 512 break;
512 case STATE_INIT_CONNECTION: 513 case STATE_INIT_CONNECTION:
513 DCHECK_EQ(OK, rv); 514 DCHECK_EQ(OK, rv);
514 rv = DoInitConnection(); 515 rv = DoInitConnection();
515 break; 516 break;
516 case STATE_INIT_CONNECTION_COMPLETE: 517 case STATE_INIT_CONNECTION_COMPLETE:
517 rv = DoInitConnectionComplete(rv); 518 rv = DoInitConnectionComplete(rv);
518 break; 519 break;
519 case STATE_TUNNEL_RESTART_WITH_AUTH:
520 DCHECK_EQ(OK, rv);
521 rv = DoTunnelRestartWithAuth();
522 break;
523 case STATE_SSL_CONNECT:
524 DCHECK_EQ(OK, rv);
525 rv = DoSSLConnect();
526 break;
527 case STATE_SSL_CONNECT_COMPLETE:
528 rv = DoSSLConnectComplete(rv);
529 break;
530 case STATE_GENERATE_PROXY_AUTH_TOKEN: 520 case STATE_GENERATE_PROXY_AUTH_TOKEN:
531 DCHECK_EQ(OK, rv); 521 DCHECK_EQ(OK, rv);
532 rv = DoGenerateProxyAuthToken(); 522 rv = DoGenerateProxyAuthToken();
533 break; 523 break;
534 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: 524 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
535 rv = DoGenerateProxyAuthTokenComplete(rv); 525 rv = DoGenerateProxyAuthTokenComplete(rv);
536 break; 526 break;
537 case STATE_GENERATE_SERVER_AUTH_TOKEN: 527 case STATE_GENERATE_SERVER_AUTH_TOKEN:
538 DCHECK_EQ(OK, rv); 528 DCHECK_EQ(OK, rv);
539 rv = DoGenerateServerAuthToken(); 529 rv = DoGenerateServerAuthToken();
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 return ERR_NO_SUPPORTED_PROXIES; 684 return ERR_NO_SUPPORTED_PROXIES;
695 } 685 }
696 686
697 next_state_ = STATE_INIT_CONNECTION; 687 next_state_ = STATE_INIT_CONNECTION;
698 return OK; 688 return OK;
699 } 689 }
700 690
701 int HttpNetworkTransaction::DoInitConnection() { 691 int HttpNetworkTransaction::DoInitConnection() {
702 DCHECK(!connection_->is_initialized()); 692 DCHECK(!connection_->is_initialized());
703 DCHECK(proxy_info_.proxy_server().is_valid()); 693 DCHECK(proxy_info_.proxy_server().is_valid());
694 next_state_ = STATE_INIT_CONNECTION_COMPLETE;
704 695
705 // Now that the proxy server has been resolved, create the auth_controllers_. 696 // Now that the proxy server has been resolved, create the auth_controllers_.
706 for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) { 697 for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) {
707 HttpAuth::Target target = static_cast<HttpAuth::Target>(i); 698 HttpAuth::Target target = static_cast<HttpAuth::Target>(i);
708 if (!auth_controllers_[target].get()) 699 if (!auth_controllers_[target].get())
709 auth_controllers_[target] = new HttpAuthController(target, 700 auth_controllers_[target] = new HttpAuthController(target,
710 AuthURL(target), 701 AuthURL(target),
711 session_); 702 session_);
712 } 703 }
713 704
714 next_state_ = STATE_INIT_CONNECTION_COMPLETE; 705 bool want_spdy = alternate_protocol_mode_ == kUsingAlternateProtocol
715 706 && alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_1;
716 using_ssl_ = request_->url.SchemeIs("https") || 707 using_ssl_ = request_->url.SchemeIs("https") || want_spdy;
717 (alternate_protocol_mode_ == kUsingAlternateProtocol &&
718 alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_1);
719
720 using_spdy_ = false; 708 using_spdy_ = false;
721 709 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
722 // Build the string used to uniquely identify connections of this type.
723 // Determine the host and port to connect to.
724 std::string connection_group;
725 710
726 // Use the fixed testing ports if they've been provided. 711 // Use the fixed testing ports if they've been provided.
727 if (using_ssl_) { 712 if (using_ssl_) {
728 if (session_->fixed_https_port() != 0) 713 if (session_->fixed_https_port() != 0)
729 endpoint_.port = session_->fixed_https_port(); 714 endpoint_.port = session_->fixed_https_port();
730 } else if (session_->fixed_http_port() != 0) { 715 } else if (session_->fixed_http_port() != 0) {
731 endpoint_.port = session_->fixed_http_port(); 716 endpoint_.port = session_->fixed_http_port();
732 } 717 }
733 718
734 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
735
736 // Check first if we have a spdy session for this group. If so, then go 719 // Check first if we have a spdy session for this group. If so, then go
737 // straight to using that. 720 // straight to using that.
738 if (session_->spdy_session_pool()->HasSession(endpoint_)) { 721 if (session_->spdy_session_pool()->HasSession(endpoint_)) {
739 using_spdy_ = true; 722 using_spdy_ = true;
740 reused_socket_ = true; 723 reused_socket_ = true;
724 next_state_ = STATE_SPDY_SEND_REQUEST;
741 return OK; 725 return OK;
742 } 726 }
743 727
744 connection_group = endpoint_.ToString(); 728 // Build the string used to uniquely identify connections of this type.
729 // Determine the host and port to connect to.
730 std::string connection_group = endpoint_.ToString();
745 DCHECK(!connection_group.empty()); 731 DCHECK(!connection_group.empty());
746 732
747 if (using_ssl_) 733 if (using_ssl_)
748 connection_group = StringPrintf("ssl/%s", connection_group.c_str()); 734 connection_group = StringPrintf("ssl/%s", connection_group.c_str());
749 735
750 // If the user is refreshing the page, bypass the host cache. 736 // If the user is refreshing the page, bypass the host cache.
751 bool disable_resolver_cache = request_->load_flags & LOAD_BYPASS_CACHE || 737 bool disable_resolver_cache = request_->load_flags & LOAD_BYPASS_CACHE ||
752 request_->load_flags & LOAD_VALIDATE_CACHE || 738 request_->load_flags & LOAD_VALIDATE_CACHE ||
753 request_->load_flags & LOAD_DISABLE_CACHE; 739 request_->load_flags & LOAD_DISABLE_CACHE;
754 740
755 int rv; 741 // Build up the connection parameters.
756 if (!proxy_info_.is_direct()) { 742 scoped_refptr<TCPSocketParams> tcp_params;
743 scoped_refptr<HttpProxySocketParams> http_proxy_params;
744 scoped_refptr<SOCKSSocketParams> socks_params;
745 scoped_ptr<HostPortPair> proxy_host_port;
746
747 if (proxy_info_.is_direct()) {
748 tcp_params = new TCPSocketParams(endpoint_, request_->priority,
749 request_->referrer,
750 disable_resolver_cache);
751 } else {
757 ProxyServer proxy_server = proxy_info_.proxy_server(); 752 ProxyServer proxy_server = proxy_info_.proxy_server();
758 HostPortPair proxy_host_port_pair(proxy_server.HostNoBrackets(), 753 proxy_host_port.reset(new HostPortPair(proxy_server.HostNoBrackets(),
759 proxy_server.port()); 754 proxy_server.port()));
760 755 scoped_refptr<TCPSocketParams> proxy_tcp_params =
761 scoped_refptr<TCPSocketParams> tcp_params = 756 new TCPSocketParams(*proxy_host_port, request_->priority,
762 new TCPSocketParams(proxy_host_port_pair, request_->priority,
763 request_->referrer, disable_resolver_cache); 757 request_->referrer, disable_resolver_cache);
764 758
765 if (proxy_info_.is_socks()) { 759 if (proxy_info_.is_http()) {
766 const char* socks_version;
767 bool socks_v5;
768 if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5) {
769 socks_version = "5";
770 socks_v5 = true;
771 } else {
772 socks_version = "4";
773 socks_v5 = false;
774 }
775
776 connection_group =
777 StringPrintf("socks%s/%s", socks_version, connection_group.c_str());
778
779 scoped_refptr<SOCKSSocketParams> socks_params =
780 new SOCKSSocketParams(tcp_params, socks_v5, endpoint_,
781 request_->priority, request_->referrer);
782
783 rv = connection_->Init(
784 connection_group, socks_params, request_->priority,
785 &io_callback_,
786 session_->GetSocketPoolForSOCKSProxy(proxy_host_port_pair), net_log_);
787 } else {
788 DCHECK(proxy_info_.is_http());
789 scoped_refptr<HttpAuthController> http_proxy_auth; 760 scoped_refptr<HttpAuthController> http_proxy_auth;
790 if (using_ssl_) { 761 if (using_ssl_) {
791 http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY]; 762 http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY];
792 establishing_tunnel_ = true; 763 establishing_tunnel_ = true;
793 } 764 }
765 http_proxy_params = new HttpProxySocketParams(proxy_tcp_params,
766 request_->url, endpoint_,
767 http_proxy_auth,
768 using_ssl_);
769 } else {
770 DCHECK(proxy_info_.is_socks());
771 char socks_version;
772 if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5)
773 socks_version = '5';
774 else
775 socks_version = '4';
776 connection_group =
777 StringPrintf("socks%c/%s", socks_version, connection_group.c_str());
794 778
795 scoped_refptr<HttpProxySocketParams> http_proxy_params = 779 socks_params = new SOCKSSocketParams(proxy_tcp_params,
796 new HttpProxySocketParams(tcp_params, request_->url, endpoint_, 780 socks_version == '5',
797 http_proxy_auth, using_ssl_); 781 endpoint_,
782 request_->priority,
783 request_->referrer);
784 }
785 }
798 786
799 rv = connection_->Init(connection_group, http_proxy_params, 787 // Deal with SSL - which layers on top of any given proxy.
800 request_->priority, &io_callback_, 788 if (using_ssl_) {
801 session_->GetSocketPoolForHTTPProxy( 789 if (ContainsKey(*g_tls_intolerant_servers, GetHostAndPort(request_->url))) {
802 proxy_host_port_pair), 790 LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
803 net_log_); 791 << GetHostAndPort(request_->url);
792 ssl_config_.tls1_enabled = false;
804 } 793 }
805 } else { 794
806 scoped_refptr<TCPSocketParams> tcp_params = 795 int load_flags = request_->load_flags;
807 new TCPSocketParams(endpoint_, request_->priority, request_->referrer, 796 if (g_ignore_certificate_errors)
808 disable_resolver_cache); 797 load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
809 rv = connection_->Init(connection_group, tcp_params, request_->priority, 798 if (request_->load_flags & LOAD_VERIFY_EV_CERT)
799 ssl_config_.verify_ev_cert = true;
800
801 scoped_refptr<SSLSocketParams> ssl_params =
802 new SSLSocketParams(tcp_params, http_proxy_params, socks_params,
803 proxy_info_.proxy_server().scheme(),
804 request_->url.HostNoBrackets(), ssl_config_,
805 load_flags, want_spdy);
806
807 scoped_refptr<SSLClientSocketPool> ssl_pool;
808 if (proxy_info_.is_direct())
809 ssl_pool = session_->ssl_socket_pool();
810 else
811 ssl_pool = session_->GetSocketPoolForSSLWithProxy(*proxy_host_port);
812
813 return connection_->Init(connection_group, ssl_params, request_->priority,
814 &io_callback_, ssl_pool, net_log_);
815 }
816
817 // Finally, get the connection started.
818 if (proxy_info_.is_http()) {
819 return connection_->Init(
820 connection_group, http_proxy_params, request_->priority, &io_callback_,
821 session_->GetSocketPoolForHTTPProxy(*proxy_host_port), net_log_);
822 }
823
824 if (proxy_info_.is_socks()) {
825 return connection_->Init(
826 connection_group, socks_params, request_->priority, &io_callback_,
827 session_->GetSocketPoolForSOCKSProxy(*proxy_host_port), net_log_);
828 }
829
830 DCHECK(proxy_info_.is_direct());
831 return connection_->Init(connection_group, tcp_params, request_->priority,
810 &io_callback_, session_->tcp_socket_pool(), 832 &io_callback_, session_->tcp_socket_pool(),
811 net_log_); 833 net_log_);
812 }
813
814 return rv;
815 } 834 }
816 835
817 int HttpNetworkTransaction::DoInitConnectionComplete(int result) { 836 int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
818 if (result < 0) { 837 // |result| may be the result of any of the stacked pools. The following
819 if (result == ERR_RETRY_CONNECTION) { 838 // logic is used when determining how to interpret an error.
820 DCHECK(establishing_tunnel_); 839 // If |result| < 0:
821 next_state_ = STATE_INIT_CONNECTION; 840 // and connection_->socket() != NULL, then the SSL handshake ran and it
822 connection_->socket()->Disconnect(); 841 // is a potentially recoverable error.
823 connection_->Reset(); 842 // and connection_->socket == NULL and connection_->is_ssl_error() is true,
824 return OK; 843 // then the SSL handshake ran with an unrecoverable error.
844 // otherwise, the error came from one of the other pools.
845 bool ssl_started = using_ssl_ && (result == OK || connection_->socket() ||
846 connection_->is_ssl_error());
847
848 if (ssl_started && (result == OK || IsCertificateError(result))) {
849 SSLClientSocket* ssl_socket =
850 static_cast<SSLClientSocket*>(connection_->socket());
851 if (ssl_socket->wasNpnNegotiated()) {
852 response_.was_npn_negotiated = true;
853 std::string proto;
854 ssl_socket->GetNextProto(&proto);
855 if (SSLClientSocket::NextProtoFromString(proto) ==
856 SSLClientSocket::kProtoSPDY1)
857 using_spdy_ = true;
825 } 858 }
826
827 if (result == ERR_PROXY_AUTH_REQUESTED) {
828 DCHECK(establishing_tunnel_);
829 HttpProxyClientSocket* tunnel_socket =
830 static_cast<HttpProxyClientSocket*>(connection_->socket());
831 DCHECK(tunnel_socket);
832 DCHECK(!tunnel_socket->IsConnected());
833 const HttpResponseInfo* auth_response = tunnel_socket->GetResponseInfo();
834
835 response_.headers = auth_response->headers;
836 headers_valid_ = true;
837 response_.auth_challenge = auth_response->auth_challenge;
838 pending_auth_target_ = HttpAuth::AUTH_PROXY;
839 return OK;
840 }
841
842 if (alternate_protocol_mode_ == kUsingAlternateProtocol) {
843 // Mark the alternate protocol as broken and fallback.
844 MarkBrokenAlternateProtocolAndFallback();
845 return OK;
846 }
847
848 return ReconsiderProxyAfterError(result);
849 } 859 }
850 860
851 DCHECK_EQ(OK, result); 861 if (result == ERR_PROXY_AUTH_REQUESTED) {
852 if (establishing_tunnel_) { 862 DCHECK(!ssl_started);
853 DCHECK(connection_->socket()->IsConnected()); 863 const HttpResponseInfo& tunnel_auth_response =
854 establishing_tunnel_ = false; 864 connection_->tunnel_auth_response_info();
855 }
856 865
857 if (using_spdy_) { 866 response_.headers = tunnel_auth_response.headers;
858 DCHECK(!connection_->is_initialized()); 867 response_.auth_challenge = tunnel_auth_response.auth_challenge;
859 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620 868 headers_valid_ = true;
860 next_state_ = STATE_SPDY_SEND_REQUEST; 869 pending_auth_target_ = HttpAuth::AUTH_PROXY;
861 return OK; 870 return OK;
862 } 871 }
863 872
864 LogHttpConnectedMetrics(*connection_); 873 if ((!ssl_started && result < 0 &&
865 874 alternate_protocol_mode_ == kUsingAlternateProtocol) ||
866 // Set the reused_socket_ flag to indicate that we are using a keep-alive 875 result == ERR_NPN_NEGOTIATION_FAILED) {
867 // connection. This flag is used to handle errors that occur while we are 876 // Mark the alternate protocol as broken and fallback.
868 // trying to reuse a keep-alive connection.
869 reused_socket_ = connection_->is_reused();
870 if (reused_socket_) {
871 if (using_ssl_) {
872 SSLClientSocket* ssl_socket =
873 reinterpret_cast<SSLClientSocket*>(connection_->socket());
874 response_.was_npn_negotiated = ssl_socket->wasNpnNegotiated();
875 }
876 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
877 } else {
878 // Now we have a TCP connected socket. Perform other connection setup as
879 // needed.
880 UpdateConnectionTypeHistograms(CONNECTION_HTTP);
881 if (using_ssl_)
882 next_state_ = STATE_SSL_CONNECT;
883 else
884 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
885 }
886
887 return OK;
888 }
889
890 int HttpNetworkTransaction::DoTunnelRestartWithAuth() {
891 next_state_ = STATE_INIT_CONNECTION_COMPLETE;
892 HttpProxyClientSocket* tunnel_socket =
893 reinterpret_cast<HttpProxyClientSocket*>(connection_->socket());
894
895 return tunnel_socket->RestartWithAuth(&io_callback_);
896 }
897
898 int HttpNetworkTransaction::DoSSLConnect() {
899 next_state_ = STATE_SSL_CONNECT_COMPLETE;
900
901 if (ContainsKey(*g_tls_intolerant_servers, GetHostAndPort(request_->url))) {
902 LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
903 << GetHostAndPort(request_->url);
904 ssl_config_.tls1_enabled = false;
905 }
906
907 if (request_->load_flags & LOAD_VERIFY_EV_CERT)
908 ssl_config_.verify_ev_cert = true;
909
910 ssl_connect_start_time_ = base::TimeTicks::Now();
911
912 // Add a SSL socket on top of our existing transport socket.
913 ClientSocket* s = connection_->release_socket();
914 s = session_->socket_factory()->CreateSSLClientSocket(
915 s, request_->url.HostNoBrackets(), ssl_config_);
916 connection_->set_socket(s);
917 return connection_->socket()->Connect(&io_callback_);
918 }
919
920 int HttpNetworkTransaction::DoSSLConnectComplete(int result) {
921 SSLClientSocket* ssl_socket =
922 reinterpret_cast<SSLClientSocket*>(connection_->socket());
923
924 SSLClientSocket::NextProtoStatus status =
925 SSLClientSocket::kNextProtoUnsupported;
926 std::string proto;
927 // GetNextProto will fail and and trigger a NOTREACHED if we pass in a socket
928 // that hasn't had SSL_ImportFD called on it. If we get a certificate error
929 // here, then we know that we called SSL_ImportFD.
930 if (result == OK || IsCertificateError(result))
931 status = ssl_socket->GetNextProto(&proto);
932
933 if (status == SSLClientSocket::kNextProtoNegotiated) {
934 ssl_socket->setWasNpnNegotiated(true);
935 response_.was_npn_negotiated = true;
936 if (SSLClientSocket::NextProtoFromString(proto) ==
937 SSLClientSocket::kProtoSPDY1) {
938 using_spdy_ = true;
939 }
940 }
941
942 if (alternate_protocol_mode_ == kUsingAlternateProtocol &&
943 alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_1 &&
944 !using_spdy_) {
945 // We tried using the NPN_SPDY_1 alternate protocol, but failed, so we
946 // fallback.
947 MarkBrokenAlternateProtocolAndFallback(); 877 MarkBrokenAlternateProtocolAndFallback();
948 return OK; 878 return OK;
949 } 879 }
950 880
881 if (result < 0 && !ssl_started)
882 return ReconsiderProxyAfterError(result);
883 establishing_tunnel_ = false;
884
885 if (connection_->socket()) {
886 LogHttpConnectedMetrics(*connection_);
887
888 // Set the reused_socket_ flag to indicate that we are using a keep-alive
889 // connection. This flag is used to handle errors that occur while we are
890 // trying to reuse a keep-alive connection.
891 reused_socket_ = connection_->is_reused();
892 // TODO(vandebo) should we exclude SPDY in the following if?
893 if (!reused_socket_)
894 UpdateConnectionTypeHistograms(CONNECTION_HTTP);
895
896 if (!using_ssl_) {
897 DCHECK_EQ(OK, result);
898 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
899 return result;
900 }
901 }
902
903 // Handle SSL errors below.
904 DCHECK(using_ssl_);
905 DCHECK(ssl_started);
951 if (IsCertificateError(result)) { 906 if (IsCertificateError(result)) {
952 if (using_spdy_ && request_->url.SchemeIs("http")) { 907 if (using_spdy_ && request_->url.SchemeIs("http")) {
953 // We ignore certificate errors for http over spdy. 908 // We ignore certificate errors for http over spdy.
954 spdy_certificate_error_ = result; 909 spdy_certificate_error_ = result;
955 result = OK; 910 result = OK;
956 } else { 911 } else {
957 result = HandleCertificateError(result); 912 result = HandleCertificateError(result);
958 if (result == OK && !connection_->socket()->IsConnectedAndIdle()) { 913 if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
959 connection_->socket()->Disconnect(); 914 connection_->socket()->Disconnect();
960 connection_->Reset(); 915 connection_->Reset();
961 next_state_ = STATE_INIT_CONNECTION; 916 next_state_ = STATE_INIT_CONNECTION;
962 return result; 917 return result;
963 } 918 }
964 } 919 }
965 } 920 }
966 921
967 if (result == OK) { 922 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
968 DCHECK(ssl_connect_start_time_ != base::TimeTicks()); 923 return HandleCertificateRequest(result);
969 base::TimeDelta connect_duration = 924 if (result < 0)
970 base::TimeTicks::Now() - ssl_connect_start_time_; 925 return HandleSSLHandshakeError(result);
971 926
972 if (using_spdy_) { 927 if (using_spdy_) {
973 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency", 928 UpdateConnectionTypeHistograms(CONNECTION_SPDY);
974 connect_duration, 929 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620
975 base::TimeDelta::FromMilliseconds(1), 930 next_state_ = STATE_SPDY_SEND_REQUEST;
976 base::TimeDelta::FromMinutes(10),
977 100);
978
979 UpdateConnectionTypeHistograms(CONNECTION_SPDY);
980 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620
981 next_state_ = STATE_SPDY_SEND_REQUEST;
982 } else {
983 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency",
984 connect_duration,
985 base::TimeDelta::FromMilliseconds(1),
986 base::TimeDelta::FromMinutes(10),
987 100);
988
989 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
990 }
991 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
992 result = HandleCertificateRequest(result);
993 } else { 931 } else {
994 result = HandleSSLHandshakeError(result); 932 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
995 } 933 }
996 return result; 934 return OK;
997 } 935 }
998 936
999 int HttpNetworkTransaction::DoGenerateProxyAuthToken() { 937 int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
1000 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; 938 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
1001 if (!ShouldApplyProxyAuth()) 939 if (!ShouldApplyProxyAuth())
1002 return OK; 940 return OK;
1003 return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken( 941 return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken(
1004 request_, &io_callback_, net_log_); 942 request_, &io_callback_, net_log_);
1005 } 943 }
1006 944
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 ProcessAlternateProtocol(*response_.headers, 1122 ProcessAlternateProtocol(*response_.headers,
1185 endpoint_, 1123 endpoint_,
1186 session_->mutable_alternate_protocols()); 1124 session_->mutable_alternate_protocols());
1187 1125
1188 int rv = HandleAuthChallenge(); 1126 int rv = HandleAuthChallenge();
1189 if (rv != OK) 1127 if (rv != OK)
1190 return rv; 1128 return rv;
1191 1129
1192 if (using_ssl_) { 1130 if (using_ssl_) {
1193 SSLClientSocket* ssl_socket = 1131 SSLClientSocket* ssl_socket =
1194 reinterpret_cast<SSLClientSocket*>(connection_->socket()); 1132 static_cast<SSLClientSocket*>(connection_->socket());
1195 ssl_socket->GetSSLInfo(&response_.ssl_info); 1133 ssl_socket->GetSSLInfo(&response_.ssl_info);
1196 } 1134 }
1197 1135
1198 headers_valid_ = true; 1136 headers_valid_ = true;
1199 return OK; 1137 return OK;
1200 } 1138 }
1201 1139
1202 int HttpNetworkTransaction::DoReadBody() { 1140 int HttpNetworkTransaction::DoReadBody() {
1203 DCHECK(read_buf_); 1141 DCHECK(read_buf_);
1204 DCHECK_GT(read_buf_len_, 0); 1142 DCHECK_GT(read_buf_len_, 0);
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1527 total_duration, base::TimeDelta::FromMilliseconds(1), 1465 total_duration, base::TimeDelta::FromMilliseconds(1),
1528 base::TimeDelta::FromMinutes(10), 100); 1466 base::TimeDelta::FromMinutes(10), 100);
1529 } 1467 }
1530 } 1468 }
1531 1469
1532 int HttpNetworkTransaction::HandleCertificateError(int error) { 1470 int HttpNetworkTransaction::HandleCertificateError(int error) {
1533 DCHECK(using_ssl_); 1471 DCHECK(using_ssl_);
1534 DCHECK(IsCertificateError(error)); 1472 DCHECK(IsCertificateError(error));
1535 1473
1536 SSLClientSocket* ssl_socket = 1474 SSLClientSocket* ssl_socket =
1537 reinterpret_cast<SSLClientSocket*>(connection_->socket()); 1475 static_cast<SSLClientSocket*>(connection_->socket());
1538 ssl_socket->GetSSLInfo(&response_.ssl_info); 1476 ssl_socket->GetSSLInfo(&response_.ssl_info);
1539 1477
1540 // Add the bad certificate to the set of allowed certificates in the 1478 // Add the bad certificate to the set of allowed certificates in the
1541 // SSL info object. This data structure will be consulted after calling 1479 // SSL info object. This data structure will be consulted after calling
1542 // RestartIgnoringLastError(). And the user will be asked interactively 1480 // RestartIgnoringLastError(). And the user will be asked interactively
1543 // before RestartIgnoringLastError() is ever called. 1481 // before RestartIgnoringLastError() is ever called.
1544 SSLConfig::CertAndStatus bad_cert; 1482 SSLConfig::CertAndStatus bad_cert;
1545 bad_cert.cert = response_.ssl_info.cert; 1483 bad_cert.cert = response_.ssl_info.cert;
1546 bad_cert.cert_status = response_.ssl_info.cert_status; 1484 bad_cert.cert_status = response_.ssl_info.cert_status;
1547 ssl_config_.allowed_bad_certs.push_back(bad_cert); 1485 ssl_config_.allowed_bad_certs.push_back(bad_cert);
1548 1486
1487 int load_flags = request_->load_flags;
1549 if (g_ignore_certificate_errors) 1488 if (g_ignore_certificate_errors)
1489 load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
1490 if (ssl_socket->IgnoreCertError(error, load_flags))
1550 return OK; 1491 return OK;
1551
1552 const int kCertFlags = LOAD_IGNORE_CERT_COMMON_NAME_INVALID |
1553 LOAD_IGNORE_CERT_DATE_INVALID |
1554 LOAD_IGNORE_CERT_AUTHORITY_INVALID |
1555 LOAD_IGNORE_CERT_WRONG_USAGE;
1556 if (request_->load_flags & kCertFlags) {
1557 switch (error) {
1558 case ERR_CERT_COMMON_NAME_INVALID:
1559 if (request_->load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID)
1560 error = OK;
1561 break;
1562 case ERR_CERT_DATE_INVALID:
1563 if (request_->load_flags & LOAD_IGNORE_CERT_DATE_INVALID)
1564 error = OK;
1565 break;
1566 case ERR_CERT_AUTHORITY_INVALID:
1567 if (request_->load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID)
1568 error = OK;
1569 break;
1570 }
1571 }
1572 return error; 1492 return error;
1573 } 1493 }
1574 1494
1575 int HttpNetworkTransaction::HandleCertificateRequest(int error) { 1495 int HttpNetworkTransaction::HandleCertificateRequest(int error) {
1576 // Assert that the socket did not send a client certificate. 1496 // Assert that the socket did not send a client certificate.
1577 // Note: If we got a reused socket, it was created with some other 1497 // Note: If we got a reused socket, it was created with some other
1578 // transaction's ssl_config_, so we need to disable this assertion. We can 1498 // transaction's ssl_config_, so we need to disable this assertion. We can
1579 // get a certificate request on a reused socket when the server requested 1499 // get a certificate request on a reused socket when the server requested
1580 // renegotiation (rehandshake). 1500 // renegotiation (rehandshake).
1581 // TODO(wtc): add a GetSSLParams method to SSLClientSocket so we can query 1501 // TODO(wtc): add a GetSSLParams method to SSLClientSocket so we can query
1582 // the SSL parameters it was created with and get rid of the reused_socket_ 1502 // the SSL parameters it was created with and get rid of the reused_socket_
1583 // test. 1503 // test.
1584 DCHECK(reused_socket_ || !ssl_config_.send_client_cert); 1504 DCHECK(reused_socket_ || !ssl_config_.send_client_cert);
1585 1505
1586 response_.cert_request_info = new SSLCertRequestInfo; 1506 response_.cert_request_info = new SSLCertRequestInfo;
1587 SSLClientSocket* ssl_socket = 1507 SSLClientSocket* ssl_socket =
1588 reinterpret_cast<SSLClientSocket*>(connection_->socket()); 1508 static_cast<SSLClientSocket*>(connection_->socket());
1589 ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info); 1509 ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info);
1590 1510
1591 // Close the connection while the user is selecting a certificate to send 1511 // Close the connection while the user is selecting a certificate to send
1592 // to the server. 1512 // to the server.
1593 connection_->socket()->Disconnect(); 1513 connection_->socket()->Disconnect();
1594 connection_->Reset(); 1514 connection_->Reset();
1595 1515
1596 // If the user selected one of the certificate in client_certs for this 1516 // If the user selected one of the certificate in client_certs for this
1597 // server before, use it automatically. 1517 // server before, use it automatically.
1598 X509Certificate* client_cert = session_->ssl_client_auth_cache()-> 1518 X509Certificate* client_cert = session_->ssl_client_auth_cache()->
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1683 // This automatically prevents an infinite resend loop because we'll run 1603 // This automatically prevents an infinite resend loop because we'll run
1684 // out of the cached keep-alive connections eventually. 1604 // out of the cached keep-alive connections eventually.
1685 if (!connection_->ShouldResendFailedRequest(error) || 1605 if (!connection_->ShouldResendFailedRequest(error) ||
1686 GetResponseHeaders()) { // We have received some response headers. 1606 GetResponseHeaders()) { // We have received some response headers.
1687 return false; 1607 return false;
1688 } 1608 }
1689 return true; 1609 return true;
1690 } 1610 }
1691 1611
1692 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() { 1612 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
1693 connection_->socket()->Disconnect(); 1613 if (connection_->socket())
1614 connection_->socket()->Disconnect();
1694 connection_->Reset(); 1615 connection_->Reset();
1695 // We need to clear request_headers_ because it contains the real request 1616 // We need to clear request_headers_ because it contains the real request
1696 // headers, but we may need to resend the CONNECT request first to recreate 1617 // headers, but we may need to resend the CONNECT request first to recreate
1697 // the SSL tunnel. 1618 // the SSL tunnel.
1619
1698 request_headers_.clear(); 1620 request_headers_.clear();
1699 next_state_ = STATE_INIT_CONNECTION; // Resend the request. 1621 next_state_ = STATE_INIT_CONNECTION; // Resend the request.
1700 } 1622 }
1701 1623
1702 int HttpNetworkTransaction::ReconsiderProxyAfterError(int error) { 1624 int HttpNetworkTransaction::ReconsiderProxyAfterError(int error) {
1703 DCHECK(!pac_request_); 1625 DCHECK(!pac_request_);
1704 1626
1705 // A failure to resolve the hostname or any error related to establishing a 1627 // A failure to resolve the hostname or any error related to establishing a
1706 // TCP connection could be grounds for trying a new proxy configuration. 1628 // TCP connection could be grounds for trying a new proxy configuration.
1707 // 1629 //
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1866 default: 1788 default:
1867 description = StringPrintf("Unknown state 0x%08X (%u)", state, state); 1789 description = StringPrintf("Unknown state 0x%08X (%u)", state, state);
1868 break; 1790 break;
1869 } 1791 }
1870 return description; 1792 return description;
1871 } 1793 }
1872 1794
1873 #undef STATE_CASE 1795 #undef STATE_CASE
1874 1796
1875 } // namespace net 1797 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698