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

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

Issue 139009: Tests for socks4/4a implementation. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: scoped_refptr Created 11 years, 5 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) 2009 The Chromium Authors. All rights reserved. 1 // 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 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 "build/build_config.h" 8 #include "build/build_config.h"
9 #if defined(OS_WIN) 9 #if defined(OS_WIN)
10 #include <ws2tcpip.h> 10 #include <ws2tcpip.h>
(...skipping 10 matching lines...) Expand all
21 // Every SOCKS server requests a user-id from the client. It is optional 21 // Every SOCKS server requests a user-id from the client. It is optional
22 // and we send an empty string. 22 // and we send an empty string.
23 static const char kEmptyUserId[] = ""; 23 static const char kEmptyUserId[] = "";
24 24
25 // The SOCKS4a implementation suggests to use an invalid IP in case the DNS 25 // The SOCKS4a implementation suggests to use an invalid IP in case the DNS
26 // resolution at client fails. 26 // resolution at client fails.
27 static const uint8 kInvalidIp[] = { 0, 0, 0, 127 }; 27 static const uint8 kInvalidIp[] = { 0, 0, 0, 127 };
28 28
29 // For SOCKS4, the client sends 8 bytes plus the size of the user-id. 29 // For SOCKS4, the client sends 8 bytes plus the size of the user-id.
30 // For SOCKS4A, this increases to accomodate the unresolved hostname. 30 // For SOCKS4A, this increases to accomodate the unresolved hostname.
31 static const int kWriteHeaderSize = 8; 31 static const unsigned int kWriteHeaderSize = 8;
32 32
33 // For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement. 33 // For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement.
34 static const int kReadHeaderSize = 8; 34 static const unsigned int kReadHeaderSize = 8;
35 35
36 // Server Response codes for SOCKS. 36 // Server Response codes for SOCKS.
37 static const uint8 kServerResponseOk = 0x5A; 37 static const uint8 kServerResponseOk = 0x5A;
38 static const uint8 kServerResponseRejected = 0x5B; 38 static const uint8 kServerResponseRejected = 0x5B;
39 static const uint8 kServerResponseNotReachable = 0x5C; 39 static const uint8 kServerResponseNotReachable = 0x5C;
40 static const uint8 kServerResponseMismatchedUserId = 0x5D; 40 static const uint8 kServerResponseMismatchedUserId = 0x5D;
41 41
42 static const uint8 kSOCKSVersion4 = 0x04; 42 static const uint8 kSOCKSVersion4 = 0x04;
43 static const uint8 kSOCKSStreamRequest = 0x01; 43 static const uint8 kSOCKSStreamRequest = 0x01;
44 44
(...skipping 20 matching lines...) Expand all
65 65
66 SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket, 66 SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket,
67 const HostResolver::RequestInfo& req_info, 67 const HostResolver::RequestInfo& req_info,
68 HostResolver* host_resolver) 68 HostResolver* host_resolver)
69 : ALLOW_THIS_IN_INITIALIZER_LIST( 69 : ALLOW_THIS_IN_INITIALIZER_LIST(
70 io_callback_(this, &SOCKSClientSocket::OnIOComplete)), 70 io_callback_(this, &SOCKSClientSocket::OnIOComplete)),
71 transport_(transport_socket), 71 transport_(transport_socket),
72 next_state_(STATE_NONE), 72 next_state_(STATE_NONE),
73 socks_version_(kSOCKS4Unresolved), 73 socks_version_(kSOCKS4Unresolved),
74 user_callback_(NULL), 74 user_callback_(NULL),
75 handshake_buf_len_(0),
76 buffer_(NULL),
77 buffer_len_(0),
78 completed_handshake_(false), 75 completed_handshake_(false),
79 bytes_sent_(0), 76 bytes_sent_(0),
80 bytes_received_(0), 77 bytes_received_(0),
81 resolver_(host_resolver), 78 host_resolver_(host_resolver),
82 host_request_info_(req_info) { 79 host_request_info_(req_info) {
83 } 80 }
84 81
85 SOCKSClientSocket::~SOCKSClientSocket() { 82 SOCKSClientSocket::~SOCKSClientSocket() {
86 Disconnect(); 83 Disconnect();
87 } 84 }
88 85
89 int SOCKSClientSocket::Connect(CompletionCallback* callback) { 86 int SOCKSClientSocket::Connect(CompletionCallback* callback) {
90 DCHECK(transport_.get()); 87 DCHECK(transport_.get());
91 DCHECK(transport_->IsConnected()); 88 DCHECK(transport_->IsConnected());
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 break; 189 break;
193 } 190 }
194 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 191 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
195 return rv; 192 return rv;
196 } 193 }
197 194
198 int SOCKSClientSocket::DoResolveHost() { 195 int SOCKSClientSocket::DoResolveHost() {
199 DCHECK_EQ(kSOCKS4Unresolved, socks_version_); 196 DCHECK_EQ(kSOCKS4Unresolved, socks_version_);
200 197
201 next_state_ = STATE_RESOLVE_HOST_COMPLETE; 198 next_state_ = STATE_RESOLVE_HOST_COMPLETE;
202 return resolver_.Resolve(host_request_info_, &addresses_, &io_callback_); 199 return host_resolver_.Resolve(host_request_info_, &addresses_, &io_callback_);
203 } 200 }
204 201
205 int SOCKSClientSocket::DoResolveHostComplete(int result) { 202 int SOCKSClientSocket::DoResolveHostComplete(int result) {
206 DCHECK_EQ(kSOCKS4Unresolved, socks_version_); 203 DCHECK_EQ(kSOCKS4Unresolved, socks_version_);
207 204
208 bool ok = (result == OK); 205 bool ok = (result == OK);
209 next_state_ = STATE_HANDSHAKE_WRITE; 206 next_state_ = STATE_HANDSHAKE_WRITE;
210 if (ok) { 207 if (ok) {
211 DCHECK(addresses_.head()); 208 DCHECK(addresses_.head());
212 209
(...skipping 13 matching lines...) Expand all
226 } 223 }
227 224
228 // Even if DNS resolution fails, we send OK since the server 225 // Even if DNS resolution fails, we send OK since the server
229 // resolves the domain. 226 // resolves the domain.
230 return OK; 227 return OK;
231 } 228 }
232 229
233 // Builds the buffer that is to be sent to the server. 230 // Builds the buffer that is to be sent to the server.
234 // We check whether the SOCKS proxy is 4 or 4A. 231 // We check whether the SOCKS proxy is 4 or 4A.
235 // In case it is 4A, the record size increases by size of the hostname. 232 // In case it is 4A, the record size increases by size of the hostname.
236 void SOCKSClientSocket::BuildHandshakeWriteBuffer() { 233 const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const {
237 DCHECK_NE(kSOCKS4Unresolved, socks_version_); 234 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
238 235
239 int record_size = kWriteHeaderSize + arraysize(kEmptyUserId); 236 SOCKS4ServerRequest request;
240 if (socks_version_ == kSOCKS4a) { 237 request.version = kSOCKSVersion4;
241 record_size += host_request_info_.hostname().size() + 1; 238 request.command = kSOCKSStreamRequest;
242 } 239 request.nw_port = htons(host_request_info_.port());
243
244 buffer_len_ = record_size;
245 buffer_.reset(new char[buffer_len_]);
246
247 SOCKS4ServerRequest* request =
248 reinterpret_cast<SOCKS4ServerRequest*>(buffer_.get());
249
250 request->version = kSOCKSVersion4;
251 request->command = kSOCKSStreamRequest;
252 request->nw_port = htons(host_request_info_.port());
253 240
254 if (socks_version_ == kSOCKS4) { 241 if (socks_version_ == kSOCKS4) {
255 const struct addrinfo* ai = addresses_.head(); 242 const struct addrinfo* ai = addresses_.head();
256 DCHECK(ai); 243 DCHECK(ai);
257 // If the sockaddr is IPv6, we have already marked the version to socks4a 244 // If the sockaddr is IPv6, we have already marked the version to socks4a
258 // and so this step does not get hit. 245 // and so this step does not get hit.
259 struct sockaddr_in *ipv4_host = 246 struct sockaddr_in* ipv4_host =
260 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); 247 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr);
261 memcpy(&request->ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr)); 248 memcpy(&request.ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr));
262 249
263 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai); 250 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai);
264 } else if (socks_version_ == kSOCKS4a) { 251 } else if (socks_version_ == kSOCKS4a) {
265 // invalid IP of the form 0.0.0.127 252 // invalid IP of the form 0.0.0.127
266 memcpy(&request->ip, kInvalidIp, arraysize(kInvalidIp)); 253 memcpy(&request.ip, kInvalidIp, arraysize(kInvalidIp));
267 } else { 254 } else {
268 NOTREACHED(); 255 NOTREACHED();
269 } 256 }
270 257
271 memcpy(&buffer_[kWriteHeaderSize], kEmptyUserId, arraysize(kEmptyUserId)); 258 std::string handshake_data(reinterpret_cast<char*>(&request),
259 sizeof(request));
260 handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId));
272 261
262 // In case we are passing the domain also, pass the hostname
263 // terminated with a null character.
273 if (socks_version_ == kSOCKS4a) { 264 if (socks_version_ == kSOCKS4a) {
274 memcpy(&buffer_[kWriteHeaderSize + arraysize(kEmptyUserId)], 265 handshake_data.append(host_request_info_.hostname());
275 host_request_info_.hostname().c_str(), 266 handshake_data.push_back('\0');
276 host_request_info_.hostname().size() + 1);
277 } 267 }
268
269 return handshake_data;
278 } 270 }
279 271
280 // Writes the SOCKS handshake data to the underlying socket connection. 272 // Writes the SOCKS handshake data to the underlying socket connection.
281 int SOCKSClientSocket::DoHandshakeWrite() { 273 int SOCKSClientSocket::DoHandshakeWrite() {
282 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; 274 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
283 275
284 if (!buffer_.get()) { 276 if (buffer_.empty()) {
285 BuildHandshakeWriteBuffer(); 277 buffer_ = BuildHandshakeWriteBuffer();
286 bytes_sent_ = 0; 278 bytes_sent_ = 0;
287 } 279 }
288 280
289 handshake_buf_len_ = buffer_len_ - bytes_sent_; 281 int handshake_buf_len = buffer_.size() - bytes_sent_;
290 DCHECK_GT(handshake_buf_len_, 0); 282 DCHECK_GT(handshake_buf_len, 0);
291 handshake_buf_ = new IOBuffer(handshake_buf_len_); 283 handshake_buf_ = new IOBuffer(handshake_buf_len);
292 memcpy(handshake_buf_.get()->data(), &buffer_[bytes_sent_], 284 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
293 handshake_buf_len_); 285 handshake_buf_len);
294 return transport_->Write(handshake_buf_, handshake_buf_len_, &io_callback_); 286 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_);
295 } 287 }
296 288
297 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) { 289 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) {
298 DCHECK_NE(kSOCKS4Unresolved, socks_version_); 290 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
299 291
300 if (result < 0) 292 if (result < 0)
301 return result; 293 return result;
302 294
295 // We ignore the case when result is 0, since the underlying Write
296 // may return spurious writes while waiting on the socket.
297
303 bytes_sent_ += result; 298 bytes_sent_ += result;
304 if (bytes_sent_ == buffer_len_) { 299 if (bytes_sent_ == buffer_.size()) {
305 next_state_ = STATE_HANDSHAKE_READ; 300 next_state_ = STATE_HANDSHAKE_READ;
306 buffer_.reset(NULL); 301 buffer_.clear();
307 } else if (bytes_sent_ < buffer_len_) { 302 } else if (bytes_sent_ < buffer_.size()) {
308 next_state_ = STATE_HANDSHAKE_WRITE; 303 next_state_ = STATE_HANDSHAKE_WRITE;
309 } else { 304 } else {
310 return ERR_UNEXPECTED; 305 return ERR_UNEXPECTED;
311 } 306 }
312 307
313 return OK; 308 return OK;
314 } 309 }
315 310
316 int SOCKSClientSocket::DoHandshakeRead() { 311 int SOCKSClientSocket::DoHandshakeRead() {
317 DCHECK_NE(kSOCKS4Unresolved, socks_version_); 312 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
318 313
319 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; 314 next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
320 315
321 if (!buffer_.get()) { 316 if (buffer_.empty()) {
322 buffer_.reset(new char[kReadHeaderSize]);
323 buffer_len_ = kReadHeaderSize;
324 bytes_received_ = 0; 317 bytes_received_ = 0;
325 } 318 }
326 319
327 handshake_buf_len_ = buffer_len_ - bytes_received_; 320 int handshake_buf_len = kReadHeaderSize - bytes_received_;
328 handshake_buf_ = new IOBuffer(handshake_buf_len_); 321 handshake_buf_ = new IOBuffer(handshake_buf_len);
329 return transport_->Read(handshake_buf_, handshake_buf_len_, &io_callback_); 322 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_);
330 } 323 }
331 324
332 int SOCKSClientSocket::DoHandshakeReadComplete(int result) { 325 int SOCKSClientSocket::DoHandshakeReadComplete(int result) {
333 DCHECK_NE(kSOCKS4Unresolved, socks_version_); 326 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
334 327
335 if (result < 0) 328 if (result < 0)
336 return result; 329 return result;
337 if (bytes_received_ + result > buffer_len_) 330
331 // The underlying socket closed unexpectedly.
332 if (result == 0)
333 return ERR_CONNECTION_CLOSED;
334
335 if (bytes_received_ + result > kReadHeaderSize)
338 return ERR_INVALID_RESPONSE; 336 return ERR_INVALID_RESPONSE;
339 337
340 memcpy(buffer_.get() + bytes_received_, handshake_buf_->data(), result); 338 buffer_.append(handshake_buf_->data(), result);
341 bytes_received_ += result; 339 bytes_received_ += result;
342 if (bytes_received_ < buffer_len_) { 340 if (bytes_received_ < kReadHeaderSize) {
343 next_state_ = STATE_HANDSHAKE_READ; 341 next_state_ = STATE_HANDSHAKE_READ;
344 return OK; 342 return OK;
345 } 343 }
346 344
347 SOCKS4ServerResponse* response = 345 const SOCKS4ServerResponse* response =
348 reinterpret_cast<SOCKS4ServerResponse*>(buffer_.get()); 346 reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data());
349 347
350 if (response->reserved_null != 0x00) { 348 if (response->reserved_null != 0x00) {
351 LOG(ERROR) << "Unknown response from SOCKS server."; 349 LOG(ERROR) << "Unknown response from SOCKS server.";
352 return ERR_INVALID_RESPONSE; 350 return ERR_INVALID_RESPONSE;
353 } 351 }
354 352
355 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h 353 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h
356 switch (response->code) { 354 switch (response->code) {
357 case kServerResponseOk: 355 case kServerResponseOk:
358 completed_handshake_ = true; 356 completed_handshake_ = true;
(...skipping 22 matching lines...) Expand all
381 // Needed by ssl_client_socket_nss. 379 // Needed by ssl_client_socket_nss.
382 int SOCKSClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { 380 int SOCKSClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) {
383 // Default implementation just permits some unit tests to link. 381 // Default implementation just permits some unit tests to link.
384 NOTREACHED(); 382 NOTREACHED();
385 return ERR_UNEXPECTED; 383 return ERR_UNEXPECTED;
386 } 384 }
387 #endif 385 #endif
388 386
389 } // namespace net 387 } // namespace net
390 388
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