Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: net/socket/socks_client_socket.cc

Issue 6719035: Remove the fallback from SOCKSv4 to SOCKSv4a. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: address wtc's comments Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket/socks_client_socket.h ('k') | net/socket/socks_client_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/socket/socks_client_socket.h" 5 #include "net/socket/socks_client_socket.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "net/base/io_buffer.h" 9 #include "net/base/io_buffer.h"
10 #include "net/base/net_log.h" 10 #include "net/base/net_log.h"
11 #include "net/base/net_util.h" 11 #include "net/base/net_util.h"
12 #include "net/base/sys_addrinfo.h" 12 #include "net/base/sys_addrinfo.h"
13 #include "net/socket/client_socket_handle.h" 13 #include "net/socket/client_socket_handle.h"
14 14
15 namespace net { 15 namespace net {
16 16
17 // Every SOCKS server requests a user-id from the client. It is optional 17 // Every SOCKS server requests a user-id from the client. It is optional
18 // and we send an empty string. 18 // and we send an empty string.
19 static const char kEmptyUserId[] = ""; 19 static const char kEmptyUserId[] = "";
20 20
21 // The SOCKS4a implementation suggests to use an invalid IP in case the DNS
22 // resolution at client fails.
23 static const uint8 kInvalidIp[] = { 0, 0, 0, 127 };
24
25 // For SOCKS4, the client sends 8 bytes plus the size of the user-id. 21 // For SOCKS4, the client sends 8 bytes plus the size of the user-id.
26 // For SOCKS4A, this increases to accomodate the unresolved hostname.
27 static const unsigned int kWriteHeaderSize = 8; 22 static const unsigned int kWriteHeaderSize = 8;
28 23
29 // For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement. 24 // For SOCKS4 the server sends 8 bytes for acknowledgement.
30 static const unsigned int kReadHeaderSize = 8; 25 static const unsigned int kReadHeaderSize = 8;
31 26
32 // Server Response codes for SOCKS. 27 // Server Response codes for SOCKS.
33 static const uint8 kServerResponseOk = 0x5A; 28 static const uint8 kServerResponseOk = 0x5A;
34 static const uint8 kServerResponseRejected = 0x5B; 29 static const uint8 kServerResponseRejected = 0x5B;
35 static const uint8 kServerResponseNotReachable = 0x5C; 30 static const uint8 kServerResponseNotReachable = 0x5C;
36 static const uint8 kServerResponseMismatchedUserId = 0x5D; 31 static const uint8 kServerResponseMismatchedUserId = 0x5D;
37 32
38 static const uint8 kSOCKSVersion4 = 0x04; 33 static const uint8 kSOCKSVersion4 = 0x04;
39 static const uint8 kSOCKSStreamRequest = 0x01; 34 static const uint8 kSOCKSStreamRequest = 0x01;
40 35
41 // A struct holding the essential details of the SOCKS4/4a Server Request. 36 // A struct holding the essential details of the SOCKS4 Server Request.
42 // The port in the header is stored in network byte order. 37 // The port in the header is stored in network byte order.
43 struct SOCKS4ServerRequest { 38 struct SOCKS4ServerRequest {
44 uint8 version; 39 uint8 version;
45 uint8 command; 40 uint8 command;
46 uint16 nw_port; 41 uint16 nw_port;
47 uint8 ip[4]; 42 uint8 ip[4];
48 }; 43 };
49 COMPILE_ASSERT(sizeof(SOCKS4ServerRequest) == kWriteHeaderSize, 44 COMPILE_ASSERT(sizeof(SOCKS4ServerRequest) == kWriteHeaderSize,
50 socks4_server_request_struct_wrong_size); 45 socks4_server_request_struct_wrong_size);
51 46
52 // A struct holding details of the SOCKS4/4a Server Response. 47 // A struct holding details of the SOCKS4 Server Response.
53 struct SOCKS4ServerResponse { 48 struct SOCKS4ServerResponse {
54 uint8 reserved_null; 49 uint8 reserved_null;
55 uint8 code; 50 uint8 code;
56 uint16 port; 51 uint16 port;
57 uint8 ip[4]; 52 uint8 ip[4];
58 }; 53 };
59 COMPILE_ASSERT(sizeof(SOCKS4ServerResponse) == kReadHeaderSize, 54 COMPILE_ASSERT(sizeof(SOCKS4ServerResponse) == kReadHeaderSize,
60 socks4_server_response_struct_wrong_size); 55 socks4_server_response_struct_wrong_size);
61 56
62 SOCKSClientSocket::SOCKSClientSocket(ClientSocketHandle* transport_socket, 57 SOCKSClientSocket::SOCKSClientSocket(ClientSocketHandle* transport_socket,
63 const HostResolver::RequestInfo& req_info, 58 const HostResolver::RequestInfo& req_info,
64 HostResolver* host_resolver) 59 HostResolver* host_resolver)
65 : ALLOW_THIS_IN_INITIALIZER_LIST( 60 : ALLOW_THIS_IN_INITIALIZER_LIST(
66 io_callback_(this, &SOCKSClientSocket::OnIOComplete)), 61 io_callback_(this, &SOCKSClientSocket::OnIOComplete)),
67 transport_(transport_socket), 62 transport_(transport_socket),
68 next_state_(STATE_NONE), 63 next_state_(STATE_NONE),
69 socks_version_(kSOCKS4Unresolved),
70 user_callback_(NULL), 64 user_callback_(NULL),
71 completed_handshake_(false), 65 completed_handshake_(false),
72 bytes_sent_(0), 66 bytes_sent_(0),
73 bytes_received_(0), 67 bytes_received_(0),
74 host_resolver_(host_resolver), 68 host_resolver_(host_resolver),
75 host_request_info_(req_info), 69 host_request_info_(req_info),
76 net_log_(transport_socket->socket()->NetLog()) { 70 net_log_(transport_socket->socket()->NetLog()) {
77 } 71 }
78 72
79 SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket, 73 SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket,
80 const HostResolver::RequestInfo& req_info, 74 const HostResolver::RequestInfo& req_info,
81 HostResolver* host_resolver) 75 HostResolver* host_resolver)
82 : ALLOW_THIS_IN_INITIALIZER_LIST( 76 : ALLOW_THIS_IN_INITIALIZER_LIST(
83 io_callback_(this, &SOCKSClientSocket::OnIOComplete)), 77 io_callback_(this, &SOCKSClientSocket::OnIOComplete)),
84 transport_(new ClientSocketHandle()), 78 transport_(new ClientSocketHandle()),
85 next_state_(STATE_NONE), 79 next_state_(STATE_NONE),
86 socks_version_(kSOCKS4Unresolved),
87 user_callback_(NULL), 80 user_callback_(NULL),
88 completed_handshake_(false), 81 completed_handshake_(false),
89 bytes_sent_(0), 82 bytes_sent_(0),
90 bytes_received_(0), 83 bytes_received_(0),
91 host_resolver_(host_resolver), 84 host_resolver_(host_resolver),
92 host_request_info_(req_info), 85 host_request_info_(req_info),
93 net_log_(transport_socket->NetLog()) { 86 net_log_(transport_socket->NetLog()) {
94 transport_->set_socket(transport_socket); 87 transport_->set_socket(transport_socket);
95 } 88 }
96 89
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 default: 252 default:
260 NOTREACHED() << "bad state"; 253 NOTREACHED() << "bad state";
261 rv = ERR_UNEXPECTED; 254 rv = ERR_UNEXPECTED;
262 break; 255 break;
263 } 256 }
264 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 257 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
265 return rv; 258 return rv;
266 } 259 }
267 260
268 int SOCKSClientSocket::DoResolveHost() { 261 int SOCKSClientSocket::DoResolveHost() {
269 DCHECK_EQ(kSOCKS4Unresolved, socks_version_);
270
271 next_state_ = STATE_RESOLVE_HOST_COMPLETE; 262 next_state_ = STATE_RESOLVE_HOST_COMPLETE;
263 // SOCKS4 only supports IPv4 addresses, so only try getting the IPv4
264 // addresses for the target host.
265 host_request_info_.set_address_family(ADDRESS_FAMILY_IPV4);
272 return host_resolver_.Resolve( 266 return host_resolver_.Resolve(
273 host_request_info_, &addresses_, &io_callback_, net_log_); 267 host_request_info_, &addresses_, &io_callback_, net_log_);
274 } 268 }
275 269
276 int SOCKSClientSocket::DoResolveHostComplete(int result) { 270 int SOCKSClientSocket::DoResolveHostComplete(int result) {
277 DCHECK_EQ(kSOCKS4Unresolved, socks_version_); 271 if (result != OK) {
278 272 // Resolving the hostname failed; fail the request rather than automatically
279 bool ok = (result == OK); 273 // falling back to SOCKS4a (since it can be confusing to see invalid IP
280 next_state_ = STATE_HANDSHAKE_WRITE; 274 // addresses being sent to the SOCKS4 server when it doesn't support 4A.)
281 if (ok) { 275 return result;
282 DCHECK(addresses_.head());
283
284 // If the host is resolved to an IPv6 address, we revert to SOCKS4a
285 // since IPv6 is unsupported by SOCKS4/4a protocol.
286 struct sockaddr *host_info = addresses_.head()->ai_addr;
287 if (host_info->sa_family == AF_INET) {
288 DVLOG(1) << "Resolved host. Using SOCKS4 to communicate";
289 socks_version_ = kSOCKS4;
290 } else {
291 DVLOG(1) << "Resolved host but to IPv6. Using SOCKS4a to communicate";
292 socks_version_ = kSOCKS4a;
293 }
294 } else {
295 DVLOG(1) << "Could not resolve host. Using SOCKS4a to communicate";
296 socks_version_ = kSOCKS4a;
297 } 276 }
298 277
299 // Even if DNS resolution fails, we send OK since the server 278 next_state_ = STATE_HANDSHAKE_WRITE;
300 // resolves the domain.
301 return OK; 279 return OK;
302 } 280 }
303 281
304 // Builds the buffer that is to be sent to the server. 282 // Builds the buffer that is to be sent to the server.
305 // We check whether the SOCKS proxy is 4 or 4A.
306 // In case it is 4A, the record size increases by size of the hostname.
307 const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const { 283 const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const {
308 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
309
310 SOCKS4ServerRequest request; 284 SOCKS4ServerRequest request;
311 request.version = kSOCKSVersion4; 285 request.version = kSOCKSVersion4;
312 request.command = kSOCKSStreamRequest; 286 request.command = kSOCKSStreamRequest;
313 request.nw_port = htons(host_request_info_.port()); 287 request.nw_port = htons(host_request_info_.port());
314 288
315 if (socks_version_ == kSOCKS4) { 289 const struct addrinfo* ai = addresses_.head();
316 const struct addrinfo* ai = addresses_.head(); 290 DCHECK(ai);
317 DCHECK(ai);
318 // If the sockaddr is IPv6, we have already marked the version to socks4a
319 // and so this step does not get hit.
320 struct sockaddr_in* ipv4_host =
321 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr);
322 memcpy(&request.ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr));
323 291
324 DVLOG(1) << "Resolved Host is : " << NetAddressToString(ai); 292 // We disabled IPv6 results when resolving the hostname, so none of the
325 } else if (socks_version_ == kSOCKS4a) { 293 // results in the list will be IPv6.
326 // invalid IP of the form 0.0.0.127 294 // TODO(eroman): we only ever use the first address in the list. It would be
327 memcpy(&request.ip, kInvalidIp, arraysize(kInvalidIp)); 295 // more robust to try all the IP addresses we have before
328 } else { 296 // failing the connect attempt.
329 NOTREACHED(); 297 CHECK_EQ(AF_INET, ai->ai_addr->sa_family);
330 } 298 struct sockaddr_in* ipv4_host =
299 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr);
300 memcpy(&request.ip, &ipv4_host->sin_addr, sizeof(ipv4_host->sin_addr));
301
302 DVLOG(1) << "Resolved Host is : " << NetAddressToString(ai);
331 303
332 std::string handshake_data(reinterpret_cast<char*>(&request), 304 std::string handshake_data(reinterpret_cast<char*>(&request),
333 sizeof(request)); 305 sizeof(request));
334 handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId)); 306 handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId));
335 307
336 // In case we are passing the domain also, pass the hostname
337 // terminated with a null character.
338 if (socks_version_ == kSOCKS4a) {
339 handshake_data.append(host_request_info_.hostname());
340 handshake_data.push_back('\0');
341 }
342
343 return handshake_data; 308 return handshake_data;
344 } 309 }
345 310
346 // Writes the SOCKS handshake data to the underlying socket connection. 311 // Writes the SOCKS handshake data to the underlying socket connection.
347 int SOCKSClientSocket::DoHandshakeWrite() { 312 int SOCKSClientSocket::DoHandshakeWrite() {
348 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; 313 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
349 314
350 if (buffer_.empty()) { 315 if (buffer_.empty()) {
351 buffer_ = BuildHandshakeWriteBuffer(); 316 buffer_ = BuildHandshakeWriteBuffer();
352 bytes_sent_ = 0; 317 bytes_sent_ = 0;
353 } 318 }
354 319
355 int handshake_buf_len = buffer_.size() - bytes_sent_; 320 int handshake_buf_len = buffer_.size() - bytes_sent_;
356 DCHECK_GT(handshake_buf_len, 0); 321 DCHECK_GT(handshake_buf_len, 0);
357 handshake_buf_ = new IOBuffer(handshake_buf_len); 322 handshake_buf_ = new IOBuffer(handshake_buf_len);
358 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], 323 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
359 handshake_buf_len); 324 handshake_buf_len);
360 return transport_->socket()->Write(handshake_buf_, handshake_buf_len, 325 return transport_->socket()->Write(handshake_buf_, handshake_buf_len,
361 &io_callback_); 326 &io_callback_);
362 } 327 }
363 328
364 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) { 329 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) {
365 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
366
367 if (result < 0) 330 if (result < 0)
368 return result; 331 return result;
369 332
370 // We ignore the case when result is 0, since the underlying Write 333 // We ignore the case when result is 0, since the underlying Write
371 // may return spurious writes while waiting on the socket. 334 // may return spurious writes while waiting on the socket.
372 335
373 bytes_sent_ += result; 336 bytes_sent_ += result;
374 if (bytes_sent_ == buffer_.size()) { 337 if (bytes_sent_ == buffer_.size()) {
375 next_state_ = STATE_HANDSHAKE_READ; 338 next_state_ = STATE_HANDSHAKE_READ;
376 buffer_.clear(); 339 buffer_.clear();
377 } else if (bytes_sent_ < buffer_.size()) { 340 } else if (bytes_sent_ < buffer_.size()) {
378 next_state_ = STATE_HANDSHAKE_WRITE; 341 next_state_ = STATE_HANDSHAKE_WRITE;
379 } else { 342 } else {
380 return ERR_UNEXPECTED; 343 return ERR_UNEXPECTED;
381 } 344 }
382 345
383 return OK; 346 return OK;
384 } 347 }
385 348
386 int SOCKSClientSocket::DoHandshakeRead() { 349 int SOCKSClientSocket::DoHandshakeRead() {
387 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
388
389 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; 350 next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
390 351
391 if (buffer_.empty()) { 352 if (buffer_.empty()) {
392 bytes_received_ = 0; 353 bytes_received_ = 0;
393 } 354 }
394 355
395 int handshake_buf_len = kReadHeaderSize - bytes_received_; 356 int handshake_buf_len = kReadHeaderSize - bytes_received_;
396 handshake_buf_ = new IOBuffer(handshake_buf_len); 357 handshake_buf_ = new IOBuffer(handshake_buf_len);
397 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, 358 return transport_->socket()->Read(handshake_buf_, handshake_buf_len,
398 &io_callback_); 359 &io_callback_);
399 } 360 }
400 361
401 int SOCKSClientSocket::DoHandshakeReadComplete(int result) { 362 int SOCKSClientSocket::DoHandshakeReadComplete(int result) {
402 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
403
404 if (result < 0) 363 if (result < 0)
405 return result; 364 return result;
406 365
407 // The underlying socket closed unexpectedly. 366 // The underlying socket closed unexpectedly.
408 if (result == 0) 367 if (result == 0)
409 return ERR_CONNECTION_CLOSED; 368 return ERR_CONNECTION_CLOSED;
410 369
411 if (bytes_received_ + result > kReadHeaderSize) { 370 if (bytes_received_ + result > kReadHeaderSize) {
412 // TODO(eroman): Describe failure in NetLog. 371 // TODO(eroman): Describe failure in NetLog.
413 return ERR_SOCKS_CONNECTION_FAILED; 372 return ERR_SOCKS_CONNECTION_FAILED;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 } 408 }
450 409
451 // Note: we ignore the last 6 bytes as specified by the SOCKS protocol 410 // Note: we ignore the last 6 bytes as specified by the SOCKS protocol
452 } 411 }
453 412
454 int SOCKSClientSocket::GetPeerAddress(AddressList* address) const { 413 int SOCKSClientSocket::GetPeerAddress(AddressList* address) const {
455 return transport_->socket()->GetPeerAddress(address); 414 return transport_->socket()->GetPeerAddress(address);
456 } 415 }
457 416
458 } // namespace net 417 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/socks_client_socket.h ('k') | net/socket/socks_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698