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/socks5_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/format_macros.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/sys_byteorder.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/base/sys_addrinfo.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/base/tracing.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_event_type.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/traffic_annotation/network_traffic_annotation.h"
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker namespace net {
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2;
25*6777b538SAndroid Build Coastguard Worker const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10;
26*6777b538SAndroid Build Coastguard Worker const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5;
27*6777b538SAndroid Build Coastguard Worker const uint8_t SOCKS5ClientSocket::kSOCKS5Version = 0x05;
28*6777b538SAndroid Build Coastguard Worker const uint8_t SOCKS5ClientSocket::kTunnelCommand = 0x01;
29*6777b538SAndroid Build Coastguard Worker const uint8_t SOCKS5ClientSocket::kNullByte = 0x00;
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker static_assert(sizeof(struct in_addr) == 4, "incorrect system size of IPv4");
32*6777b538SAndroid Build Coastguard Worker static_assert(sizeof(struct in6_addr) == 16, "incorrect system size of IPv6");
33*6777b538SAndroid Build Coastguard Worker
SOCKS5ClientSocket(std::unique_ptr<StreamSocket> transport_socket,const HostPortPair & destination,const NetworkTrafficAnnotationTag & traffic_annotation)34*6777b538SAndroid Build Coastguard Worker SOCKS5ClientSocket::SOCKS5ClientSocket(
35*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StreamSocket> transport_socket,
36*6777b538SAndroid Build Coastguard Worker const HostPortPair& destination,
37*6777b538SAndroid Build Coastguard Worker const NetworkTrafficAnnotationTag& traffic_annotation)
38*6777b538SAndroid Build Coastguard Worker : io_callback_(base::BindRepeating(&SOCKS5ClientSocket::OnIOComplete,
39*6777b538SAndroid Build Coastguard Worker base::Unretained(this))),
40*6777b538SAndroid Build Coastguard Worker transport_socket_(std::move(transport_socket)),
41*6777b538SAndroid Build Coastguard Worker read_header_size(kReadHeaderSize),
42*6777b538SAndroid Build Coastguard Worker destination_(destination),
43*6777b538SAndroid Build Coastguard Worker net_log_(transport_socket_->NetLog()),
44*6777b538SAndroid Build Coastguard Worker traffic_annotation_(traffic_annotation) {}
45*6777b538SAndroid Build Coastguard Worker
~SOCKS5ClientSocket()46*6777b538SAndroid Build Coastguard Worker SOCKS5ClientSocket::~SOCKS5ClientSocket() {
47*6777b538SAndroid Build Coastguard Worker Disconnect();
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker
Connect(CompletionOnceCallback callback)50*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::Connect(CompletionOnceCallback callback) {
51*6777b538SAndroid Build Coastguard Worker DCHECK(transport_socket_);
52*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
53*6777b538SAndroid Build Coastguard Worker DCHECK(user_callback_.is_null());
54*6777b538SAndroid Build Coastguard Worker
55*6777b538SAndroid Build Coastguard Worker // If already connected, then just return OK.
56*6777b538SAndroid Build Coastguard Worker if (completed_handshake_)
57*6777b538SAndroid Build Coastguard Worker return OK;
58*6777b538SAndroid Build Coastguard Worker
59*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::SOCKS5_CONNECT);
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_GREET_WRITE;
62*6777b538SAndroid Build Coastguard Worker buffer_.clear();
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker int rv = DoLoop(OK);
65*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
66*6777b538SAndroid Build Coastguard Worker user_callback_ = std::move(callback);
67*6777b538SAndroid Build Coastguard Worker } else {
68*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_CONNECT, rv);
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker return rv;
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker
Disconnect()73*6777b538SAndroid Build Coastguard Worker void SOCKS5ClientSocket::Disconnect() {
74*6777b538SAndroid Build Coastguard Worker completed_handshake_ = false;
75*6777b538SAndroid Build Coastguard Worker transport_socket_->Disconnect();
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker // Reset other states to make sure they aren't mistakenly used later.
78*6777b538SAndroid Build Coastguard Worker // These are the states initialized by Connect().
79*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NONE;
80*6777b538SAndroid Build Coastguard Worker user_callback_.Reset();
81*6777b538SAndroid Build Coastguard Worker }
82*6777b538SAndroid Build Coastguard Worker
IsConnected() const83*6777b538SAndroid Build Coastguard Worker bool SOCKS5ClientSocket::IsConnected() const {
84*6777b538SAndroid Build Coastguard Worker return completed_handshake_ && transport_socket_->IsConnected();
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker
IsConnectedAndIdle() const87*6777b538SAndroid Build Coastguard Worker bool SOCKS5ClientSocket::IsConnectedAndIdle() const {
88*6777b538SAndroid Build Coastguard Worker return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
89*6777b538SAndroid Build Coastguard Worker }
90*6777b538SAndroid Build Coastguard Worker
NetLog() const91*6777b538SAndroid Build Coastguard Worker const NetLogWithSource& SOCKS5ClientSocket::NetLog() const {
92*6777b538SAndroid Build Coastguard Worker return net_log_;
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker
WasEverUsed() const95*6777b538SAndroid Build Coastguard Worker bool SOCKS5ClientSocket::WasEverUsed() const {
96*6777b538SAndroid Build Coastguard Worker return was_ever_used_;
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker
GetNegotiatedProtocol() const99*6777b538SAndroid Build Coastguard Worker NextProto SOCKS5ClientSocket::GetNegotiatedProtocol() const {
100*6777b538SAndroid Build Coastguard Worker if (transport_socket_)
101*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetNegotiatedProtocol();
102*6777b538SAndroid Build Coastguard Worker NOTREACHED();
103*6777b538SAndroid Build Coastguard Worker return kProtoUnknown;
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker
GetSSLInfo(SSLInfo * ssl_info)106*6777b538SAndroid Build Coastguard Worker bool SOCKS5ClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
107*6777b538SAndroid Build Coastguard Worker if (transport_socket_)
108*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetSSLInfo(ssl_info);
109*6777b538SAndroid Build Coastguard Worker NOTREACHED();
110*6777b538SAndroid Build Coastguard Worker return false;
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker
GetTotalReceivedBytes() const113*6777b538SAndroid Build Coastguard Worker int64_t SOCKS5ClientSocket::GetTotalReceivedBytes() const {
114*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetTotalReceivedBytes();
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker
ApplySocketTag(const SocketTag & tag)117*6777b538SAndroid Build Coastguard Worker void SOCKS5ClientSocket::ApplySocketTag(const SocketTag& tag) {
118*6777b538SAndroid Build Coastguard Worker return transport_socket_->ApplySocketTag(tag);
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker // Read is called by the transport layer above to read. This can only be done
122*6777b538SAndroid Build Coastguard Worker // if the SOCKS handshake is complete.
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)123*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::Read(IOBuffer* buf,
124*6777b538SAndroid Build Coastguard Worker int buf_len,
125*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
126*6777b538SAndroid Build Coastguard Worker DCHECK(completed_handshake_);
127*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
128*6777b538SAndroid Build Coastguard Worker DCHECK(user_callback_.is_null());
129*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker int rv = transport_socket_->Read(
132*6777b538SAndroid Build Coastguard Worker buf, buf_len,
133*6777b538SAndroid Build Coastguard Worker base::BindOnce(&SOCKS5ClientSocket::OnReadWriteComplete,
134*6777b538SAndroid Build Coastguard Worker base::Unretained(this), std::move(callback)));
135*6777b538SAndroid Build Coastguard Worker if (rv > 0)
136*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
137*6777b538SAndroid Build Coastguard Worker return rv;
138*6777b538SAndroid Build Coastguard Worker }
139*6777b538SAndroid Build Coastguard Worker
140*6777b538SAndroid Build Coastguard Worker // Write is called by the transport layer. This can only be done if the
141*6777b538SAndroid Build Coastguard Worker // SOCKS handshake is complete.
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)142*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::Write(
143*6777b538SAndroid Build Coastguard Worker IOBuffer* buf,
144*6777b538SAndroid Build Coastguard Worker int buf_len,
145*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback,
146*6777b538SAndroid Build Coastguard Worker const NetworkTrafficAnnotationTag& traffic_annotation) {
147*6777b538SAndroid Build Coastguard Worker DCHECK(completed_handshake_);
148*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
149*6777b538SAndroid Build Coastguard Worker DCHECK(user_callback_.is_null());
150*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
151*6777b538SAndroid Build Coastguard Worker
152*6777b538SAndroid Build Coastguard Worker int rv = transport_socket_->Write(
153*6777b538SAndroid Build Coastguard Worker buf, buf_len,
154*6777b538SAndroid Build Coastguard Worker base::BindOnce(&SOCKS5ClientSocket::OnReadWriteComplete,
155*6777b538SAndroid Build Coastguard Worker base::Unretained(this), std::move(callback)),
156*6777b538SAndroid Build Coastguard Worker traffic_annotation);
157*6777b538SAndroid Build Coastguard Worker if (rv > 0)
158*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
159*6777b538SAndroid Build Coastguard Worker return rv;
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker
SetReceiveBufferSize(int32_t size)162*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::SetReceiveBufferSize(int32_t size) {
163*6777b538SAndroid Build Coastguard Worker return transport_socket_->SetReceiveBufferSize(size);
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker
SetSendBufferSize(int32_t size)166*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::SetSendBufferSize(int32_t size) {
167*6777b538SAndroid Build Coastguard Worker return transport_socket_->SetSendBufferSize(size);
168*6777b538SAndroid Build Coastguard Worker }
169*6777b538SAndroid Build Coastguard Worker
DoCallback(int result)170*6777b538SAndroid Build Coastguard Worker void SOCKS5ClientSocket::DoCallback(int result) {
171*6777b538SAndroid Build Coastguard Worker DCHECK_NE(ERR_IO_PENDING, result);
172*6777b538SAndroid Build Coastguard Worker DCHECK(!user_callback_.is_null());
173*6777b538SAndroid Build Coastguard Worker
174*6777b538SAndroid Build Coastguard Worker // Since Run() may result in Read being called,
175*6777b538SAndroid Build Coastguard Worker // clear user_callback_ up front.
176*6777b538SAndroid Build Coastguard Worker std::move(user_callback_).Run(result);
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker
OnIOComplete(int result)179*6777b538SAndroid Build Coastguard Worker void SOCKS5ClientSocket::OnIOComplete(int result) {
180*6777b538SAndroid Build Coastguard Worker DCHECK_NE(STATE_NONE, next_state_);
181*6777b538SAndroid Build Coastguard Worker int rv = DoLoop(result);
182*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING) {
183*6777b538SAndroid Build Coastguard Worker net_log_.EndEvent(NetLogEventType::SOCKS5_CONNECT);
184*6777b538SAndroid Build Coastguard Worker DoCallback(rv);
185*6777b538SAndroid Build Coastguard Worker }
186*6777b538SAndroid Build Coastguard Worker }
187*6777b538SAndroid Build Coastguard Worker
OnReadWriteComplete(CompletionOnceCallback callback,int result)188*6777b538SAndroid Build Coastguard Worker void SOCKS5ClientSocket::OnReadWriteComplete(CompletionOnceCallback callback,
189*6777b538SAndroid Build Coastguard Worker int result) {
190*6777b538SAndroid Build Coastguard Worker DCHECK_NE(ERR_IO_PENDING, result);
191*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
192*6777b538SAndroid Build Coastguard Worker
193*6777b538SAndroid Build Coastguard Worker if (result > 0)
194*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
195*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(result);
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker
DoLoop(int last_io_result)198*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoLoop(int last_io_result) {
199*6777b538SAndroid Build Coastguard Worker DCHECK_NE(next_state_, STATE_NONE);
200*6777b538SAndroid Build Coastguard Worker int rv = last_io_result;
201*6777b538SAndroid Build Coastguard Worker do {
202*6777b538SAndroid Build Coastguard Worker State state = next_state_;
203*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NONE;
204*6777b538SAndroid Build Coastguard Worker switch (state) {
205*6777b538SAndroid Build Coastguard Worker case STATE_GREET_WRITE:
206*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
207*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::SOCKS5_GREET_WRITE);
208*6777b538SAndroid Build Coastguard Worker rv = DoGreetWrite();
209*6777b538SAndroid Build Coastguard Worker break;
210*6777b538SAndroid Build Coastguard Worker case STATE_GREET_WRITE_COMPLETE:
211*6777b538SAndroid Build Coastguard Worker rv = DoGreetWriteComplete(rv);
212*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_GREET_WRITE,
213*6777b538SAndroid Build Coastguard Worker rv);
214*6777b538SAndroid Build Coastguard Worker break;
215*6777b538SAndroid Build Coastguard Worker case STATE_GREET_READ:
216*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
217*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::SOCKS5_GREET_READ);
218*6777b538SAndroid Build Coastguard Worker rv = DoGreetRead();
219*6777b538SAndroid Build Coastguard Worker break;
220*6777b538SAndroid Build Coastguard Worker case STATE_GREET_READ_COMPLETE:
221*6777b538SAndroid Build Coastguard Worker rv = DoGreetReadComplete(rv);
222*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_GREET_READ,
223*6777b538SAndroid Build Coastguard Worker rv);
224*6777b538SAndroid Build Coastguard Worker break;
225*6777b538SAndroid Build Coastguard Worker case STATE_HANDSHAKE_WRITE:
226*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
227*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::SOCKS5_HANDSHAKE_WRITE);
228*6777b538SAndroid Build Coastguard Worker rv = DoHandshakeWrite();
229*6777b538SAndroid Build Coastguard Worker break;
230*6777b538SAndroid Build Coastguard Worker case STATE_HANDSHAKE_WRITE_COMPLETE:
231*6777b538SAndroid Build Coastguard Worker rv = DoHandshakeWriteComplete(rv);
232*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(
233*6777b538SAndroid Build Coastguard Worker NetLogEventType::SOCKS5_HANDSHAKE_WRITE, rv);
234*6777b538SAndroid Build Coastguard Worker break;
235*6777b538SAndroid Build Coastguard Worker case STATE_HANDSHAKE_READ:
236*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
237*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::SOCKS5_HANDSHAKE_READ);
238*6777b538SAndroid Build Coastguard Worker rv = DoHandshakeRead();
239*6777b538SAndroid Build Coastguard Worker break;
240*6777b538SAndroid Build Coastguard Worker case STATE_HANDSHAKE_READ_COMPLETE:
241*6777b538SAndroid Build Coastguard Worker rv = DoHandshakeReadComplete(rv);
242*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(
243*6777b538SAndroid Build Coastguard Worker NetLogEventType::SOCKS5_HANDSHAKE_READ, rv);
244*6777b538SAndroid Build Coastguard Worker break;
245*6777b538SAndroid Build Coastguard Worker default:
246*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "bad state";
247*6777b538SAndroid Build Coastguard Worker rv = ERR_UNEXPECTED;
248*6777b538SAndroid Build Coastguard Worker break;
249*6777b538SAndroid Build Coastguard Worker }
250*6777b538SAndroid Build Coastguard Worker } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
251*6777b538SAndroid Build Coastguard Worker return rv;
252*6777b538SAndroid Build Coastguard Worker }
253*6777b538SAndroid Build Coastguard Worker
254*6777b538SAndroid Build Coastguard Worker const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication
255*6777b538SAndroid Build Coastguard Worker
DoGreetWrite()256*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoGreetWrite() {
257*6777b538SAndroid Build Coastguard Worker // Since we only have 1 byte to send the hostname length in, if the
258*6777b538SAndroid Build Coastguard Worker // URL has a hostname longer than 255 characters we can't send it.
259*6777b538SAndroid Build Coastguard Worker if (0xFF < destination_.host().size()) {
260*6777b538SAndroid Build Coastguard Worker net_log_.AddEvent(NetLogEventType::SOCKS_HOSTNAME_TOO_BIG);
261*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
262*6777b538SAndroid Build Coastguard Worker }
263*6777b538SAndroid Build Coastguard Worker
264*6777b538SAndroid Build Coastguard Worker if (buffer_.empty()) {
265*6777b538SAndroid Build Coastguard Worker buffer_ =
266*6777b538SAndroid Build Coastguard Worker std::string(kSOCKS5GreetWriteData, std::size(kSOCKS5GreetWriteData));
267*6777b538SAndroid Build Coastguard Worker bytes_sent_ = 0;
268*6777b538SAndroid Build Coastguard Worker }
269*6777b538SAndroid Build Coastguard Worker
270*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_GREET_WRITE_COMPLETE;
271*6777b538SAndroid Build Coastguard Worker size_t handshake_buf_len = buffer_.size() - bytes_sent_;
272*6777b538SAndroid Build Coastguard Worker handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
273*6777b538SAndroid Build Coastguard Worker memcpy(handshake_buf_->data(), &buffer_.data()[bytes_sent_],
274*6777b538SAndroid Build Coastguard Worker handshake_buf_len);
275*6777b538SAndroid Build Coastguard Worker return transport_socket_->Write(handshake_buf_.get(), handshake_buf_len,
276*6777b538SAndroid Build Coastguard Worker io_callback_, traffic_annotation_);
277*6777b538SAndroid Build Coastguard Worker }
278*6777b538SAndroid Build Coastguard Worker
DoGreetWriteComplete(int result)279*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoGreetWriteComplete(int result) {
280*6777b538SAndroid Build Coastguard Worker if (result < 0)
281*6777b538SAndroid Build Coastguard Worker return result;
282*6777b538SAndroid Build Coastguard Worker
283*6777b538SAndroid Build Coastguard Worker bytes_sent_ += result;
284*6777b538SAndroid Build Coastguard Worker if (bytes_sent_ == buffer_.size()) {
285*6777b538SAndroid Build Coastguard Worker buffer_.clear();
286*6777b538SAndroid Build Coastguard Worker bytes_received_ = 0;
287*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_GREET_READ;
288*6777b538SAndroid Build Coastguard Worker } else {
289*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_GREET_WRITE;
290*6777b538SAndroid Build Coastguard Worker }
291*6777b538SAndroid Build Coastguard Worker return OK;
292*6777b538SAndroid Build Coastguard Worker }
293*6777b538SAndroid Build Coastguard Worker
DoGreetRead()294*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoGreetRead() {
295*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_GREET_READ_COMPLETE;
296*6777b538SAndroid Build Coastguard Worker size_t handshake_buf_len = kGreetReadHeaderSize - bytes_received_;
297*6777b538SAndroid Build Coastguard Worker handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
298*6777b538SAndroid Build Coastguard Worker return transport_socket_->Read(handshake_buf_.get(), handshake_buf_len,
299*6777b538SAndroid Build Coastguard Worker io_callback_);
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker
DoGreetReadComplete(int result)302*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoGreetReadComplete(int result) {
303*6777b538SAndroid Build Coastguard Worker if (result < 0)
304*6777b538SAndroid Build Coastguard Worker return result;
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker if (result == 0) {
307*6777b538SAndroid Build Coastguard Worker net_log_.AddEvent(
308*6777b538SAndroid Build Coastguard Worker NetLogEventType::SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING);
309*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker bytes_received_ += result;
313*6777b538SAndroid Build Coastguard Worker buffer_.append(handshake_buf_->data(), result);
314*6777b538SAndroid Build Coastguard Worker if (bytes_received_ < kGreetReadHeaderSize) {
315*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_GREET_READ;
316*6777b538SAndroid Build Coastguard Worker return OK;
317*6777b538SAndroid Build Coastguard Worker }
318*6777b538SAndroid Build Coastguard Worker
319*6777b538SAndroid Build Coastguard Worker // Got the greet data.
320*6777b538SAndroid Build Coastguard Worker if (buffer_[0] != kSOCKS5Version) {
321*6777b538SAndroid Build Coastguard Worker net_log_.AddEventWithIntParams(NetLogEventType::SOCKS_UNEXPECTED_VERSION,
322*6777b538SAndroid Build Coastguard Worker "version", buffer_[0]);
323*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
324*6777b538SAndroid Build Coastguard Worker }
325*6777b538SAndroid Build Coastguard Worker if (buffer_[1] != 0x00) {
326*6777b538SAndroid Build Coastguard Worker net_log_.AddEventWithIntParams(NetLogEventType::SOCKS_UNEXPECTED_AUTH,
327*6777b538SAndroid Build Coastguard Worker "method", buffer_[1]);
328*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
329*6777b538SAndroid Build Coastguard Worker }
330*6777b538SAndroid Build Coastguard Worker
331*6777b538SAndroid Build Coastguard Worker buffer_.clear();
332*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_WRITE;
333*6777b538SAndroid Build Coastguard Worker return OK;
334*6777b538SAndroid Build Coastguard Worker }
335*6777b538SAndroid Build Coastguard Worker
BuildHandshakeWriteBuffer(std::string * handshake) const336*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake)
337*6777b538SAndroid Build Coastguard Worker const {
338*6777b538SAndroid Build Coastguard Worker DCHECK(handshake->empty());
339*6777b538SAndroid Build Coastguard Worker
340*6777b538SAndroid Build Coastguard Worker handshake->push_back(kSOCKS5Version);
341*6777b538SAndroid Build Coastguard Worker handshake->push_back(kTunnelCommand); // Connect command
342*6777b538SAndroid Build Coastguard Worker handshake->push_back(kNullByte); // Reserved null
343*6777b538SAndroid Build Coastguard Worker
344*6777b538SAndroid Build Coastguard Worker handshake->push_back(kEndPointDomain); // The type of the address.
345*6777b538SAndroid Build Coastguard Worker
346*6777b538SAndroid Build Coastguard Worker DCHECK_GE(static_cast<size_t>(0xFF), destination_.host().size());
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker // First add the size of the hostname, followed by the hostname.
349*6777b538SAndroid Build Coastguard Worker handshake->push_back(static_cast<unsigned char>(destination_.host().size()));
350*6777b538SAndroid Build Coastguard Worker handshake->append(destination_.host());
351*6777b538SAndroid Build Coastguard Worker
352*6777b538SAndroid Build Coastguard Worker uint16_t nw_port = base::HostToNet16(destination_.port());
353*6777b538SAndroid Build Coastguard Worker handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port));
354*6777b538SAndroid Build Coastguard Worker return OK;
355*6777b538SAndroid Build Coastguard Worker }
356*6777b538SAndroid Build Coastguard Worker
357*6777b538SAndroid Build Coastguard Worker // Writes the SOCKS handshake data to the underlying socket connection.
DoHandshakeWrite()358*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoHandshakeWrite() {
359*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
360*6777b538SAndroid Build Coastguard Worker
361*6777b538SAndroid Build Coastguard Worker if (buffer_.empty()) {
362*6777b538SAndroid Build Coastguard Worker int rv = BuildHandshakeWriteBuffer(&buffer_);
363*6777b538SAndroid Build Coastguard Worker if (rv != OK)
364*6777b538SAndroid Build Coastguard Worker return rv;
365*6777b538SAndroid Build Coastguard Worker bytes_sent_ = 0;
366*6777b538SAndroid Build Coastguard Worker }
367*6777b538SAndroid Build Coastguard Worker
368*6777b538SAndroid Build Coastguard Worker int handshake_buf_len = buffer_.size() - bytes_sent_;
369*6777b538SAndroid Build Coastguard Worker DCHECK_LT(0, handshake_buf_len);
370*6777b538SAndroid Build Coastguard Worker handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
371*6777b538SAndroid Build Coastguard Worker memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
372*6777b538SAndroid Build Coastguard Worker handshake_buf_len);
373*6777b538SAndroid Build Coastguard Worker return transport_socket_->Write(handshake_buf_.get(), handshake_buf_len,
374*6777b538SAndroid Build Coastguard Worker io_callback_, traffic_annotation_);
375*6777b538SAndroid Build Coastguard Worker }
376*6777b538SAndroid Build Coastguard Worker
DoHandshakeWriteComplete(int result)377*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) {
378*6777b538SAndroid Build Coastguard Worker if (result < 0)
379*6777b538SAndroid Build Coastguard Worker return result;
380*6777b538SAndroid Build Coastguard Worker
381*6777b538SAndroid Build Coastguard Worker // We ignore the case when result is 0, since the underlying Write
382*6777b538SAndroid Build Coastguard Worker // may return spurious writes while waiting on the socket.
383*6777b538SAndroid Build Coastguard Worker
384*6777b538SAndroid Build Coastguard Worker bytes_sent_ += result;
385*6777b538SAndroid Build Coastguard Worker if (bytes_sent_ == buffer_.size()) {
386*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_READ;
387*6777b538SAndroid Build Coastguard Worker buffer_.clear();
388*6777b538SAndroid Build Coastguard Worker } else if (bytes_sent_ < buffer_.size()) {
389*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_WRITE;
390*6777b538SAndroid Build Coastguard Worker } else {
391*6777b538SAndroid Build Coastguard Worker NOTREACHED();
392*6777b538SAndroid Build Coastguard Worker }
393*6777b538SAndroid Build Coastguard Worker
394*6777b538SAndroid Build Coastguard Worker return OK;
395*6777b538SAndroid Build Coastguard Worker }
396*6777b538SAndroid Build Coastguard Worker
DoHandshakeRead()397*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoHandshakeRead() {
398*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
399*6777b538SAndroid Build Coastguard Worker
400*6777b538SAndroid Build Coastguard Worker if (buffer_.empty()) {
401*6777b538SAndroid Build Coastguard Worker bytes_received_ = 0;
402*6777b538SAndroid Build Coastguard Worker read_header_size = kReadHeaderSize;
403*6777b538SAndroid Build Coastguard Worker }
404*6777b538SAndroid Build Coastguard Worker
405*6777b538SAndroid Build Coastguard Worker int handshake_buf_len = read_header_size - bytes_received_;
406*6777b538SAndroid Build Coastguard Worker handshake_buf_ = base::MakeRefCounted<IOBufferWithSize>(handshake_buf_len);
407*6777b538SAndroid Build Coastguard Worker return transport_socket_->Read(handshake_buf_.get(), handshake_buf_len,
408*6777b538SAndroid Build Coastguard Worker io_callback_);
409*6777b538SAndroid Build Coastguard Worker }
410*6777b538SAndroid Build Coastguard Worker
DoHandshakeReadComplete(int result)411*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) {
412*6777b538SAndroid Build Coastguard Worker if (result < 0)
413*6777b538SAndroid Build Coastguard Worker return result;
414*6777b538SAndroid Build Coastguard Worker
415*6777b538SAndroid Build Coastguard Worker // The underlying socket closed unexpectedly.
416*6777b538SAndroid Build Coastguard Worker if (result == 0) {
417*6777b538SAndroid Build Coastguard Worker net_log_.AddEvent(
418*6777b538SAndroid Build Coastguard Worker NetLogEventType::SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE);
419*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
420*6777b538SAndroid Build Coastguard Worker }
421*6777b538SAndroid Build Coastguard Worker
422*6777b538SAndroid Build Coastguard Worker buffer_.append(handshake_buf_->data(), result);
423*6777b538SAndroid Build Coastguard Worker bytes_received_ += result;
424*6777b538SAndroid Build Coastguard Worker
425*6777b538SAndroid Build Coastguard Worker // When the first few bytes are read, check how many more are required
426*6777b538SAndroid Build Coastguard Worker // and accordingly increase them
427*6777b538SAndroid Build Coastguard Worker if (bytes_received_ == kReadHeaderSize) {
428*6777b538SAndroid Build Coastguard Worker if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) {
429*6777b538SAndroid Build Coastguard Worker net_log_.AddEventWithIntParams(NetLogEventType::SOCKS_UNEXPECTED_VERSION,
430*6777b538SAndroid Build Coastguard Worker "version", buffer_[0]);
431*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
432*6777b538SAndroid Build Coastguard Worker }
433*6777b538SAndroid Build Coastguard Worker if (buffer_[1] != 0x00) {
434*6777b538SAndroid Build Coastguard Worker net_log_.AddEventWithIntParams(NetLogEventType::SOCKS_SERVER_ERROR,
435*6777b538SAndroid Build Coastguard Worker "error_code", buffer_[1]);
436*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
437*6777b538SAndroid Build Coastguard Worker }
438*6777b538SAndroid Build Coastguard Worker
439*6777b538SAndroid Build Coastguard Worker // We check the type of IP/Domain the server returns and accordingly
440*6777b538SAndroid Build Coastguard Worker // increase the size of the response. For domains, we need to read the
441*6777b538SAndroid Build Coastguard Worker // size of the domain, so the initial request size is upto the domain
442*6777b538SAndroid Build Coastguard Worker // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is
443*6777b538SAndroid Build Coastguard Worker // read, we substract 1 byte from the additional request size.
444*6777b538SAndroid Build Coastguard Worker SocksEndPointAddressType address_type =
445*6777b538SAndroid Build Coastguard Worker static_cast<SocksEndPointAddressType>(buffer_[3]);
446*6777b538SAndroid Build Coastguard Worker if (address_type == kEndPointDomain) {
447*6777b538SAndroid Build Coastguard Worker read_header_size += static_cast<uint8_t>(buffer_[4]);
448*6777b538SAndroid Build Coastguard Worker } else if (address_type == kEndPointResolvedIPv4) {
449*6777b538SAndroid Build Coastguard Worker read_header_size += sizeof(struct in_addr) - 1;
450*6777b538SAndroid Build Coastguard Worker } else if (address_type == kEndPointResolvedIPv6) {
451*6777b538SAndroid Build Coastguard Worker read_header_size += sizeof(struct in6_addr) - 1;
452*6777b538SAndroid Build Coastguard Worker } else {
453*6777b538SAndroid Build Coastguard Worker net_log_.AddEventWithIntParams(
454*6777b538SAndroid Build Coastguard Worker NetLogEventType::SOCKS_UNKNOWN_ADDRESS_TYPE, "address_type",
455*6777b538SAndroid Build Coastguard Worker buffer_[3]);
456*6777b538SAndroid Build Coastguard Worker return ERR_SOCKS_CONNECTION_FAILED;
457*6777b538SAndroid Build Coastguard Worker }
458*6777b538SAndroid Build Coastguard Worker
459*6777b538SAndroid Build Coastguard Worker read_header_size += 2; // for the port.
460*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_READ;
461*6777b538SAndroid Build Coastguard Worker return OK;
462*6777b538SAndroid Build Coastguard Worker }
463*6777b538SAndroid Build Coastguard Worker
464*6777b538SAndroid Build Coastguard Worker // When the final bytes are read, setup handshake. We ignore the rest
465*6777b538SAndroid Build Coastguard Worker // of the response since they represent the SOCKSv5 endpoint and have
466*6777b538SAndroid Build Coastguard Worker // no use when doing a tunnel connection.
467*6777b538SAndroid Build Coastguard Worker if (bytes_received_ == read_header_size) {
468*6777b538SAndroid Build Coastguard Worker completed_handshake_ = true;
469*6777b538SAndroid Build Coastguard Worker buffer_.clear();
470*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NONE;
471*6777b538SAndroid Build Coastguard Worker return OK;
472*6777b538SAndroid Build Coastguard Worker }
473*6777b538SAndroid Build Coastguard Worker
474*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HANDSHAKE_READ;
475*6777b538SAndroid Build Coastguard Worker return OK;
476*6777b538SAndroid Build Coastguard Worker }
477*6777b538SAndroid Build Coastguard Worker
GetPeerAddress(IPEndPoint * address) const478*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const {
479*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetPeerAddress(address);
480*6777b538SAndroid Build Coastguard Worker }
481*6777b538SAndroid Build Coastguard Worker
GetLocalAddress(IPEndPoint * address) const482*6777b538SAndroid Build Coastguard Worker int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const {
483*6777b538SAndroid Build Coastguard Worker return transport_socket_->GetLocalAddress(address);
484*6777b538SAndroid Build Coastguard Worker }
485*6777b538SAndroid Build Coastguard Worker
486*6777b538SAndroid Build Coastguard Worker } // namespace net
487