OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 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 // TODO(ukai): code is similar with http_network_transaction.cc. We should | 5 // TODO(ukai): code is similar with http_network_transaction.cc. We should |
6 // think about ways to share code, if possible. | 6 // think about ways to share code, if possible. |
7 | 7 |
8 #include "net/socket_stream/socket_stream.h" | 8 #include "net/socket_stream/socket_stream.h" |
9 | 9 |
10 #include <set> | 10 #include <set> |
11 #include <string> | 11 #include <string> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
16 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/message_loop.h" | 18 #include "base/message_loop.h" |
19 #include "base/string_util.h" | 19 #include "base/string_util.h" |
20 #include "base/stringprintf.h" | 20 #include "base/stringprintf.h" |
21 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
22 #include "net/base/auth.h" | 22 #include "net/base/auth.h" |
23 #include "net/base/host_resolver.h" | 23 #include "net/base/host_resolver.h" |
24 #include "net/base/io_buffer.h" | 24 #include "net/base/io_buffer.h" |
25 #include "net/base/net_errors.h" | 25 #include "net/base/net_errors.h" |
26 #include "net/base/net_util.h" | 26 #include "net/base/net_util.h" |
27 #include "net/base/ssl_cert_request_info.h" | 27 #include "net/base/ssl_cert_request_info.h" |
28 #include "net/http/http_auth_controller.h" | |
28 #include "net/http/http_auth_handler_factory.h" | 29 #include "net/http/http_auth_handler_factory.h" |
cbentzel
2012/08/15 18:08:01
http_auth_handler_factory include no longer needed
bashi
2012/08/20 01:35:10
Done.
| |
29 #include "net/http/http_network_session.h" | 30 #include "net/http/http_network_session.h" |
31 #include "net/http/http_request_headers.h" | |
30 #include "net/http/http_request_info.h" | 32 #include "net/http/http_request_info.h" |
31 #include "net/http/http_response_headers.h" | 33 #include "net/http/http_response_headers.h" |
32 #include "net/http/http_stream_factory.h" | 34 #include "net/http/http_stream_factory.h" |
33 #include "net/http/http_transaction_factory.h" | 35 #include "net/http/http_transaction_factory.h" |
34 #include "net/http/http_util.h" | 36 #include "net/http/http_util.h" |
35 #include "net/socket/client_socket_factory.h" | 37 #include "net/socket/client_socket_factory.h" |
36 #include "net/socket/socks5_client_socket.h" | 38 #include "net/socket/socks5_client_socket.h" |
37 #include "net/socket/socks_client_socket.h" | 39 #include "net/socket/socks_client_socket.h" |
38 #include "net/socket/ssl_client_socket.h" | 40 #include "net/socket/ssl_client_socket.h" |
39 #include "net/socket/tcp_client_socket.h" | 41 #include "net/socket/tcp_client_socket.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 | 87 |
86 SocketStream::SocketStream(const GURL& url, Delegate* delegate) | 88 SocketStream::SocketStream(const GURL& url, Delegate* delegate) |
87 : delegate_(delegate), | 89 : delegate_(delegate), |
88 url_(url), | 90 url_(url), |
89 max_pending_send_allowed_(kMaxPendingSendAllowed), | 91 max_pending_send_allowed_(kMaxPendingSendAllowed), |
90 context_(NULL), | 92 context_(NULL), |
91 next_state_(STATE_NONE), | 93 next_state_(STATE_NONE), |
92 host_resolver_(NULL), | 94 host_resolver_(NULL), |
93 cert_verifier_(NULL), | 95 cert_verifier_(NULL), |
94 server_bound_cert_service_(NULL), | 96 server_bound_cert_service_(NULL), |
95 http_auth_handler_factory_(NULL), | |
96 factory_(ClientSocketFactory::GetDefaultFactory()), | 97 factory_(ClientSocketFactory::GetDefaultFactory()), |
97 proxy_mode_(kDirectConnection), | 98 proxy_mode_(kDirectConnection), |
98 proxy_url_(url), | 99 proxy_url_(url), |
99 pac_request_(NULL), | 100 pac_request_(NULL), |
100 // Unretained() is required; without it, Bind() creates a circular | 101 // Unretained() is required; without it, Bind() creates a circular |
101 // dependency and the SocketStream object will not be freed. | 102 // dependency and the SocketStream object will not be freed. |
102 ALLOW_THIS_IN_INITIALIZER_LIST( | 103 ALLOW_THIS_IN_INITIALIZER_LIST( |
103 io_callback_(base::Bind(&SocketStream::OnIOCompleted, | 104 io_callback_(base::Bind(&SocketStream::OnIOCompleted, |
104 base::Unretained(this)))), | 105 base::Unretained(this)))), |
105 read_buf_(NULL), | 106 read_buf_(NULL), |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 NetLog::SOURCE_SOCKET_STREAM); | 154 NetLog::SOURCE_SOCKET_STREAM); |
154 | 155 |
155 net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE); | 156 net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE); |
156 } | 157 } |
157 } | 158 } |
158 | 159 |
159 if (context_) { | 160 if (context_) { |
160 host_resolver_ = context_->host_resolver(); | 161 host_resolver_ = context_->host_resolver(); |
161 cert_verifier_ = context_->cert_verifier(); | 162 cert_verifier_ = context_->cert_verifier(); |
162 server_bound_cert_service_ = context_->server_bound_cert_service(); | 163 server_bound_cert_service_ = context_->server_bound_cert_service(); |
163 http_auth_handler_factory_ = context_->http_auth_handler_factory(); | |
164 } | 164 } |
165 } | 165 } |
166 | 166 |
167 void SocketStream::Connect() { | 167 void SocketStream::Connect() { |
168 DCHECK(MessageLoop::current()) << | 168 DCHECK(MessageLoop::current()) << |
169 "The current MessageLoop must exist"; | 169 "The current MessageLoop must exist"; |
170 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << | 170 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << |
171 "The current MessageLoop must be TYPE_IO"; | 171 "The current MessageLoop must be TYPE_IO"; |
172 if (context_) { | 172 if (context_) { |
173 ssl_config_service()->GetSSLConfig(&server_ssl_config_); | 173 ssl_config_service()->GetSSLConfig(&server_ssl_config_); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
237 MessageLoop::current()->PostTask( | 237 MessageLoop::current()->PostTask( |
238 FROM_HERE, | 238 FROM_HERE, |
239 base::Bind(&SocketStream::DoClose, this)); | 239 base::Bind(&SocketStream::DoClose, this)); |
240 } | 240 } |
241 | 241 |
242 void SocketStream::RestartWithAuth(const AuthCredentials& credentials) { | 242 void SocketStream::RestartWithAuth(const AuthCredentials& credentials) { |
243 DCHECK(MessageLoop::current()) << | 243 DCHECK(MessageLoop::current()) << |
244 "The current MessageLoop must exist"; | 244 "The current MessageLoop must exist"; |
245 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << | 245 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << |
246 "The current MessageLoop must be TYPE_IO"; | 246 "The current MessageLoop must be TYPE_IO"; |
247 DCHECK(auth_handler_.get()); | 247 DCHECK(proxy_auth_controller_.get()); |
248 if (!socket_.get()) { | 248 if (!socket_.get()) { |
249 LOG(ERROR) << "Socket is closed before restarting with auth."; | 249 LOG(ERROR) << "Socket is closed before restarting with auth."; |
250 return; | 250 return; |
251 } | 251 } |
252 | 252 |
253 if (auth_identity_.invalid) { | 253 proxy_auth_controller_->ResetAuth(credentials); |
254 // Update the credentials. | |
255 auth_identity_.source = HttpAuth::IDENT_SRC_EXTERNAL; | |
256 auth_identity_.invalid = false; | |
257 auth_identity_.credentials = credentials; | |
258 } | |
259 | 254 |
260 MessageLoop::current()->PostTask( | 255 MessageLoop::current()->PostTask( |
261 FROM_HERE, | 256 FROM_HERE, |
262 base::Bind(&SocketStream::DoRestartWithAuth, this)); | 257 base::Bind(&SocketStream::DoRestartWithAuth, this)); |
263 } | 258 } |
264 | 259 |
265 void SocketStream::DetachDelegate() { | 260 void SocketStream::DetachDelegate() { |
266 if (!delegate_) | 261 if (!delegate_) |
267 return; | 262 return; |
268 delegate_ = NULL; | 263 delegate_ = NULL; |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 break; | 463 break; |
469 case STATE_RESOLVE_PROTOCOL_COMPLETE: | 464 case STATE_RESOLVE_PROTOCOL_COMPLETE: |
470 result = DoResolveProtocolComplete(result); | 465 result = DoResolveProtocolComplete(result); |
471 break; | 466 break; |
472 case STATE_TCP_CONNECT: | 467 case STATE_TCP_CONNECT: |
473 result = DoTcpConnect(result); | 468 result = DoTcpConnect(result); |
474 break; | 469 break; |
475 case STATE_TCP_CONNECT_COMPLETE: | 470 case STATE_TCP_CONNECT_COMPLETE: |
476 result = DoTcpConnectComplete(result); | 471 result = DoTcpConnectComplete(result); |
477 break; | 472 break; |
473 case STATE_GENERATE_PROXY_AUTH_TOKEN: | |
474 result = DoGenerateProxyAuthToken(); | |
475 break; | |
476 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: | |
477 result = DoGenerateProxyAuthTokenComplete(result); | |
478 break; | |
478 case STATE_WRITE_TUNNEL_HEADERS: | 479 case STATE_WRITE_TUNNEL_HEADERS: |
479 DCHECK_EQ(OK, result); | 480 DCHECK_EQ(OK, result); |
480 result = DoWriteTunnelHeaders(); | 481 result = DoWriteTunnelHeaders(); |
481 break; | 482 break; |
482 case STATE_WRITE_TUNNEL_HEADERS_COMPLETE: | 483 case STATE_WRITE_TUNNEL_HEADERS_COMPLETE: |
483 result = DoWriteTunnelHeadersComplete(result); | 484 result = DoWriteTunnelHeadersComplete(result); |
484 break; | 485 break; |
485 case STATE_READ_TUNNEL_HEADERS: | 486 case STATE_READ_TUNNEL_HEADERS: |
486 DCHECK_EQ(OK, result); | 487 DCHECK_EQ(OK, result); |
487 result = DoReadTunnelHeaders(); | 488 result = DoReadTunnelHeaders(); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
601 LOG(ERROR) << "Failed to resolve proxy: " << result; | 602 LOG(ERROR) << "Failed to resolve proxy: " << result; |
602 if (delegate_) | 603 if (delegate_) |
603 delegate_->OnError(this, result); | 604 delegate_->OnError(this, result); |
604 proxy_info_.UseDirect(); | 605 proxy_info_.UseDirect(); |
605 } | 606 } |
606 if (proxy_info_.is_direct()) { | 607 if (proxy_info_.is_direct()) { |
607 // If proxy was not found for original URL (i.e. websocket URL), | 608 // If proxy was not found for original URL (i.e. websocket URL), |
608 // try again with https URL, like Safari implementation. | 609 // try again with https URL, like Safari implementation. |
609 // Note that we don't want to use http proxy, because we'll use tunnel | 610 // Note that we don't want to use http proxy, because we'll use tunnel |
610 // proxy using CONNECT method, which is used by https proxy. | 611 // proxy using CONNECT method, which is used by https proxy. |
611 if (!proxy_url_.SchemeIs("https")) { | 612 if (!proxy_url_.SchemeIs("https")) { |
cbentzel
2012/08/15 18:08:01
Not part of this CL - but do you only want to do t
bashi
2012/08/20 01:35:10
I'm not familiar with the logic, but according to
cbentzel
2012/08/20 11:23:01
What is going on here is if you fail to find a pro
bashi
2012/08/22 08:36:44
Sorry for lack of explanation. I should have said
| |
612 const std::string scheme = "https"; | 613 const std::string scheme = "https"; |
613 GURL::Replacements repl; | 614 GURL::Replacements repl; |
614 repl.SetSchemeStr(scheme); | 615 repl.SetSchemeStr(scheme); |
615 proxy_url_ = url_.ReplaceComponents(repl); | 616 proxy_url_ = url_.ReplaceComponents(repl); |
616 DVLOG(1) << "Try https proxy: " << proxy_url_; | 617 DVLOG(1) << "Try https proxy: " << proxy_url_; |
617 next_state_ = STATE_RESOLVE_PROXY; | 618 next_state_ = STATE_RESOLVE_PROXY; |
618 return OK; | 619 return OK; |
619 } | 620 } |
620 } | 621 } |
621 | 622 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
701 } | 702 } |
702 next_state_ = STATE_TCP_CONNECT_COMPLETE; | 703 next_state_ = STATE_TCP_CONNECT_COMPLETE; |
703 DCHECK(factory_); | 704 DCHECK(factory_); |
704 socket_.reset(factory_->CreateTransportClientSocket(addresses_, | 705 socket_.reset(factory_->CreateTransportClientSocket(addresses_, |
705 net_log_.net_log(), | 706 net_log_.net_log(), |
706 net_log_.source())); | 707 net_log_.source())); |
707 metrics_->OnStartConnection(); | 708 metrics_->OnStartConnection(); |
708 return socket_->Connect(io_callback_); | 709 return socket_->Connect(io_callback_); |
709 } | 710 } |
710 | 711 |
712 bool SocketStream::ShouldApplyProxyAuth() const { | |
713 // The same logic as HttpNetworkTransaction::ShouldApplyProxyAuth(). | |
714 return !is_secure() && (proxy_info_.is_http() || proxy_info_.is_https()); | |
cbentzel
2012/08/15 18:08:01
This isn't going to work when tunneling WSS connec
bashi
2012/08/20 01:35:10
Yes. the logic was wrong. Thank you for pointing t
| |
715 } | |
716 | |
711 int SocketStream::DoTcpConnectComplete(int result) { | 717 int SocketStream::DoTcpConnectComplete(int result) { |
712 // TODO(ukai): if error occured, reconsider proxy after error. | 718 // TODO(ukai): if error occured, reconsider proxy after error. |
713 if (result != OK) { | 719 if (result != OK) { |
714 next_state_ = STATE_CLOSE; | 720 next_state_ = STATE_CLOSE; |
715 return result; | 721 return result; |
716 } | 722 } |
717 | 723 |
724 if (ShouldApplyProxyAuth()) | |
725 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | |
726 else | |
727 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; | |
728 return result; | |
729 } | |
730 | |
731 int SocketStream::DoGenerateProxyAuthToken() { | |
732 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; | |
733 if (!proxy_auth_controller_.get()) { | |
734 DCHECK(context_); | |
735 DCHECK(context_->http_transaction_factory()); | |
736 DCHECK(context_->http_transaction_factory()->GetSession()); | |
737 HttpNetworkSession* session = | |
738 context_->http_transaction_factory()->GetSession(); | |
739 const char* scheme = proxy_info_.is_https() ? "https://" : "http://"; | |
cbentzel
2012/08/15 18:08:01
Perhaps share with HttpNetworkTransaction::AuthURL
bashi
2012/08/20 01:35:10
I'd like to keep this because:
- SocketStream only
| |
740 GURL auth_url(scheme + | |
741 proxy_info_.proxy_server().host_port_pair().ToString()); | |
742 proxy_auth_controller_ = | |
743 new HttpAuthController(HttpAuth::AUTH_PROXY, | |
744 auth_url, | |
745 session->http_auth_cache(), | |
746 session->http_auth_handler_factory()); | |
747 } | |
748 HttpRequestInfo request_info; | |
749 request_info.method = "GET"; | |
750 request_info.load_flags = 0; | |
751 request_info.priority = MEDIUM; | |
752 request_info.request_id = 0; | |
753 return proxy_auth_controller_->MaybeGenerateAuthToken( | |
754 &request_info, io_callback_, net_log_); | |
755 } | |
756 | |
757 int SocketStream::DoGenerateProxyAuthTokenComplete(int result) { | |
758 if (result != OK) { | |
759 next_state_ = STATE_CLOSE; | |
760 return result; | |
761 } | |
762 | |
718 if (proxy_mode_ == kTunnelProxy) { | 763 if (proxy_mode_ == kTunnelProxy) { |
719 if (proxy_info_.is_https()) | 764 if (proxy_info_.is_https()) |
720 next_state_ = STATE_SECURE_PROXY_CONNECT; | 765 next_state_ = STATE_SECURE_PROXY_CONNECT; |
721 else | 766 else |
722 next_state_ = STATE_WRITE_TUNNEL_HEADERS; | 767 next_state_ = STATE_WRITE_TUNNEL_HEADERS; |
723 } else if (proxy_mode_ == kSOCKSProxy) { | 768 } else if (proxy_mode_ == kSOCKSProxy) { |
724 next_state_ = STATE_SOCKS_CONNECT; | 769 next_state_ = STATE_SOCKS_CONNECT; |
725 } else if (is_secure()) { | 770 } else if (is_secure()) { |
726 next_state_ = STATE_SSL_CONNECT; | 771 next_state_ = STATE_SSL_CONNECT; |
727 } else { | 772 } else { |
728 result = DidEstablishConnection(); | 773 result = DidEstablishConnection(); |
729 } | 774 } |
730 return result; | 775 return result; |
731 } | 776 } |
732 | 777 |
733 int SocketStream::DoWriteTunnelHeaders() { | 778 int SocketStream::DoWriteTunnelHeaders() { |
734 DCHECK_EQ(kTunnelProxy, proxy_mode_); | 779 DCHECK_EQ(kTunnelProxy, proxy_mode_); |
735 | 780 |
736 next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE; | 781 next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE; |
737 | 782 |
738 if (!tunnel_request_headers_.get()) { | 783 if (!tunnel_request_headers_.get()) { |
739 metrics_->OnCountConnectionType(SocketStreamMetrics::TUNNEL_CONNECTION); | 784 metrics_->OnCountConnectionType(SocketStreamMetrics::TUNNEL_CONNECTION); |
740 tunnel_request_headers_ = new RequestHeaders(); | 785 tunnel_request_headers_ = new RequestHeaders(); |
741 tunnel_request_headers_bytes_sent_ = 0; | 786 tunnel_request_headers_bytes_sent_ = 0; |
742 } | 787 } |
743 if (tunnel_request_headers_->headers_.empty()) { | 788 if (tunnel_request_headers_->headers_.empty()) { |
744 std::string authorization_headers; | 789 HttpRequestHeaders request_headers; |
745 | 790 request_headers.SetHeader("Host", GetHostAndOptionalPort(url_)); |
746 if (!auth_handler_.get()) { | 791 request_headers.SetHeader("Proxy-Connection", "keep-alive"); |
747 // Do preemptive authentication. | 792 if (proxy_auth_controller_.get() && proxy_auth_controller_->HaveAuth()) |
748 HttpAuthCache::Entry* entry = auth_cache_.LookupByPath( | 793 proxy_auth_controller_->AddAuthorizationHeader(&request_headers); |
749 ProxyAuthOrigin(), std::string()); | |
750 if (entry) { | |
751 scoped_ptr<HttpAuthHandler> handler_preemptive; | |
752 int rv_create = http_auth_handler_factory_-> | |
753 CreatePreemptiveAuthHandlerFromString( | |
754 entry->auth_challenge(), HttpAuth::AUTH_PROXY, | |
755 ProxyAuthOrigin(), entry->IncrementNonceCount(), | |
756 net_log_, &handler_preemptive); | |
757 if (rv_create == OK) { | |
758 auth_identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP; | |
759 auth_identity_.invalid = false; | |
760 auth_identity_.credentials = AuthCredentials(); | |
761 auth_handler_.swap(handler_preemptive); | |
762 } | |
763 } | |
764 } | |
765 | |
766 // Support basic authentication scheme only, because we don't have | |
767 // HttpRequestInfo. | |
768 // TODO(ukai): Add support other authentication scheme. | |
769 if (auth_handler_.get() && | |
770 auth_handler_->auth_scheme() == HttpAuth::AUTH_SCHEME_BASIC) { | |
771 HttpRequestInfo request_info; | |
772 std::string auth_token; | |
773 int rv = auth_handler_->GenerateAuthToken( | |
774 &auth_identity_.credentials, | |
775 &request_info, | |
776 CompletionCallback(), | |
777 &auth_token); | |
778 // TODO(cbentzel): Support async auth handlers. | |
779 DCHECK_NE(ERR_IO_PENDING, rv); | |
780 if (rv != OK) | |
781 return rv; | |
782 authorization_headers.append( | |
783 HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY) + | |
784 ": " + auth_token + "\r\n"); | |
785 } | |
786 | |
787 tunnel_request_headers_->headers_ = base::StringPrintf( | 794 tunnel_request_headers_->headers_ = base::StringPrintf( |
788 "CONNECT %s HTTP/1.1\r\n" | 795 "CONNECT %s HTTP/1.1\r\n" |
789 "Host: %s\r\n" | 796 "%s", |
790 "Proxy-Connection: keep-alive\r\n", | |
791 GetHostAndPort(url_).c_str(), | 797 GetHostAndPort(url_).c_str(), |
792 GetHostAndOptionalPort(url_).c_str()); | 798 request_headers.ToString().c_str()); |
793 if (!authorization_headers.empty()) | |
794 tunnel_request_headers_->headers_ += authorization_headers; | |
795 tunnel_request_headers_->headers_ += "\r\n"; | |
796 } | 799 } |
797 tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_); | 800 tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_); |
798 int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() - | 801 int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() - |
799 tunnel_request_headers_bytes_sent_); | 802 tunnel_request_headers_bytes_sent_); |
800 DCHECK_GT(buf_len, 0); | 803 DCHECK_GT(buf_len, 0); |
801 return socket_->Write(tunnel_request_headers_, buf_len, io_callback_); | 804 return socket_->Write(tunnel_request_headers_, buf_len, io_callback_); |
802 } | 805 } |
803 | 806 |
804 int SocketStream::DoWriteTunnelHeadersComplete(int result) { | 807 int SocketStream::DoWriteTunnelHeadersComplete(int result) { |
805 DCHECK_EQ(kTunnelProxy, proxy_mode_); | 808 DCHECK_EQ(kTunnelProxy, proxy_mode_); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
892 next_state_ = STATE_CLOSE; | 895 next_state_ = STATE_CLOSE; |
893 return result; | 896 return result; |
894 } | 897 } |
895 if ((eoh < tunnel_response_headers_len_) && delegate_) | 898 if ((eoh < tunnel_response_headers_len_) && delegate_) |
896 delegate_->OnReceivedData( | 899 delegate_->OnReceivedData( |
897 this, tunnel_response_headers_->headers() + eoh, | 900 this, tunnel_response_headers_->headers() + eoh, |
898 tunnel_response_headers_len_ - eoh); | 901 tunnel_response_headers_len_ - eoh); |
899 } | 902 } |
900 return OK; | 903 return OK; |
901 case 407: // Proxy Authentication Required. | 904 case 407: // Proxy Authentication Required. |
902 result = HandleAuthChallenge(headers.get()); | 905 if (!proxy_auth_controller_.get() || proxy_mode_ != kTunnelProxy || |
903 if (result == ERR_PROXY_AUTH_UNSUPPORTED && | 906 proxy_info_.is_direct()) { |
904 auth_handler_.get() && delegate_) { | 907 return ERR_UNEXPECTED_PROXY_AUTH; |
908 } | |
909 result = proxy_auth_controller_->HandleAuthChallenge( | |
910 headers, false, true, net_log_); | |
911 if (result == OK && delegate_) { | |
905 DCHECK(!proxy_info_.is_empty()); | 912 DCHECK(!proxy_info_.is_empty()); |
906 auth_info_ = new AuthChallengeInfo; | |
907 auth_info_->is_proxy = true; | |
908 auth_info_->challenger = proxy_info_.proxy_server().host_port_pair(); | |
909 auth_info_->scheme = HttpAuth::SchemeToString( | |
910 auth_handler_->auth_scheme()); | |
911 auth_info_->realm = auth_handler_->realm(); | |
912 // Wait until RestartWithAuth or Close is called. | 913 // Wait until RestartWithAuth or Close is called. |
913 MessageLoop::current()->PostTask( | 914 MessageLoop::current()->PostTask( |
914 FROM_HERE, | 915 FROM_HERE, |
915 base::Bind(&SocketStream::DoAuthRequired, this)); | 916 base::Bind(&SocketStream::DoAuthRequired, this)); |
916 next_state_ = STATE_AUTH_REQUIRED; | 917 next_state_ = STATE_AUTH_REQUIRED; |
917 return ERR_IO_PENDING; | 918 return ERR_IO_PENDING; |
918 } | 919 } |
920 break; | |
919 default: | 921 default: |
920 break; | 922 break; |
921 } | 923 } |
922 next_state_ = STATE_CLOSE; | 924 next_state_ = STATE_CLOSE; |
923 return ERR_TUNNEL_CONNECTION_FAILED; | 925 return ERR_TUNNEL_CONNECTION_FAILED; |
924 } | 926 } |
925 | 927 |
926 int SocketStream::DoSOCKSConnect() { | 928 int SocketStream::DoSOCKSConnect() { |
927 DCHECK_EQ(kSOCKSProxy, proxy_mode_); | 929 DCHECK_EQ(kSOCKSProxy, proxy_mode_); |
928 | 930 |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1137 // We arrived here when both operation is pending. | 1139 // We arrived here when both operation is pending. |
1138 return ERR_IO_PENDING; | 1140 return ERR_IO_PENDING; |
1139 } | 1141 } |
1140 | 1142 |
1141 GURL SocketStream::ProxyAuthOrigin() const { | 1143 GURL SocketStream::ProxyAuthOrigin() const { |
1142 DCHECK(!proxy_info_.is_empty()); | 1144 DCHECK(!proxy_info_.is_empty()); |
1143 return GURL("http://" + | 1145 return GURL("http://" + |
1144 proxy_info_.proxy_server().host_port_pair().ToString()); | 1146 proxy_info_.proxy_server().host_port_pair().ToString()); |
1145 } | 1147 } |
1146 | 1148 |
1147 int SocketStream::HandleAuthChallenge(const HttpResponseHeaders* headers) { | |
1148 GURL auth_origin(ProxyAuthOrigin()); | |
1149 | |
1150 VLOG(1) << "The proxy " << auth_origin << " requested auth"; | |
1151 | |
1152 // TODO(cbentzel): Since SocketStream only suppports basic authentication | |
1153 // right now, another challenge is always treated as a rejection. | |
1154 // Ultimately this should be converted to use HttpAuthController like the | |
1155 // HttpNetworkTransaction has. | |
1156 if (auth_handler_.get() && !auth_identity_.invalid) { | |
1157 if (auth_identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP) | |
1158 auth_cache_.Remove(auth_origin, | |
1159 auth_handler_->realm(), | |
1160 auth_handler_->auth_scheme(), | |
1161 auth_identity_.credentials); | |
1162 auth_handler_.reset(); | |
1163 auth_identity_ = HttpAuth::Identity(); | |
1164 } | |
1165 | |
1166 auth_identity_.invalid = true; | |
1167 std::set<HttpAuth::Scheme> disabled_schemes; | |
1168 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, headers, | |
1169 HttpAuth::AUTH_PROXY, | |
1170 auth_origin, disabled_schemes, | |
1171 net_log_, &auth_handler_); | |
1172 if (!auth_handler_.get()) { | |
1173 LOG(ERROR) << "Can't perform auth to the proxy " << auth_origin; | |
1174 return ERR_TUNNEL_CONNECTION_FAILED; | |
1175 } | |
1176 if (auth_handler_->NeedsIdentity()) { | |
1177 // We only support basic authentication scheme now. | |
1178 // TODO(ukai): Support other authentication scheme. | |
1179 HttpAuthCache::Entry* entry = auth_cache_.Lookup( | |
1180 auth_origin, auth_handler_->realm(), HttpAuth::AUTH_SCHEME_BASIC); | |
1181 if (entry) { | |
1182 auth_identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP; | |
1183 auth_identity_.invalid = false; | |
1184 auth_identity_.credentials = AuthCredentials(); | |
1185 // Restart with auth info. | |
1186 } | |
1187 return ERR_PROXY_AUTH_UNSUPPORTED; | |
1188 } else { | |
1189 auth_identity_.invalid = false; | |
1190 } | |
1191 return ERR_TUNNEL_CONNECTION_FAILED; | |
1192 } | |
1193 | |
1194 int SocketStream::HandleCertificateRequest(int result, SSLConfig* ssl_config) { | 1149 int SocketStream::HandleCertificateRequest(int result, SSLConfig* ssl_config) { |
1195 if (ssl_config->send_client_cert) | 1150 if (ssl_config->send_client_cert) |
1196 // We already have performed SSL client authentication once and failed. | 1151 // We already have performed SSL client authentication once and failed. |
1197 return result; | 1152 return result; |
1198 | 1153 |
1199 DCHECK(socket_.get()); | 1154 DCHECK(socket_.get()); |
1200 scoped_refptr<SSLCertRequestInfo> cert_request_info = new SSLCertRequestInfo; | 1155 scoped_refptr<SSLCertRequestInfo> cert_request_info = new SSLCertRequestInfo; |
1201 SSLClientSocket* ssl_socket = | 1156 SSLClientSocket* ssl_socket = |
1202 static_cast<SSLClientSocket*>(socket_.get()); | 1157 static_cast<SSLClientSocket*>(socket_.get()); |
1203 ssl_socket->GetSSLCertRequestInfo(cert_request_info); | 1158 ssl_socket->GetSSLCertRequestInfo(cert_request_info); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1264 bad_cert.cert_status = ssl_info.cert_status; | 1219 bad_cert.cert_status = ssl_info.cert_status; |
1265 ssl_config->allowed_bad_certs.push_back(bad_cert); | 1220 ssl_config->allowed_bad_certs.push_back(bad_cert); |
1266 // Restart connection ignoring the bad certificate. | 1221 // Restart connection ignoring the bad certificate. |
1267 socket_->Disconnect(); | 1222 socket_->Disconnect(); |
1268 socket_.reset(); | 1223 socket_.reset(); |
1269 next_state_ = STATE_TCP_CONNECT; | 1224 next_state_ = STATE_TCP_CONNECT; |
1270 return OK; | 1225 return OK; |
1271 } | 1226 } |
1272 | 1227 |
1273 void SocketStream::DoAuthRequired() { | 1228 void SocketStream::DoAuthRequired() { |
1274 if (delegate_ && auth_info_.get()) | 1229 if (delegate_ && proxy_auth_controller_.get()) |
1275 delegate_->OnAuthRequired(this, auth_info_.get()); | 1230 delegate_->OnAuthRequired(this, proxy_auth_controller_->auth_info().get()); |
1276 else | 1231 else |
1277 DoLoop(ERR_UNEXPECTED); | 1232 DoLoop(ERR_UNEXPECTED); |
1278 } | 1233 } |
1279 | 1234 |
1280 void SocketStream::DoRestartWithAuth() { | 1235 void SocketStream::DoRestartWithAuth() { |
1281 DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED); | 1236 DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED); |
1282 auth_cache_.Add(ProxyAuthOrigin(), | |
1283 auth_handler_->realm(), | |
1284 auth_handler_->auth_scheme(), | |
1285 auth_handler_->challenge(), | |
1286 auth_identity_.credentials, | |
1287 std::string()); | |
1288 | |
1289 tunnel_request_headers_ = NULL; | 1237 tunnel_request_headers_ = NULL; |
1290 tunnel_request_headers_bytes_sent_ = 0; | 1238 tunnel_request_headers_bytes_sent_ = 0; |
1291 tunnel_response_headers_ = NULL; | 1239 tunnel_response_headers_ = NULL; |
1292 tunnel_response_headers_capacity_ = 0; | 1240 tunnel_response_headers_capacity_ = 0; |
1293 tunnel_response_headers_len_ = 0; | 1241 tunnel_response_headers_len_ = 0; |
1294 | 1242 |
1295 next_state_ = STATE_TCP_CONNECT; | 1243 next_state_ = STATE_TCP_CONNECT; |
1296 DoLoop(OK); | 1244 DoLoop(OK); |
1297 } | 1245 } |
1298 | 1246 |
(...skipping 27 matching lines...) Expand all Loading... | |
1326 | 1274 |
1327 SSLConfigService* SocketStream::ssl_config_service() const { | 1275 SSLConfigService* SocketStream::ssl_config_service() const { |
1328 return context_->ssl_config_service(); | 1276 return context_->ssl_config_service(); |
1329 } | 1277 } |
1330 | 1278 |
1331 ProxyService* SocketStream::proxy_service() const { | 1279 ProxyService* SocketStream::proxy_service() const { |
1332 return context_->proxy_service(); | 1280 return context_->proxy_service(); |
1333 } | 1281 } |
1334 | 1282 |
1335 } // namespace net | 1283 } // namespace net |
OLD | NEW |