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_client_socket.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <utility>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/sys_byteorder.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/base/address_list.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_query_type.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/secure_dns_policy.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_event_type.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/traffic_annotation/network_traffic_annotation.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace net {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker // Every SOCKS server requests a user-id from the client. It is optional
24*6777b538SAndroid Build Coastguard Worker // and we send an empty string.
25*6777b538SAndroid Build Coastguard Worker static const char kEmptyUserId[] = "";
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker // For SOCKS4, the client sends 8 bytes plus the size of the user-id.
28*6777b538SAndroid Build Coastguard Worker static const unsigned int kWriteHeaderSize = 8;
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker // For SOCKS4 the server sends 8 bytes for acknowledgement.
31*6777b538SAndroid Build Coastguard Worker static const unsigned int kReadHeaderSize = 8;
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker // Server Response codes for SOCKS.
34*6777b538SAndroid Build Coastguard Worker static const uint8_t kServerResponseOk = 0x5A;
35*6777b538SAndroid Build Coastguard Worker static const uint8_t kServerResponseRejected = 0x5B;
36*6777b538SAndroid Build Coastguard Worker static const uint8_t kServerResponseNotReachable = 0x5C;
37*6777b538SAndroid Build Coastguard Worker static const uint8_t kServerResponseMismatchedUserId = 0x5D;
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker static const uint8_t kSOCKSVersion4 = 0x04;
40*6777b538SAndroid Build Coastguard Worker static const uint8_t kSOCKSStreamRequest = 0x01;
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker // A struct holding the essential details of the SOCKS4 Server Request.
43*6777b538SAndroid Build Coastguard Worker // The port in the header is stored in network byte order.
44*6777b538SAndroid Build Coastguard Worker struct SOCKS4ServerRequest {
45*6777b538SAndroid Build Coastguard Worker uint8_t version;
46*6777b538SAndroid Build Coastguard Worker uint8_t command;
47*6777b538SAndroid Build Coastguard Worker uint16_t nw_port;
48*6777b538SAndroid Build Coastguard Worker uint8_t ip[4];
49*6777b538SAndroid Build Coastguard Worker };
50*6777b538SAndroid Build Coastguard Worker static_assert(sizeof(SOCKS4ServerRequest) == kWriteHeaderSize,
51*6777b538SAndroid Build Coastguard Worker "socks4 server request struct has incorrect size");
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker // A struct holding details of the SOCKS4 Server Response.
54*6777b538SAndroid Build Coastguard Worker struct SOCKS4ServerResponse {
55*6777b538SAndroid Build Coastguard Worker uint8_t reserved_null;
56*6777b538SAndroid Build Coastguard Worker uint8_t code;
57*6777b538SAndroid Build Coastguard Worker uint16_t port;
58*6777b538SAndroid Build Coastguard Worker uint8_t ip[4];
59*6777b538SAndroid Build Coastguard Worker };
60*6777b538SAndroid Build Coastguard Worker static_assert(sizeof(SOCKS4ServerResponse) == kReadHeaderSize,
61*6777b538SAndroid Build Coastguard Worker "socks4 server response struct has incorrect size");
62*6777b538SAndroid Build Coastguard Worker
SOCKSClientSocket(std::unique_ptr<StreamSocket> transport_socket,const HostPortPair & destination,const NetworkAnonymizationKey & network_anonymization_key,RequestPriority priority,HostResolver * host_resolver,SecureDnsPolicy secure_dns_policy,const NetworkTrafficAnnotationTag & traffic_annotation)63*6777b538SAndroid Build Coastguard Worker SOCKSClientSocket::SOCKSClientSocket(
64*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StreamSocket> transport_socket,
65*6777b538SAndroid Build Coastguard Worker const HostPortPair& destination,
66*6777b538SAndroid Build Coastguard Worker const NetworkAnonymizationKey& network_anonymization_key,
67*6777b538SAndroid Build Coastguard Worker RequestPriority priority,
68*6777b538SAndroid Build Coastguard Worker HostResolver* host_resolver,
69*6777b538SAndroid Build Coastguard Worker SecureDnsPolicy secure_dns_policy,
70*6777b538SAndroid Build Coastguard Worker const NetworkTrafficAnnotationTag& traffic_annotation)
71*6777b538SAndroid Build Coastguard Worker : transport_socket_(std::move(transport_socket)),
72*6777b538SAndroid Build Coastguard Worker host_resolver_(host_resolver),
73*6777b538SAndroid Build Coastguard Worker secure_dns_policy_(secure_dns_policy),
74*6777b538SAndroid Build Coastguard Worker destination_(destination),
75*6777b538SAndroid Build Coastguard Worker network_anonymization_key_(network_anonymization_key),
76*6777b538SAndroid Build Coastguard Worker priority_(priority),
77*6777b538SAndroid Build Coastguard Worker net_log_(transport_socket_->NetLog()),
78*6777b538SAndroid Build Coastguard Worker traffic_annotation_(traffic_annotation) {}
79*6777b538SAndroid Build Coastguard Worker
~SOCKSClientSocket()80*6777b538SAndroid Build Coastguard Worker SOCKSClientSocket::~SOCKSClientSocket() {
81*6777b538SAndroid Build Coastguard Worker Disconnect();
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
Connect(CompletionOnceCallback callback)84*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::Connect(CompletionOnceCallback callback) {
85*6777b538SAndroid Build Coastguard Worker DCHECK(transport_socket_);
86*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
87*6777b538SAndroid Build Coastguard Worker DCHECK(user_callback_.is_null());
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker // If already connected, then just return OK.
90*6777b538SAndroid Build Coastguard Worker if (completed_handshake_)
91*6777b538SAndroid Build Coastguard Worker return OK;
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_RESOLVE_HOST;
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::SOCKS_CONNECT);
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker int rv = DoLoop(OK);
98*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
99*6777b538SAndroid Build Coastguard Worker user_callback_ = std::move(callback);
100*6777b538SAndroid Build Coastguard Worker } else {
101*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS_CONNECT, rv);
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker return rv;
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker
Disconnect()106*6777b538SAndroid Build Coastguard Worker void SOCKSClientSocket::Disconnect() {
107*6777b538SAndroid Build Coastguard Worker completed_handshake_ = false;
108*6777b538SAndroid Build Coastguard Worker resolve_host_request_.reset();
109*6777b538SAndroid Build Coastguard Worker transport_socket_->Disconnect();
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker // Reset other states to make sure they aren't mistakenly used later.
112*6777b538SAndroid Build Coastguard Worker // These are the states initialized by Connect().
113*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NONE;
114*6777b538SAndroid Build Coastguard Worker user_callback_.Reset();
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker
IsConnected() const117*6777b538SAndroid Build Coastguard Worker bool SOCKSClientSocket::IsConnected() const {
118*6777b538SAndroid Build Coastguard Worker return completed_handshake_ && transport_socket_->IsConnected();
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker
IsConnectedAndIdle() const121*6777b538SAndroid Build Coastguard Worker bool SOCKSClientSocket::IsConnectedAndIdle() const {
122*6777b538SAndroid Build Coastguard Worker return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker
NetLog() const125*6777b538SAndroid Build Coastguard Worker const NetLogWithSource& SOCKSClientSocket::NetLog() const {
126*6777b538SAndroid Build Coastguard Worker return net_log_;
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker
WasEverUsed() const129*6777b538SAndroid Build Coastguard Worker bool SOCKSClientSocket::WasEverUsed() const {
130*6777b538SAndroid Build Coastguard Worker return was_ever_used_;
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker
GetNegotiatedProtocol() const133*6777b538SAndroid Build Coastguard Worker NextProto SOCKSClientSocket::GetNegotiatedProtocol() const {
134*6777b538SAndroid Build Coastguard Worker if (transport_socket_)
135*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetNegotiatedProtocol();
136*6777b538SAndroid Build Coastguard Worker NOTREACHED();
137*6777b538SAndroid Build Coastguard Worker return kProtoUnknown;
138*6777b538SAndroid Build Coastguard Worker }
139*6777b538SAndroid Build Coastguard Worker
GetSSLInfo(SSLInfo * ssl_info)140*6777b538SAndroid Build Coastguard Worker bool SOCKSClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
141*6777b538SAndroid Build Coastguard Worker if (transport_socket_)
142*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetSSLInfo(ssl_info);
143*6777b538SAndroid Build Coastguard Worker NOTREACHED();
144*6777b538SAndroid Build Coastguard Worker return false;
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker
GetTotalReceivedBytes() const147*6777b538SAndroid Build Coastguard Worker int64_t SOCKSClientSocket::GetTotalReceivedBytes() const {
148*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetTotalReceivedBytes();
149*6777b538SAndroid Build Coastguard Worker }
150*6777b538SAndroid Build Coastguard Worker
ApplySocketTag(const SocketTag & tag)151*6777b538SAndroid Build Coastguard Worker void SOCKSClientSocket::ApplySocketTag(const SocketTag& tag) {
152*6777b538SAndroid Build Coastguard Worker return transport_socket_->ApplySocketTag(tag);
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker // Read is called by the transport layer above to read. This can only be done
156*6777b538SAndroid Build Coastguard Worker // if the SOCKS handshake is complete.
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)157*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::Read(IOBuffer* buf,
158*6777b538SAndroid Build Coastguard Worker int buf_len,
159*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
160*6777b538SAndroid Build Coastguard Worker DCHECK(completed_handshake_);
161*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
162*6777b538SAndroid Build Coastguard Worker DCHECK(user_callback_.is_null());
163*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Worker int rv = transport_socket_->Read(
166*6777b538SAndroid Build Coastguard Worker buf, buf_len,
167*6777b538SAndroid Build Coastguard Worker base::BindOnce(&SOCKSClientSocket::OnReadWriteComplete,
168*6777b538SAndroid Build Coastguard Worker base::Unretained(this), std::move(callback)));
169*6777b538SAndroid Build Coastguard Worker if (rv > 0)
170*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
171*6777b538SAndroid Build Coastguard Worker return rv;
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker
ReadIfReady(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)174*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::ReadIfReady(IOBuffer* buf,
175*6777b538SAndroid Build Coastguard Worker int buf_len,
176*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
177*6777b538SAndroid Build Coastguard Worker DCHECK(completed_handshake_);
178*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
179*6777b538SAndroid Build Coastguard Worker DCHECK(user_callback_.is_null());
180*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
181*6777b538SAndroid Build Coastguard Worker
182*6777b538SAndroid Build Coastguard Worker // Pass |callback| directly instead of wrapping it with OnReadWriteComplete.
183*6777b538SAndroid Build Coastguard Worker // This is to avoid setting |was_ever_used_| unless data is actually read.
184*6777b538SAndroid Build Coastguard Worker int rv = transport_socket_->ReadIfReady(buf, buf_len, std::move(callback));
185*6777b538SAndroid Build Coastguard Worker if (rv > 0)
186*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
187*6777b538SAndroid Build Coastguard Worker return rv;
188*6777b538SAndroid Build Coastguard Worker }
189*6777b538SAndroid Build Coastguard Worker
CancelReadIfReady()190*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::CancelReadIfReady() {
191*6777b538SAndroid Build Coastguard Worker return transport_socket_->CancelReadIfReady();
192*6777b538SAndroid Build Coastguard Worker }
193*6777b538SAndroid Build Coastguard Worker
194*6777b538SAndroid Build Coastguard Worker // Write is called by the transport layer. This can only be done if the
195*6777b538SAndroid Build Coastguard Worker // SOCKS handshake is complete.
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)196*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::Write(
197*6777b538SAndroid Build Coastguard Worker IOBuffer* buf,
198*6777b538SAndroid Build Coastguard Worker int buf_len,
199*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback,
200*6777b538SAndroid Build Coastguard Worker const NetworkTrafficAnnotationTag& traffic_annotation) {
201*6777b538SAndroid Build Coastguard Worker DCHECK(completed_handshake_);
202*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
203*6777b538SAndroid Build Coastguard Worker DCHECK(user_callback_.is_null());
204*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
205*6777b538SAndroid Build Coastguard Worker
206*6777b538SAndroid Build Coastguard Worker int rv = transport_socket_->Write(
207*6777b538SAndroid Build Coastguard Worker buf, buf_len,
208*6777b538SAndroid Build Coastguard Worker base::BindOnce(&SOCKSClientSocket::OnReadWriteComplete,
209*6777b538SAndroid Build Coastguard Worker base::Unretained(this), std::move(callback)),
210*6777b538SAndroid Build Coastguard Worker traffic_annotation);
211*6777b538SAndroid Build Coastguard Worker if (rv > 0)
212*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
213*6777b538SAndroid Build Coastguard Worker return rv;
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker
SetReceiveBufferSize(int32_t size)216*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::SetReceiveBufferSize(int32_t size) {
217*6777b538SAndroid Build Coastguard Worker return transport_socket_->SetReceiveBufferSize(size);
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker
SetSendBufferSize(int32_t size)220*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::SetSendBufferSize(int32_t size) {
221*6777b538SAndroid Build Coastguard Worker return transport_socket_->SetSendBufferSize(size);
222*6777b538SAndroid Build Coastguard Worker }
223*6777b538SAndroid Build Coastguard Worker
DoCallback(int result)224*6777b538SAndroid Build Coastguard Worker void SOCKSClientSocket::DoCallback(int result) {
225*6777b538SAndroid Build Coastguard Worker DCHECK_NE(ERR_IO_PENDING, result);
226*6777b538SAndroid Build Coastguard Worker DCHECK(!user_callback_.is_null());
227*6777b538SAndroid Build Coastguard Worker
228*6777b538SAndroid Build Coastguard Worker // Since Run() may result in Read being called,
229*6777b538SAndroid Build Coastguard Worker // clear user_callback_ up front.
230*6777b538SAndroid Build Coastguard Worker DVLOG(1) << "Finished setting up SOCKS handshake";
231*6777b538SAndroid Build Coastguard Worker std::move(user_callback_).Run(result);
232*6777b538SAndroid Build Coastguard Worker }
233*6777b538SAndroid Build Coastguard Worker
OnIOComplete(int result)234*6777b538SAndroid Build Coastguard Worker void SOCKSClientSocket::OnIOComplete(int result) {
235*6777b538SAndroid Build Coastguard Worker DCHECK_NE(STATE_NONE, next_state_);
236*6777b538SAndroid Build Coastguard Worker int rv = DoLoop(result);
237*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING) {
238*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS_CONNECT, rv);
239*6777b538SAndroid Build Coastguard Worker DoCallback(rv);
240*6777b538SAndroid Build Coastguard Worker }
241*6777b538SAndroid Build Coastguard Worker }
242*6777b538SAndroid Build Coastguard Worker
OnReadWriteComplete(CompletionOnceCallback callback,int result)243*6777b538SAndroid Build Coastguard Worker void SOCKSClientSocket::OnReadWriteComplete(CompletionOnceCallback callback,
244*6777b538SAndroid Build Coastguard Worker int result) {
245*6777b538SAndroid Build Coastguard Worker DCHECK_NE(ERR_IO_PENDING, result);
246*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
247*6777b538SAndroid Build Coastguard Worker
248*6777b538SAndroid Build Coastguard Worker if (result > 0)
249*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
250*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(result);
251*6777b538SAndroid Build Coastguard Worker }
252*6777b538SAndroid Build Coastguard Worker
DoLoop(int last_io_result)253*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::DoLoop(int last_io_result) {
254*6777b538SAndroid Build Coastguard Worker DCHECK_NE(next_state_, STATE_NONE);
255*6777b538SAndroid Build Coastguard Worker int rv = last_io_result;
256*6777b538SAndroid Build Coastguard Worker do {
257*6777b538SAndroid Build Coastguard Worker State state = next_state_;
258*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NONE;
259*6777b538SAndroid Build Coastguard Worker switch (state) {
260*6777b538SAndroid Build Coastguard Worker case STATE_RESOLVE_HOST:
261*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
262*6777b538SAndroid Build Coastguard Worker rv = DoResolveHost();
263*6777b538SAndroid Build Coastguard Worker break;
264*6777b538SAndroid Build Coastguard Worker case STATE_RESOLVE_HOST_COMPLETE:
265*6777b538SAndroid Build Coastguard Worker rv = DoResolveHostComplete(rv);
266*6777b538SAndroid Build Coastguard Worker break;
267*6777b538SAndroid Build Coastguard Worker case STATE_HANDSHAKE_WRITE:
268*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
269*6777b538SAndroid Build Coastguard Worker rv = DoHandshakeWrite();
270*6777b538SAndroid Build Coastguard Worker break;
271*6777b538SAndroid Build Coastguard Worker case STATE_HANDSHAKE_WRITE_COMPLETE:
272*6777b538SAndroid Build Coastguard Worker rv = DoHandshakeWriteComplete(rv);
273*6777b538SAndroid Build Coastguard Worker break;
274*6777b538SAndroid Build Coastguard Worker case STATE_HANDSHAKE_READ:
275*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
276*6777b538SAndroid Build Coastguard Worker rv = DoHandshakeRead();
277*6777b538SAndroid Build Coastguard Worker break;
278*6777b538SAndroid Build Coastguard Worker case STATE_HANDSHAKE_READ_COMPLETE:
279*6777b538SAndroid Build Coastguard Worker rv = DoHandshakeReadComplete(rv);
280*6777b538SAndroid Build Coastguard Worker break;
281*6777b538SAndroid Build Coastguard Worker default:
282*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "bad state";
283*6777b538SAndroid Build Coastguard Worker rv = ERR_UNEXPECTED;
284*6777b538SAndroid Build Coastguard Worker break;
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
287*6777b538SAndroid Build Coastguard Worker return rv;
288*6777b538SAndroid Build Coastguard Worker }
289*6777b538SAndroid Build Coastguard Worker
DoResolveHost()290*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::DoResolveHost() {
291*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_RESOLVE_HOST_COMPLETE;
292*6777b538SAndroid Build Coastguard Worker // SOCKS4 only supports IPv4 addresses, so only try getting the IPv4
293*6777b538SAndroid Build Coastguard Worker // addresses for the target host.
294*6777b538SAndroid Build Coastguard Worker HostResolver::ResolveHostParameters parameters;
295*6777b538SAndroid Build Coastguard Worker parameters.dns_query_type = DnsQueryType::A;
296*6777b538SAndroid Build Coastguard Worker parameters.initial_priority = priority_;
297*6777b538SAndroid Build Coastguard Worker parameters.secure_dns_policy = secure_dns_policy_;
298*6777b538SAndroid Build Coastguard Worker resolve_host_request_ = host_resolver_->CreateRequest(
299*6777b538SAndroid Build Coastguard Worker destination_, network_anonymization_key_, net_log_, parameters);
300*6777b538SAndroid Build Coastguard Worker
301*6777b538SAndroid Build Coastguard Worker return resolve_host_request_->Start(
302*6777b538SAndroid Build Coastguard Worker base::BindOnce(&SOCKSClientSocket::OnIOComplete, base::Unretained(this)));
303*6777b538SAndroid Build Coastguard Worker }
304*6777b538SAndroid Build Coastguard Worker
DoResolveHostComplete(int result)305*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::DoResolveHostComplete(int result) {
306*6777b538SAndroid Build Coastguard Worker resolve_error_info_ = resolve_host_request_->GetResolveErrorInfo();
307*6777b538SAndroid Build Coastguard Worker if (result != OK) {
308*6777b538SAndroid Build Coastguard Worker // Resolving the hostname failed; fail the request rather than automatically
309*6777b538SAndroid Build Coastguard Worker // falling back to SOCKS4a (since it can be confusing to see invalid IP
310*6777b538SAndroid Build Coastguard Worker // addresses being sent to the SOCKS4 server when it doesn't support 4A.)
311*6777b538SAndroid Build Coastguard Worker return result;
312*6777b538SAndroid Build Coastguard Worker }
313*6777b538SAndroid Build Coastguard Worker
314*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_WRITE;
315*6777b538SAndroid Build Coastguard Worker return OK;
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker
318*6777b538SAndroid Build Coastguard Worker // Builds the buffer that is to be sent to the server.
BuildHandshakeWriteBuffer() const319*6777b538SAndroid Build Coastguard Worker const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const {
320*6777b538SAndroid Build Coastguard Worker SOCKS4ServerRequest request;
321*6777b538SAndroid Build Coastguard Worker request.version = kSOCKSVersion4;
322*6777b538SAndroid Build Coastguard Worker request.command = kSOCKSStreamRequest;
323*6777b538SAndroid Build Coastguard Worker request.nw_port = base::HostToNet16(destination_.port());
324*6777b538SAndroid Build Coastguard Worker
325*6777b538SAndroid Build Coastguard Worker DCHECK(resolve_host_request_->GetAddressResults() &&
326*6777b538SAndroid Build Coastguard Worker !resolve_host_request_->GetAddressResults()->empty());
327*6777b538SAndroid Build Coastguard Worker const IPEndPoint& endpoint =
328*6777b538SAndroid Build Coastguard Worker resolve_host_request_->GetAddressResults()->front();
329*6777b538SAndroid Build Coastguard Worker
330*6777b538SAndroid Build Coastguard Worker // We disabled IPv6 results when resolving the hostname, so none of the
331*6777b538SAndroid Build Coastguard Worker // results in the list will be IPv6.
332*6777b538SAndroid Build Coastguard Worker // TODO(eroman): we only ever use the first address in the list. It would be
333*6777b538SAndroid Build Coastguard Worker // more robust to try all the IP addresses we have before
334*6777b538SAndroid Build Coastguard Worker // failing the connect attempt.
335*6777b538SAndroid Build Coastguard Worker CHECK_EQ(ADDRESS_FAMILY_IPV4, endpoint.GetFamily());
336*6777b538SAndroid Build Coastguard Worker CHECK_LE(endpoint.address().size(), sizeof(request.ip));
337*6777b538SAndroid Build Coastguard Worker memcpy(&request.ip, &endpoint.address().bytes()[0],
338*6777b538SAndroid Build Coastguard Worker endpoint.address().size());
339*6777b538SAndroid Build Coastguard Worker
340*6777b538SAndroid Build Coastguard Worker DVLOG(1) << "Resolved Host is : " << endpoint.ToStringWithoutPort();
341*6777b538SAndroid Build Coastguard Worker
342*6777b538SAndroid Build Coastguard Worker std::string handshake_data(reinterpret_cast<char*>(&request),
343*6777b538SAndroid Build Coastguard Worker sizeof(request));
344*6777b538SAndroid Build Coastguard Worker handshake_data.append(kEmptyUserId, std::size(kEmptyUserId));
345*6777b538SAndroid Build Coastguard Worker
346*6777b538SAndroid Build Coastguard Worker return handshake_data;
347*6777b538SAndroid Build Coastguard Worker }
348*6777b538SAndroid Build Coastguard Worker
349*6777b538SAndroid Build Coastguard Worker // Writes the SOCKS handshake data to the underlying socket connection.
DoHandshakeWrite()350*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::DoHandshakeWrite() {
351*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
352*6777b538SAndroid Build Coastguard Worker
353*6777b538SAndroid Build Coastguard Worker if (buffer_.empty()) {
354*6777b538SAndroid Build Coastguard Worker buffer_ = BuildHandshakeWriteBuffer();
355*6777b538SAndroid Build Coastguard Worker bytes_sent_ = 0;
356*6777b538SAndroid Build Coastguard Worker }
357*6777b538SAndroid Build Coastguard Worker
358*6777b538SAndroid Build Coastguard Worker int handshake_buf_len = buffer_.size() - bytes_sent_;
359*6777b538SAndroid Build Coastguard Worker DCHECK_GT(handshake_buf_len, 0);
360*6777b538SAndroid Build Coastguard Worker handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
361*6777b538SAndroid Build Coastguard Worker memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
362*6777b538SAndroid Build Coastguard Worker handshake_buf_len);
363*6777b538SAndroid Build Coastguard Worker return transport_socket_->Write(
364*6777b538SAndroid Build Coastguard Worker handshake_buf_.get(), handshake_buf_len,
365*6777b538SAndroid Build Coastguard Worker base::BindOnce(&SOCKSClientSocket::OnIOComplete, base::Unretained(this)),
366*6777b538SAndroid Build Coastguard Worker traffic_annotation_);
367*6777b538SAndroid Build Coastguard Worker }
368*6777b538SAndroid Build Coastguard Worker
DoHandshakeWriteComplete(int result)369*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::DoHandshakeWriteComplete(int result) {
370*6777b538SAndroid Build Coastguard Worker if (result < 0)
371*6777b538SAndroid Build Coastguard Worker return result;
372*6777b538SAndroid Build Coastguard Worker
373*6777b538SAndroid Build Coastguard Worker // We ignore the case when result is 0, since the underlying Write
374*6777b538SAndroid Build Coastguard Worker // may return spurious writes while waiting on the socket.
375*6777b538SAndroid Build Coastguard Worker
376*6777b538SAndroid Build Coastguard Worker bytes_sent_ += result;
377*6777b538SAndroid Build Coastguard Worker if (bytes_sent_ == buffer_.size()) {
378*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_READ;
379*6777b538SAndroid Build Coastguard Worker buffer_.clear();
380*6777b538SAndroid Build Coastguard Worker } else if (bytes_sent_ < buffer_.size()) {
381*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_WRITE;
382*6777b538SAndroid Build Coastguard Worker } else {
383*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
384*6777b538SAndroid Build Coastguard Worker }
385*6777b538SAndroid Build Coastguard Worker
386*6777b538SAndroid Build Coastguard Worker return OK;
387*6777b538SAndroid Build Coastguard Worker }
388*6777b538SAndroid Build Coastguard Worker
DoHandshakeRead()389*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::DoHandshakeRead() {
390*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
391*6777b538SAndroid Build Coastguard Worker
392*6777b538SAndroid Build Coastguard Worker if (buffer_.empty()) {
393*6777b538SAndroid Build Coastguard Worker bytes_received_ = 0;
394*6777b538SAndroid Build Coastguard Worker }
395*6777b538SAndroid Build Coastguard Worker
396*6777b538SAndroid Build Coastguard Worker int handshake_buf_len = kReadHeaderSize - bytes_received_;
397*6777b538SAndroid Build Coastguard Worker handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
398*6777b538SAndroid Build Coastguard Worker return transport_socket_->Read(
399*6777b538SAndroid Build Coastguard Worker handshake_buf_.get(), handshake_buf_len,
400*6777b538SAndroid Build Coastguard Worker base::BindOnce(&SOCKSClientSocket::OnIOComplete, base::Unretained(this)));
401*6777b538SAndroid Build Coastguard Worker }
402*6777b538SAndroid Build Coastguard Worker
DoHandshakeReadComplete(int result)403*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::DoHandshakeReadComplete(int result) {
404*6777b538SAndroid Build Coastguard Worker if (result < 0)
405*6777b538SAndroid Build Coastguard Worker return result;
406*6777b538SAndroid Build Coastguard Worker
407*6777b538SAndroid Build Coastguard Worker // The underlying socket closed unexpectedly.
408*6777b538SAndroid Build Coastguard Worker if (result == 0)
409*6777b538SAndroid Build Coastguard Worker return ERR_CONNECTION_CLOSED;
410*6777b538SAndroid Build Coastguard Worker
411*6777b538SAndroid Build Coastguard Worker if (bytes_received_ + result > kReadHeaderSize) {
412*6777b538SAndroid Build Coastguard Worker // TODO(eroman): Describe failure in NetLog.
413*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
414*6777b538SAndroid Build Coastguard Worker }
415*6777b538SAndroid Build Coastguard Worker
416*6777b538SAndroid Build Coastguard Worker buffer_.append(handshake_buf_->data(), result);
417*6777b538SAndroid Build Coastguard Worker bytes_received_ += result;
418*6777b538SAndroid Build Coastguard Worker if (bytes_received_ < kReadHeaderSize) {
419*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_READ;
420*6777b538SAndroid Build Coastguard Worker return OK;
421*6777b538SAndroid Build Coastguard Worker }
422*6777b538SAndroid Build Coastguard Worker
423*6777b538SAndroid Build Coastguard Worker const SOCKS4ServerResponse* response =
424*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data());
425*6777b538SAndroid Build Coastguard Worker
426*6777b538SAndroid Build Coastguard Worker if (response->reserved_null != 0x00) {
427*6777b538SAndroid Build Coastguard Worker DVLOG(1) << "Unknown response from SOCKS server.";
428*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
429*6777b538SAndroid Build Coastguard Worker }
430*6777b538SAndroid Build Coastguard Worker
431*6777b538SAndroid Build Coastguard Worker switch (response->code) {
432*6777b538SAndroid Build Coastguard Worker case kServerResponseOk:
433*6777b538SAndroid Build Coastguard Worker completed_handshake_ = true;
434*6777b538SAndroid Build Coastguard Worker return OK;
435*6777b538SAndroid Build Coastguard Worker case kServerResponseRejected:
436*6777b538SAndroid Build Coastguard Worker DVLOG(1) << "SOCKS request rejected or failed";
437*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
438*6777b538SAndroid Build Coastguard Worker case kServerResponseNotReachable:
439*6777b538SAndroid Build Coastguard Worker DVLOG(1) << "SOCKS request failed because client is not running "
440*6777b538SAndroid Build Coastguard Worker << "identd (or not reachable from the server)";
441*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_HOST_UNREACHABLE;
442*6777b538SAndroid Build Coastguard Worker case kServerResponseMismatchedUserId:
443*6777b538SAndroid Build Coastguard Worker DVLOG(1) << "SOCKS request failed because client's identd could "
444*6777b538SAndroid Build Coastguard Worker << "not confirm the user ID string in the request";
445*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
446*6777b538SAndroid Build Coastguard Worker default:
447*6777b538SAndroid Build Coastguard Worker DVLOG(1) << "SOCKS server sent unknown response";
448*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
449*6777b538SAndroid Build Coastguard Worker }
450*6777b538SAndroid Build Coastguard Worker
451*6777b538SAndroid Build Coastguard Worker // Note: we ignore the last 6 bytes as specified by the SOCKS protocol
452*6777b538SAndroid Build Coastguard Worker }
453*6777b538SAndroid Build Coastguard Worker
GetPeerAddress(IPEndPoint * address) const454*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::GetPeerAddress(IPEndPoint* address) const {
455*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetPeerAddress(address);
456*6777b538SAndroid Build Coastguard Worker }
457*6777b538SAndroid Build Coastguard Worker
GetLocalAddress(IPEndPoint * address) const458*6777b538SAndroid Build Coastguard Worker int SOCKSClientSocket::GetLocalAddress(IPEndPoint* address) const {
459*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetLocalAddress(address);
460*6777b538SAndroid Build Coastguard Worker }
461*6777b538SAndroid Build Coastguard Worker
GetResolveErrorInfo() const462*6777b538SAndroid Build Coastguard Worker ResolveErrorInfo SOCKSClientSocket::GetResolveErrorInfo() const {
463*6777b538SAndroid Build Coastguard Worker return resolve_error_info_;
464*6777b538SAndroid Build Coastguard Worker }
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker } // namespace net
467