blob: db70461daa1b4ea9f4743354911436827bbb5f57 [file] [log] [blame]
[email protected]3cd17242009-06-23 02:59:021// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/socket/socks_client_socket.h"
6
7#include "base/basictypes.h"
[email protected]3cd17242009-06-23 02:59:028#include "base/compiler_specific.h"
9#include "base/trace_event.h"
10#include "net/base/io_buffer.h"
[email protected]5a05c47a2009-11-02 23:25:1911#include "net/base/load_log.h"
[email protected]3cd17242009-06-23 02:59:0212#include "net/base/net_util.h"
[email protected]a540c2d2009-12-12 00:47:3713#include "net/base/sys_addrinfo.h"
[email protected]3cd17242009-06-23 02:59:0214
15namespace net {
16
17// Every SOCKS server requests a user-id from the client. It is optional
18// and we send an empty string.
19static const char kEmptyUserId[] = "";
20
21// The SOCKS4a implementation suggests to use an invalid IP in case the DNS
22// resolution at client fails.
23static const uint8 kInvalidIp[] = { 0, 0, 0, 127 };
24
25// For SOCKS4, the client sends 8 bytes plus the size of the user-id.
26// For SOCKS4A, this increases to accomodate the unresolved hostname.
[email protected]76a51ac82009-06-28 07:58:5827static const unsigned int kWriteHeaderSize = 8;
[email protected]3cd17242009-06-23 02:59:0228
29// For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement.
[email protected]76a51ac82009-06-28 07:58:5830static const unsigned int kReadHeaderSize = 8;
[email protected]3cd17242009-06-23 02:59:0231
32// Server Response codes for SOCKS.
33static const uint8 kServerResponseOk = 0x5A;
34static const uint8 kServerResponseRejected = 0x5B;
35static const uint8 kServerResponseNotReachable = 0x5C;
36static const uint8 kServerResponseMismatchedUserId = 0x5D;
37
38static const uint8 kSOCKSVersion4 = 0x04;
39static const uint8 kSOCKSStreamRequest = 0x01;
40
41// A struct holding the essential details of the SOCKS4/4a Server Request.
42// The port in the header is stored in network byte order.
43struct SOCKS4ServerRequest {
44 uint8 version;
45 uint8 command;
46 uint16 nw_port;
47 uint8 ip[4];
48};
49COMPILE_ASSERT(sizeof(SOCKS4ServerRequest) == kWriteHeaderSize,
50 socks4_server_request_struct_wrong_size);
51
52// A struct holding details of the SOCKS4/4a Server Response.
53struct SOCKS4ServerResponse {
54 uint8 reserved_null;
55 uint8 code;
56 uint16 port;
57 uint8 ip[4];
58};
59COMPILE_ASSERT(sizeof(SOCKS4ServerResponse) == kReadHeaderSize,
60 socks4_server_response_struct_wrong_size);
61
62SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket,
63 const HostResolver::RequestInfo& req_info,
64 HostResolver* host_resolver)
65 : ALLOW_THIS_IN_INITIALIZER_LIST(
66 io_callback_(this, &SOCKSClientSocket::OnIOComplete)),
67 transport_(transport_socket),
68 next_state_(STATE_NONE),
69 socks_version_(kSOCKS4Unresolved),
70 user_callback_(NULL),
[email protected]3cd17242009-06-23 02:59:0271 completed_handshake_(false),
72 bytes_sent_(0),
73 bytes_received_(0),
[email protected]76a51ac82009-06-28 07:58:5874 host_resolver_(host_resolver),
[email protected]3cd17242009-06-23 02:59:0275 host_request_info_(req_info) {
76}
77
78SOCKSClientSocket::~SOCKSClientSocket() {
79 Disconnect();
80}
81
[email protected]5a05c47a2009-11-02 23:25:1982int SOCKSClientSocket::Connect(CompletionCallback* callback,
83 LoadLog* load_log) {
[email protected]3cd17242009-06-23 02:59:0284 DCHECK(transport_.get());
85 DCHECK(transport_->IsConnected());
86 DCHECK_EQ(STATE_NONE, next_state_);
87 DCHECK(!user_callback_);
88
89 // If already connected, then just return OK.
90 if (completed_handshake_)
91 return OK;
92
93 next_state_ = STATE_RESOLVE_HOST;
[email protected]5a05c47a2009-11-02 23:25:1994 load_log_ = load_log;
95
96 LoadLog::BeginEvent(load_log, LoadLog::TYPE_SOCKS_CONNECT);
[email protected]3cd17242009-06-23 02:59:0297
98 int rv = DoLoop(OK);
[email protected]5a05c47a2009-11-02 23:25:1999 if (rv == ERR_IO_PENDING) {
[email protected]3cd17242009-06-23 02:59:02100 user_callback_ = callback;
[email protected]5a05c47a2009-11-02 23:25:19101 } else {
102 LoadLog::EndEvent(load_log, LoadLog::TYPE_SOCKS_CONNECT);
103 load_log_ = NULL;
104 }
[email protected]3cd17242009-06-23 02:59:02105 return rv;
106}
107
108void SOCKSClientSocket::Disconnect() {
109 completed_handshake_ = false;
110 transport_->Disconnect();
111}
112
113bool SOCKSClientSocket::IsConnected() const {
114 return completed_handshake_ && transport_->IsConnected();
115}
116
117bool SOCKSClientSocket::IsConnectedAndIdle() const {
118 return completed_handshake_ && transport_->IsConnectedAndIdle();
119}
120
121// Read is called by the transport layer above to read. This can only be done
122// if the SOCKS handshake is complete.
123int SOCKSClientSocket::Read(IOBuffer* buf, int buf_len,
124 CompletionCallback* callback) {
125 DCHECK(completed_handshake_);
126 DCHECK_EQ(STATE_NONE, next_state_);
127 DCHECK(!user_callback_);
128
129 return transport_->Read(buf, buf_len, callback);
130}
131
132// Write is called by the transport layer. This can only be done if the
133// SOCKS handshake is complete.
134int SOCKSClientSocket::Write(IOBuffer* buf, int buf_len,
135 CompletionCallback* callback) {
136 DCHECK(completed_handshake_);
137 DCHECK_EQ(STATE_NONE, next_state_);
138 DCHECK(!user_callback_);
139
140 return transport_->Write(buf, buf_len, callback);
141}
142
[email protected]d3f66572009-09-09 22:38:04143bool SOCKSClientSocket::SetReceiveBufferSize(int32 size) {
144 return transport_->SetReceiveBufferSize(size);
145}
146
147bool SOCKSClientSocket::SetSendBufferSize(int32 size) {
148 return transport_->SetSendBufferSize(size);
149}
150
[email protected]3cd17242009-06-23 02:59:02151void SOCKSClientSocket::DoCallback(int result) {
152 DCHECK_NE(ERR_IO_PENDING, result);
153 DCHECK(user_callback_);
154
155 // Since Run() may result in Read being called,
156 // clear user_callback_ up front.
157 CompletionCallback* c = user_callback_;
158 user_callback_ = NULL;
159 DLOG(INFO) << "Finished setting up SOCKS handshake";
160 c->Run(result);
161}
162
163void SOCKSClientSocket::OnIOComplete(int result) {
164 DCHECK_NE(STATE_NONE, next_state_);
165 int rv = DoLoop(result);
[email protected]5a05c47a2009-11-02 23:25:19166 if (rv != ERR_IO_PENDING) {
167 LoadLog::EndEvent(load_log_, LoadLog::TYPE_SOCKS_CONNECT);
168 load_log_ = NULL;
[email protected]3cd17242009-06-23 02:59:02169 DoCallback(rv);
[email protected]5a05c47a2009-11-02 23:25:19170 }
[email protected]3cd17242009-06-23 02:59:02171}
172
173int SOCKSClientSocket::DoLoop(int last_io_result) {
174 DCHECK_NE(next_state_, STATE_NONE);
175 int rv = last_io_result;
176 do {
177 State state = next_state_;
178 next_state_ = STATE_NONE;
179 switch (state) {
180 case STATE_RESOLVE_HOST:
181 DCHECK_EQ(OK, rv);
182 rv = DoResolveHost();
183 break;
184 case STATE_RESOLVE_HOST_COMPLETE:
185 rv = DoResolveHostComplete(rv);
186 break;
187 case STATE_HANDSHAKE_WRITE:
188 DCHECK_EQ(OK, rv);
189 rv = DoHandshakeWrite();
190 break;
191 case STATE_HANDSHAKE_WRITE_COMPLETE:
192 rv = DoHandshakeWriteComplete(rv);
193 break;
194 case STATE_HANDSHAKE_READ:
195 DCHECK_EQ(OK, rv);
196 rv = DoHandshakeRead();
197 break;
198 case STATE_HANDSHAKE_READ_COMPLETE:
199 rv = DoHandshakeReadComplete(rv);
200 break;
201 default:
202 NOTREACHED() << "bad state";
203 rv = ERR_UNEXPECTED;
204 break;
205 }
206 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
207 return rv;
208}
209
210int SOCKSClientSocket::DoResolveHost() {
211 DCHECK_EQ(kSOCKS4Unresolved, socks_version_);
212
213 next_state_ = STATE_RESOLVE_HOST_COMPLETE;
[email protected]ec08bb22009-08-12 00:25:12214 return host_resolver_.Resolve(
[email protected]5a05c47a2009-11-02 23:25:19215 host_request_info_, &addresses_, &io_callback_, load_log_);
[email protected]3cd17242009-06-23 02:59:02216}
217
218int SOCKSClientSocket::DoResolveHostComplete(int result) {
219 DCHECK_EQ(kSOCKS4Unresolved, socks_version_);
220
221 bool ok = (result == OK);
222 next_state_ = STATE_HANDSHAKE_WRITE;
223 if (ok) {
224 DCHECK(addresses_.head());
225
226 // If the host is resolved to an IPv6 address, we revert to SOCKS4a
227 // since IPv6 is unsupported by SOCKS4/4a protocol.
228 struct sockaddr *host_info = addresses_.head()->ai_addr;
229 if (host_info->sa_family == AF_INET) {
230 DLOG(INFO) << "Resolved host. Using SOCKS4 to communicate";
231 socks_version_ = kSOCKS4;
232 } else {
233 DLOG(INFO) << "Resolved host but to IPv6. Using SOCKS4a to communicate";
234 socks_version_ = kSOCKS4a;
235 }
236 } else {
237 DLOG(INFO) << "Could not resolve host. Using SOCKS4a to communicate";
238 socks_version_ = kSOCKS4a;
239 }
240
241 // Even if DNS resolution fails, we send OK since the server
242 // resolves the domain.
243 return OK;
244}
245
246// Builds the buffer that is to be sent to the server.
247// We check whether the SOCKS proxy is 4 or 4A.
248// In case it is 4A, the record size increases by size of the hostname.
[email protected]76a51ac82009-06-28 07:58:58249const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const {
[email protected]3cd17242009-06-23 02:59:02250 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
251
[email protected]76a51ac82009-06-28 07:58:58252 SOCKS4ServerRequest request;
253 request.version = kSOCKSVersion4;
254 request.command = kSOCKSStreamRequest;
255 request.nw_port = htons(host_request_info_.port());
[email protected]3cd17242009-06-23 02:59:02256
257 if (socks_version_ == kSOCKS4) {
258 const struct addrinfo* ai = addresses_.head();
259 DCHECK(ai);
260 // If the sockaddr is IPv6, we have already marked the version to socks4a
261 // and so this step does not get hit.
[email protected]76a51ac82009-06-28 07:58:58262 struct sockaddr_in* ipv4_host =
[email protected]3cd17242009-06-23 02:59:02263 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr);
[email protected]76a51ac82009-06-28 07:58:58264 memcpy(&request.ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr));
[email protected]3cd17242009-06-23 02:59:02265
266 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai);
267 } else if (socks_version_ == kSOCKS4a) {
268 // invalid IP of the form 0.0.0.127
[email protected]76a51ac82009-06-28 07:58:58269 memcpy(&request.ip, kInvalidIp, arraysize(kInvalidIp));
[email protected]3cd17242009-06-23 02:59:02270 } else {
271 NOTREACHED();
272 }
273
[email protected]76a51ac82009-06-28 07:58:58274 std::string handshake_data(reinterpret_cast<char*>(&request),
275 sizeof(request));
276 handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId));
[email protected]3cd17242009-06-23 02:59:02277
[email protected]76a51ac82009-06-28 07:58:58278 // In case we are passing the domain also, pass the hostname
279 // terminated with a null character.
[email protected]3cd17242009-06-23 02:59:02280 if (socks_version_ == kSOCKS4a) {
[email protected]76a51ac82009-06-28 07:58:58281 handshake_data.append(host_request_info_.hostname());
282 handshake_data.push_back('\0');
[email protected]3cd17242009-06-23 02:59:02283 }
[email protected]76a51ac82009-06-28 07:58:58284
285 return handshake_data;
[email protected]3cd17242009-06-23 02:59:02286}
287
288// Writes the SOCKS handshake data to the underlying socket connection.
289int SOCKSClientSocket::DoHandshakeWrite() {
290 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
291
[email protected]76a51ac82009-06-28 07:58:58292 if (buffer_.empty()) {
293 buffer_ = BuildHandshakeWriteBuffer();
[email protected]3cd17242009-06-23 02:59:02294 bytes_sent_ = 0;
295 }
296
[email protected]76a51ac82009-06-28 07:58:58297 int handshake_buf_len = buffer_.size() - bytes_sent_;
298 DCHECK_GT(handshake_buf_len, 0);
299 handshake_buf_ = new IOBuffer(handshake_buf_len);
300 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
301 handshake_buf_len);
302 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_);
[email protected]3cd17242009-06-23 02:59:02303}
304
305int SOCKSClientSocket::DoHandshakeWriteComplete(int result) {
306 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
307
308 if (result < 0)
309 return result;
310
[email protected]76a51ac82009-06-28 07:58:58311 // We ignore the case when result is 0, since the underlying Write
312 // may return spurious writes while waiting on the socket.
313
[email protected]3cd17242009-06-23 02:59:02314 bytes_sent_ += result;
[email protected]76a51ac82009-06-28 07:58:58315 if (bytes_sent_ == buffer_.size()) {
[email protected]3cd17242009-06-23 02:59:02316 next_state_ = STATE_HANDSHAKE_READ;
[email protected]76a51ac82009-06-28 07:58:58317 buffer_.clear();
318 } else if (bytes_sent_ < buffer_.size()) {
[email protected]3cd17242009-06-23 02:59:02319 next_state_ = STATE_HANDSHAKE_WRITE;
320 } else {
321 return ERR_UNEXPECTED;
322 }
323
324 return OK;
325}
326
327int SOCKSClientSocket::DoHandshakeRead() {
328 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
329
330 next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
331
[email protected]76a51ac82009-06-28 07:58:58332 if (buffer_.empty()) {
[email protected]3cd17242009-06-23 02:59:02333 bytes_received_ = 0;
334 }
335
[email protected]76a51ac82009-06-28 07:58:58336 int handshake_buf_len = kReadHeaderSize - bytes_received_;
337 handshake_buf_ = new IOBuffer(handshake_buf_len);
338 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_);
[email protected]3cd17242009-06-23 02:59:02339}
340
341int SOCKSClientSocket::DoHandshakeReadComplete(int result) {
342 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
343
344 if (result < 0)
345 return result;
[email protected]76a51ac82009-06-28 07:58:58346
347 // The underlying socket closed unexpectedly.
348 if (result == 0)
349 return ERR_CONNECTION_CLOSED;
350
351 if (bytes_received_ + result > kReadHeaderSize)
[email protected]3cd17242009-06-23 02:59:02352 return ERR_INVALID_RESPONSE;
353
[email protected]76a51ac82009-06-28 07:58:58354 buffer_.append(handshake_buf_->data(), result);
[email protected]3cd17242009-06-23 02:59:02355 bytes_received_ += result;
[email protected]76a51ac82009-06-28 07:58:58356 if (bytes_received_ < kReadHeaderSize) {
[email protected]3cd17242009-06-23 02:59:02357 next_state_ = STATE_HANDSHAKE_READ;
358 return OK;
359 }
360
[email protected]76a51ac82009-06-28 07:58:58361 const SOCKS4ServerResponse* response =
362 reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data());
[email protected]3cd17242009-06-23 02:59:02363
364 if (response->reserved_null != 0x00) {
365 LOG(ERROR) << "Unknown response from SOCKS server.";
366 return ERR_INVALID_RESPONSE;
367 }
368
369 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h
370 switch (response->code) {
371 case kServerResponseOk:
372 completed_handshake_ = true;
373 return OK;
374 case kServerResponseRejected:
375 LOG(ERROR) << "SOCKS request rejected or failed";
376 return ERR_FAILED;
377 case kServerResponseNotReachable:
378 LOG(ERROR) << "SOCKS request failed because client is not running "
379 << "identd (or not reachable from the server)";
380 return ERR_NAME_NOT_RESOLVED;
381 case kServerResponseMismatchedUserId:
382 LOG(ERROR) << "SOCKS request failed because client's identd could "
383 << "not confirm the user ID string in the request";
384 return ERR_FAILED;
385 default:
386 LOG(ERROR) << "SOCKS server sent unknown response";
387 return ERR_INVALID_RESPONSE;
388 }
389
390 // Note: we ignore the last 6 bytes as specified by the SOCKS protocol
391}
392
393#if defined(OS_LINUX)
[email protected]773591e2009-07-08 18:23:41394int SOCKSClientSocket::GetPeerName(struct sockaddr* name,
395 socklen_t* namelen) {
396 return transport_->GetPeerName(name, namelen);
[email protected]3cd17242009-06-23 02:59:02397}
398#endif
399
400} // namespace net