OLD | NEW |
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 Loading... |
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 unsigned int kWriteHeaderSize = 8; | 31 static const 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 unsigned int kReadHeaderSize = 8; | 34 static const 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 Loading... |
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), |
75 completed_handshake_(false), | 78 completed_handshake_(false), |
76 bytes_sent_(0), | 79 bytes_sent_(0), |
77 bytes_received_(0), | 80 bytes_received_(0), |
78 resolver_(host_resolver), | 81 resolver_(host_resolver), |
79 host_request_info_(req_info) { | 82 host_request_info_(req_info) { |
80 } | 83 } |
81 | 84 |
82 SOCKSClientSocket::~SOCKSClientSocket() { | 85 SOCKSClientSocket::~SOCKSClientSocket() { |
83 Disconnect(); | 86 Disconnect(); |
84 } | 87 } |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 } | 226 } |
224 | 227 |
225 // Even if DNS resolution fails, we send OK since the server | 228 // Even if DNS resolution fails, we send OK since the server |
226 // resolves the domain. | 229 // resolves the domain. |
227 return OK; | 230 return OK; |
228 } | 231 } |
229 | 232 |
230 // Builds the buffer that is to be sent to the server. | 233 // Builds the buffer that is to be sent to the server. |
231 // We check whether the SOCKS proxy is 4 or 4A. | 234 // We check whether the SOCKS proxy is 4 or 4A. |
232 // In case it is 4A, the record size increases by size of the hostname. | 235 // In case it is 4A, the record size increases by size of the hostname. |
233 const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const { | 236 void SOCKSClientSocket::BuildHandshakeWriteBuffer() { |
234 DCHECK_NE(kSOCKS4Unresolved, socks_version_); | 237 DCHECK_NE(kSOCKS4Unresolved, socks_version_); |
235 | 238 |
236 SOCKS4ServerRequest request; | 239 int record_size = kWriteHeaderSize + arraysize(kEmptyUserId); |
237 request.version = kSOCKSVersion4; | 240 if (socks_version_ == kSOCKS4a) { |
238 request.command = kSOCKSStreamRequest; | 241 record_size += host_request_info_.hostname().size() + 1; |
239 request.nw_port = htons(host_request_info_.port()); | 242 } |
| 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()); |
240 | 253 |
241 if (socks_version_ == kSOCKS4) { | 254 if (socks_version_ == kSOCKS4) { |
242 const struct addrinfo* ai = addresses_.head(); | 255 const struct addrinfo* ai = addresses_.head(); |
243 DCHECK(ai); | 256 DCHECK(ai); |
244 // If the sockaddr is IPv6, we have already marked the version to socks4a | 257 // If the sockaddr is IPv6, we have already marked the version to socks4a |
245 // and so this step does not get hit. | 258 // and so this step does not get hit. |
246 struct sockaddr_in* ipv4_host = | 259 struct sockaddr_in *ipv4_host = |
247 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); | 260 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); |
248 memcpy(&request.ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr)); | 261 memcpy(&request->ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr)); |
249 | 262 |
250 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai); | 263 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai); |
251 } else if (socks_version_ == kSOCKS4a) { | 264 } else if (socks_version_ == kSOCKS4a) { |
252 // invalid IP of the form 0.0.0.127 | 265 // invalid IP of the form 0.0.0.127 |
253 memcpy(&request.ip, kInvalidIp, arraysize(kInvalidIp)); | 266 memcpy(&request->ip, kInvalidIp, arraysize(kInvalidIp)); |
254 } else { | 267 } else { |
255 NOTREACHED(); | 268 NOTREACHED(); |
256 } | 269 } |
257 | 270 |
258 std::string handshake_data(reinterpret_cast<char*>(&request), | 271 memcpy(&buffer_[kWriteHeaderSize], kEmptyUserId, arraysize(kEmptyUserId)); |
259 sizeof(request)); | |
260 handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId)); | |
261 | 272 |
262 // In case we are passing the domain also, pass the hostname | |
263 // terminated with a null character. | |
264 if (socks_version_ == kSOCKS4a) { | 273 if (socks_version_ == kSOCKS4a) { |
265 handshake_data.append(host_request_info_.hostname()); | 274 memcpy(&buffer_[kWriteHeaderSize + arraysize(kEmptyUserId)], |
266 handshake_data.push_back('\0'); | 275 host_request_info_.hostname().c_str(), |
| 276 host_request_info_.hostname().size() + 1); |
267 } | 277 } |
268 | |
269 return handshake_data; | |
270 } | 278 } |
271 | 279 |
272 // Writes the SOCKS handshake data to the underlying socket connection. | 280 // Writes the SOCKS handshake data to the underlying socket connection. |
273 int SOCKSClientSocket::DoHandshakeWrite() { | 281 int SOCKSClientSocket::DoHandshakeWrite() { |
274 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; | 282 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; |
275 | 283 |
276 if (buffer_.empty()) { | 284 if (!buffer_.get()) { |
277 buffer_ = BuildHandshakeWriteBuffer(); | 285 BuildHandshakeWriteBuffer(); |
278 bytes_sent_ = 0; | 286 bytes_sent_ = 0; |
279 } | 287 } |
280 | 288 |
281 int handshake_buf_len = buffer_.size() - bytes_sent_; | 289 handshake_buf_len_ = buffer_len_ - bytes_sent_; |
282 DCHECK_GT(handshake_buf_len, 0); | 290 DCHECK_GT(handshake_buf_len_, 0); |
283 handshake_buf_ = new IOBuffer(handshake_buf_len); | 291 handshake_buf_ = new IOBuffer(handshake_buf_len_); |
284 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], | 292 memcpy(handshake_buf_.get()->data(), &buffer_[bytes_sent_], |
285 handshake_buf_len); | 293 handshake_buf_len_); |
286 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); | 294 return transport_->Write(handshake_buf_, handshake_buf_len_, &io_callback_); |
287 } | 295 } |
288 | 296 |
289 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) { | 297 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) { |
290 DCHECK_NE(kSOCKS4Unresolved, socks_version_); | 298 DCHECK_NE(kSOCKS4Unresolved, socks_version_); |
291 | 299 |
292 if (result < 0) | 300 if (result < 0) |
293 return result; | 301 return result; |
294 | 302 |
295 // We ignore the case when result is 0, since the underlying Write | |
296 // may return spurious writes while waiting on the socket. | |
297 | |
298 bytes_sent_ += result; | 303 bytes_sent_ += result; |
299 if (bytes_sent_ == buffer_.size()) { | 304 if (bytes_sent_ == buffer_len_) { |
300 next_state_ = STATE_HANDSHAKE_READ; | 305 next_state_ = STATE_HANDSHAKE_READ; |
301 buffer_.clear(); | 306 buffer_.reset(NULL); |
302 } else if (bytes_sent_ < buffer_.size()) { | 307 } else if (bytes_sent_ < buffer_len_) { |
303 next_state_ = STATE_HANDSHAKE_WRITE; | 308 next_state_ = STATE_HANDSHAKE_WRITE; |
304 } else { | 309 } else { |
305 return ERR_UNEXPECTED; | 310 return ERR_UNEXPECTED; |
306 } | 311 } |
307 | 312 |
308 return OK; | 313 return OK; |
309 } | 314 } |
310 | 315 |
311 int SOCKSClientSocket::DoHandshakeRead() { | 316 int SOCKSClientSocket::DoHandshakeRead() { |
312 DCHECK_NE(kSOCKS4Unresolved, socks_version_); | 317 DCHECK_NE(kSOCKS4Unresolved, socks_version_); |
313 | 318 |
314 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 319 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
315 | 320 |
316 if (buffer_.empty()) { | 321 if (!buffer_.get()) { |
| 322 buffer_.reset(new char[kReadHeaderSize]); |
| 323 buffer_len_ = kReadHeaderSize; |
317 bytes_received_ = 0; | 324 bytes_received_ = 0; |
318 } | 325 } |
319 | 326 |
320 int handshake_buf_len = kReadHeaderSize - bytes_received_; | 327 handshake_buf_len_ = buffer_len_ - bytes_received_; |
321 handshake_buf_ = new IOBuffer(handshake_buf_len); | 328 handshake_buf_ = new IOBuffer(handshake_buf_len_); |
322 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); | 329 return transport_->Read(handshake_buf_, handshake_buf_len_, &io_callback_); |
323 } | 330 } |
324 | 331 |
325 int SOCKSClientSocket::DoHandshakeReadComplete(int result) { | 332 int SOCKSClientSocket::DoHandshakeReadComplete(int result) { |
326 DCHECK_NE(kSOCKS4Unresolved, socks_version_); | 333 DCHECK_NE(kSOCKS4Unresolved, socks_version_); |
327 | 334 |
328 if (result < 0) | 335 if (result < 0) |
329 return result; | 336 return result; |
330 | 337 if (bytes_received_ + result > buffer_len_) |
331 // The underlying socket closed unexpectedly. | |
332 if (result == 0) | |
333 return ERR_CONNECTION_CLOSED; | |
334 | |
335 if (bytes_received_ + result > kReadHeaderSize) | |
336 return ERR_INVALID_RESPONSE; | 338 return ERR_INVALID_RESPONSE; |
337 | 339 |
338 buffer_.append(handshake_buf_->data(), result); | 340 memcpy(buffer_.get() + bytes_received_, handshake_buf_->data(), result); |
339 bytes_received_ += result; | 341 bytes_received_ += result; |
340 if (bytes_received_ < kReadHeaderSize) { | 342 if (bytes_received_ < buffer_len_) { |
341 next_state_ = STATE_HANDSHAKE_READ; | 343 next_state_ = STATE_HANDSHAKE_READ; |
342 return OK; | 344 return OK; |
343 } | 345 } |
344 | 346 |
345 const SOCKS4ServerResponse* response = | 347 SOCKS4ServerResponse* response = |
346 reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data()); | 348 reinterpret_cast<SOCKS4ServerResponse*>(buffer_.get()); |
347 | 349 |
348 if (response->reserved_null != 0x00) { | 350 if (response->reserved_null != 0x00) { |
349 LOG(ERROR) << "Unknown response from SOCKS server."; | 351 LOG(ERROR) << "Unknown response from SOCKS server."; |
350 return ERR_INVALID_RESPONSE; | 352 return ERR_INVALID_RESPONSE; |
351 } | 353 } |
352 | 354 |
353 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h | 355 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h |
354 switch (response->code) { | 356 switch (response->code) { |
355 case kServerResponseOk: | 357 case kServerResponseOk: |
356 completed_handshake_ = true; | 358 completed_handshake_ = true; |
(...skipping 22 matching lines...) Expand all Loading... |
379 // Needed by ssl_client_socket_nss. | 381 // Needed by ssl_client_socket_nss. |
380 int SOCKSClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { | 382 int SOCKSClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { |
381 // Default implementation just permits some unit tests to link. | 383 // Default implementation just permits some unit tests to link. |
382 NOTREACHED(); | 384 NOTREACHED(); |
383 return ERR_UNEXPECTED; | 385 return ERR_UNEXPECTED; |
384 } | 386 } |
385 #endif | 387 #endif |
386 | 388 |
387 } // namespace net | 389 } // namespace net |
388 | 390 |
OLD | NEW |