1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/socket/socks_connect_job.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
11*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_source_type.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_with_source.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/socket/client_socket_factory.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/socket/client_socket_handle.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/socket/connect_job_params.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/socket/socks5_client_socket.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/socket/socks_client_socket.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/socket/transport_connect_job.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace net {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker // SOCKSConnectJobs will time out if the SOCKS handshake takes longer than this.
24*6777b538SAndroid Build Coastguard Worker static constexpr base::TimeDelta kSOCKSConnectJobTimeout = base::Seconds(30);
25*6777b538SAndroid Build Coastguard Worker
SOCKSSocketParams(ConnectJobParams nested_params,bool socks_v5,const HostPortPair & host_port_pair,const NetworkAnonymizationKey & network_anonymization_key,const NetworkTrafficAnnotationTag & traffic_annotation)26*6777b538SAndroid Build Coastguard Worker SOCKSSocketParams::SOCKSSocketParams(
27*6777b538SAndroid Build Coastguard Worker ConnectJobParams nested_params,
28*6777b538SAndroid Build Coastguard Worker bool socks_v5,
29*6777b538SAndroid Build Coastguard Worker const HostPortPair& host_port_pair,
30*6777b538SAndroid Build Coastguard Worker const NetworkAnonymizationKey& network_anonymization_key,
31*6777b538SAndroid Build Coastguard Worker const NetworkTrafficAnnotationTag& traffic_annotation)
32*6777b538SAndroid Build Coastguard Worker : transport_params_(nested_params.take_transport()),
33*6777b538SAndroid Build Coastguard Worker destination_(host_port_pair),
34*6777b538SAndroid Build Coastguard Worker socks_v5_(socks_v5),
35*6777b538SAndroid Build Coastguard Worker network_anonymization_key_(network_anonymization_key),
36*6777b538SAndroid Build Coastguard Worker traffic_annotation_(traffic_annotation) {}
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker SOCKSSocketParams::~SOCKSSocketParams() = default;
39*6777b538SAndroid Build Coastguard Worker
Create(RequestPriority priority,const SocketTag & socket_tag,const CommonConnectJobParams * common_connect_job_params,scoped_refptr<SOCKSSocketParams> socks_params,ConnectJob::Delegate * delegate,const NetLogWithSource * net_log)40*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SOCKSConnectJob> SOCKSConnectJob::Factory::Create(
41*6777b538SAndroid Build Coastguard Worker RequestPriority priority,
42*6777b538SAndroid Build Coastguard Worker const SocketTag& socket_tag,
43*6777b538SAndroid Build Coastguard Worker const CommonConnectJobParams* common_connect_job_params,
44*6777b538SAndroid Build Coastguard Worker scoped_refptr<SOCKSSocketParams> socks_params,
45*6777b538SAndroid Build Coastguard Worker ConnectJob::Delegate* delegate,
46*6777b538SAndroid Build Coastguard Worker const NetLogWithSource* net_log) {
47*6777b538SAndroid Build Coastguard Worker return std::make_unique<SOCKSConnectJob>(
48*6777b538SAndroid Build Coastguard Worker priority, socket_tag, common_connect_job_params, std::move(socks_params),
49*6777b538SAndroid Build Coastguard Worker delegate, net_log);
50*6777b538SAndroid Build Coastguard Worker }
51*6777b538SAndroid Build Coastguard Worker
SOCKSConnectJob(RequestPriority priority,const SocketTag & socket_tag,const CommonConnectJobParams * common_connect_job_params,scoped_refptr<SOCKSSocketParams> socks_params,ConnectJob::Delegate * delegate,const NetLogWithSource * net_log)52*6777b538SAndroid Build Coastguard Worker SOCKSConnectJob::SOCKSConnectJob(
53*6777b538SAndroid Build Coastguard Worker RequestPriority priority,
54*6777b538SAndroid Build Coastguard Worker const SocketTag& socket_tag,
55*6777b538SAndroid Build Coastguard Worker const CommonConnectJobParams* common_connect_job_params,
56*6777b538SAndroid Build Coastguard Worker scoped_refptr<SOCKSSocketParams> socks_params,
57*6777b538SAndroid Build Coastguard Worker ConnectJob::Delegate* delegate,
58*6777b538SAndroid Build Coastguard Worker const NetLogWithSource* net_log)
59*6777b538SAndroid Build Coastguard Worker : ConnectJob(priority,
60*6777b538SAndroid Build Coastguard Worker socket_tag,
61*6777b538SAndroid Build Coastguard Worker base::TimeDelta(),
62*6777b538SAndroid Build Coastguard Worker common_connect_job_params,
63*6777b538SAndroid Build Coastguard Worker delegate,
64*6777b538SAndroid Build Coastguard Worker net_log,
65*6777b538SAndroid Build Coastguard Worker NetLogSourceType::SOCKS_CONNECT_JOB,
66*6777b538SAndroid Build Coastguard Worker NetLogEventType::SOCKS_CONNECT_JOB_CONNECT),
67*6777b538SAndroid Build Coastguard Worker socks_params_(std::move(socks_params)) {}
68*6777b538SAndroid Build Coastguard Worker
~SOCKSConnectJob()69*6777b538SAndroid Build Coastguard Worker SOCKSConnectJob::~SOCKSConnectJob() {
70*6777b538SAndroid Build Coastguard Worker // In the case the job was canceled, need to delete nested job first to
71*6777b538SAndroid Build Coastguard Worker // correctly order NetLog events.
72*6777b538SAndroid Build Coastguard Worker transport_connect_job_.reset();
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker
GetLoadState() const75*6777b538SAndroid Build Coastguard Worker LoadState SOCKSConnectJob::GetLoadState() const {
76*6777b538SAndroid Build Coastguard Worker switch (next_state_) {
77*6777b538SAndroid Build Coastguard Worker case STATE_TRANSPORT_CONNECT:
78*6777b538SAndroid Build Coastguard Worker return LOAD_STATE_IDLE;
79*6777b538SAndroid Build Coastguard Worker case STATE_TRANSPORT_CONNECT_COMPLETE:
80*6777b538SAndroid Build Coastguard Worker return transport_connect_job_->GetLoadState();
81*6777b538SAndroid Build Coastguard Worker case STATE_SOCKS_CONNECT:
82*6777b538SAndroid Build Coastguard Worker case STATE_SOCKS_CONNECT_COMPLETE:
83*6777b538SAndroid Build Coastguard Worker return LOAD_STATE_CONNECTING;
84*6777b538SAndroid Build Coastguard Worker default:
85*6777b538SAndroid Build Coastguard Worker NOTREACHED();
86*6777b538SAndroid Build Coastguard Worker return LOAD_STATE_IDLE;
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker
HasEstablishedConnection() const90*6777b538SAndroid Build Coastguard Worker bool SOCKSConnectJob::HasEstablishedConnection() const {
91*6777b538SAndroid Build Coastguard Worker return next_state_ == STATE_SOCKS_CONNECT ||
92*6777b538SAndroid Build Coastguard Worker next_state_ == STATE_SOCKS_CONNECT_COMPLETE;
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker
GetResolveErrorInfo() const95*6777b538SAndroid Build Coastguard Worker ResolveErrorInfo SOCKSConnectJob::GetResolveErrorInfo() const {
96*6777b538SAndroid Build Coastguard Worker return resolve_error_info_;
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker
HandshakeTimeoutForTesting()99*6777b538SAndroid Build Coastguard Worker base::TimeDelta SOCKSConnectJob::HandshakeTimeoutForTesting() {
100*6777b538SAndroid Build Coastguard Worker return kSOCKSConnectJobTimeout;
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker
OnIOComplete(int result)103*6777b538SAndroid Build Coastguard Worker void SOCKSConnectJob::OnIOComplete(int result) {
104*6777b538SAndroid Build Coastguard Worker int rv = DoLoop(result);
105*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING)
106*6777b538SAndroid Build Coastguard Worker NotifyDelegateOfCompletion(rv); // Deletes |this|
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker
OnConnectJobComplete(int result,ConnectJob * job)109*6777b538SAndroid Build Coastguard Worker void SOCKSConnectJob::OnConnectJobComplete(int result, ConnectJob* job) {
110*6777b538SAndroid Build Coastguard Worker DCHECK(transport_connect_job_);
111*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(next_state_, STATE_TRANSPORT_CONNECT_COMPLETE);
112*6777b538SAndroid Build Coastguard Worker OnIOComplete(result);
113*6777b538SAndroid Build Coastguard Worker }
114*6777b538SAndroid Build Coastguard Worker
OnNeedsProxyAuth(const HttpResponseInfo & response,HttpAuthController * auth_controller,base::OnceClosure restart_with_auth_callback,ConnectJob * job)115*6777b538SAndroid Build Coastguard Worker void SOCKSConnectJob::OnNeedsProxyAuth(
116*6777b538SAndroid Build Coastguard Worker const HttpResponseInfo& response,
117*6777b538SAndroid Build Coastguard Worker HttpAuthController* auth_controller,
118*6777b538SAndroid Build Coastguard Worker base::OnceClosure restart_with_auth_callback,
119*6777b538SAndroid Build Coastguard Worker ConnectJob* job) {
120*6777b538SAndroid Build Coastguard Worker // A SOCKSConnectJob can't be on top of an HttpProxyConnectJob.
121*6777b538SAndroid Build Coastguard Worker NOTREACHED();
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker
DoLoop(int result)124*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoLoop(int result) {
125*6777b538SAndroid Build Coastguard Worker DCHECK_NE(next_state_, STATE_NONE);
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Worker int rv = result;
128*6777b538SAndroid Build Coastguard Worker do {
129*6777b538SAndroid Build Coastguard Worker State state = next_state_;
130*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NONE;
131*6777b538SAndroid Build Coastguard Worker switch (state) {
132*6777b538SAndroid Build Coastguard Worker case STATE_TRANSPORT_CONNECT:
133*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
134*6777b538SAndroid Build Coastguard Worker rv = DoTransportConnect();
135*6777b538SAndroid Build Coastguard Worker break;
136*6777b538SAndroid Build Coastguard Worker case STATE_TRANSPORT_CONNECT_COMPLETE:
137*6777b538SAndroid Build Coastguard Worker rv = DoTransportConnectComplete(rv);
138*6777b538SAndroid Build Coastguard Worker break;
139*6777b538SAndroid Build Coastguard Worker case STATE_SOCKS_CONNECT:
140*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
141*6777b538SAndroid Build Coastguard Worker rv = DoSOCKSConnect();
142*6777b538SAndroid Build Coastguard Worker break;
143*6777b538SAndroid Build Coastguard Worker case STATE_SOCKS_CONNECT_COMPLETE:
144*6777b538SAndroid Build Coastguard Worker rv = DoSOCKSConnectComplete(rv);
145*6777b538SAndroid Build Coastguard Worker break;
146*6777b538SAndroid Build Coastguard Worker default:
147*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "bad state";
148*6777b538SAndroid Build Coastguard Worker rv = ERR_FAILED;
149*6777b538SAndroid Build Coastguard Worker break;
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker return rv;
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
DoTransportConnect()156*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoTransportConnect() {
157*6777b538SAndroid Build Coastguard Worker DCHECK(!transport_connect_job_);
158*6777b538SAndroid Build Coastguard Worker
159*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
160*6777b538SAndroid Build Coastguard Worker transport_connect_job_ = std::make_unique<TransportConnectJob>(
161*6777b538SAndroid Build Coastguard Worker priority(), socket_tag(), common_connect_job_params(),
162*6777b538SAndroid Build Coastguard Worker socks_params_->transport_params(), this, &net_log());
163*6777b538SAndroid Build Coastguard Worker return transport_connect_job_->Connect();
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker
DoTransportConnectComplete(int result)166*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoTransportConnectComplete(int result) {
167*6777b538SAndroid Build Coastguard Worker resolve_error_info_ = transport_connect_job_->GetResolveErrorInfo();
168*6777b538SAndroid Build Coastguard Worker if (result != OK)
169*6777b538SAndroid Build Coastguard Worker return ERR_PROXY_CONNECTION_FAILED;
170*6777b538SAndroid Build Coastguard Worker
171*6777b538SAndroid Build Coastguard Worker // Start the timer to time allowed for SOCKS handshake.
172*6777b538SAndroid Build Coastguard Worker ResetTimer(kSOCKSConnectJobTimeout);
173*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_SOCKS_CONNECT;
174*6777b538SAndroid Build Coastguard Worker return result;
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker
DoSOCKSConnect()177*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoSOCKSConnect() {
178*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
179*6777b538SAndroid Build Coastguard Worker
180*6777b538SAndroid Build Coastguard Worker // Add a SOCKS connection on top of the tcp socket.
181*6777b538SAndroid Build Coastguard Worker if (socks_params_->is_socks_v5()) {
182*6777b538SAndroid Build Coastguard Worker socket_ = std::make_unique<SOCKS5ClientSocket>(
183*6777b538SAndroid Build Coastguard Worker transport_connect_job_->PassSocket(), socks_params_->destination(),
184*6777b538SAndroid Build Coastguard Worker socks_params_->traffic_annotation());
185*6777b538SAndroid Build Coastguard Worker } else {
186*6777b538SAndroid Build Coastguard Worker auto socks_socket = std::make_unique<SOCKSClientSocket>(
187*6777b538SAndroid Build Coastguard Worker transport_connect_job_->PassSocket(), socks_params_->destination(),
188*6777b538SAndroid Build Coastguard Worker socks_params_->network_anonymization_key(), priority(), host_resolver(),
189*6777b538SAndroid Build Coastguard Worker socks_params_->transport_params()->secure_dns_policy(),
190*6777b538SAndroid Build Coastguard Worker socks_params_->traffic_annotation());
191*6777b538SAndroid Build Coastguard Worker socks_socket_ptr_ = socks_socket.get();
192*6777b538SAndroid Build Coastguard Worker socket_ = std::move(socks_socket);
193*6777b538SAndroid Build Coastguard Worker }
194*6777b538SAndroid Build Coastguard Worker transport_connect_job_.reset();
195*6777b538SAndroid Build Coastguard Worker return socket_->Connect(
196*6777b538SAndroid Build Coastguard Worker base::BindOnce(&SOCKSConnectJob::OnIOComplete, base::Unretained(this)));
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker
DoSOCKSConnectComplete(int result)199*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoSOCKSConnectComplete(int result) {
200*6777b538SAndroid Build Coastguard Worker if (!socks_params_->is_socks_v5())
201*6777b538SAndroid Build Coastguard Worker resolve_error_info_ = socks_socket_ptr_->GetResolveErrorInfo();
202*6777b538SAndroid Build Coastguard Worker if (result != OK) {
203*6777b538SAndroid Build Coastguard Worker socket_->Disconnect();
204*6777b538SAndroid Build Coastguard Worker return result;
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker
207*6777b538SAndroid Build Coastguard Worker SetSocket(std::move(socket_), std::nullopt /* dns_aliases */);
208*6777b538SAndroid Build Coastguard Worker return result;
209*6777b538SAndroid Build Coastguard Worker }
210*6777b538SAndroid Build Coastguard Worker
ConnectInternal()211*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::ConnectInternal() {
212*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_TRANSPORT_CONNECT;
213*6777b538SAndroid Build Coastguard Worker return DoLoop(OK);
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker
ChangePriorityInternal(RequestPriority priority)216*6777b538SAndroid Build Coastguard Worker void SOCKSConnectJob::ChangePriorityInternal(RequestPriority priority) {
217*6777b538SAndroid Build Coastguard Worker // Currently doesn't change host resolution request priority for SOCKS4 case.
218*6777b538SAndroid Build Coastguard Worker if (transport_connect_job_)
219*6777b538SAndroid Build Coastguard Worker transport_connect_job_->ChangePriority(priority);
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker } // namespace net
223