OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/socks5_client_socket.h" | 5 #include "net/socket/socks5_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 "base/format_macros.h" | 9 #include "base/format_macros.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "base/trace_event.h" | 11 #include "base/trace_event.h" |
12 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
13 #include "net/base/net_log.h" | 13 #include "net/base/net_log.h" |
14 #include "net/base/net_util.h" | 14 #include "net/base/net_util.h" |
15 #include "net/base/sys_addrinfo.h" | 15 #include "net/base/sys_addrinfo.h" |
16 #include "net/socket/client_socket_handle.h" | 16 #include "net/socket/client_socket_handle.h" |
17 | 17 |
18 namespace net { | 18 namespace net { |
19 | 19 |
20 namespace { | |
21 | |
22 // Returns a string description of |socks_error|, or NULL if |socks_error| is | |
23 // not a valid SOCKS reply. | |
24 const char* MapSOCKSReplyToErrorString(char socks_error) { | |
25 switch(socks_error) { | |
26 case 1: return "(1) General SOCKS server failure"; | |
27 case 2: return "(2) Connection not allowed by ruleset"; | |
28 case 3: return "(3) Network unreachable"; | |
29 case 4: return "(4) Host unreachable"; | |
30 case 5: return "(5) Connection refused"; | |
31 case 6: return "(6) TTL expired"; | |
32 case 7: return "(7) Command not supported"; | |
33 case 8: return "(8) Address type not supported"; | |
34 default: return NULL; | |
35 } | |
36 } | |
37 | |
38 } // namespace | |
39 | |
40 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; | 20 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; |
41 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; | 21 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; |
42 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; | 22 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; |
43 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05; | 23 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05; |
44 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01; | 24 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01; |
45 const uint8 SOCKS5ClientSocket::kNullByte = 0x00; | 25 const uint8 SOCKS5ClientSocket::kNullByte = 0x00; |
46 | 26 |
47 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4); | 27 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4); |
48 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6); | 28 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6); |
49 | 29 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 return rv; | 209 return rv; |
230 } | 210 } |
231 | 211 |
232 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication | 212 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication |
233 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; | 213 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; |
234 | 214 |
235 int SOCKS5ClientSocket::DoGreetWrite() { | 215 int SOCKS5ClientSocket::DoGreetWrite() { |
236 // Since we only have 1 byte to send the hostname length in, if the | 216 // Since we only have 1 byte to send the hostname length in, if the |
237 // URL has a hostname longer than 255 characters we can't send it. | 217 // URL has a hostname longer than 255 characters we can't send it. |
238 if (0xFF < host_request_info_.hostname().size()) { | 218 if (0xFF < host_request_info_.hostname().size()) { |
239 net_log_.AddStringLiteral("Failed sending request because hostname is " | 219 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG); |
240 "longer than 255 characters"); | |
241 return ERR_SOCKS_CONNECTION_FAILED; | 220 return ERR_SOCKS_CONNECTION_FAILED; |
242 } | 221 } |
243 | 222 |
244 if (buffer_.empty()) { | 223 if (buffer_.empty()) { |
245 buffer_ = std::string(kSOCKS5GreetWriteData, | 224 buffer_ = std::string(kSOCKS5GreetWriteData, |
246 arraysize(kSOCKS5GreetWriteData)); | 225 arraysize(kSOCKS5GreetWriteData)); |
247 bytes_sent_ = 0; | 226 bytes_sent_ = 0; |
248 } | 227 } |
249 | 228 |
250 next_state_ = STATE_GREET_WRITE_COMPLETE; | 229 next_state_ = STATE_GREET_WRITE_COMPLETE; |
(...skipping 26 matching lines...) Expand all Loading... |
277 handshake_buf_ = new IOBuffer(handshake_buf_len); | 256 handshake_buf_ = new IOBuffer(handshake_buf_len); |
278 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, | 257 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, |
279 &io_callback_); | 258 &io_callback_); |
280 } | 259 } |
281 | 260 |
282 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { | 261 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { |
283 if (result < 0) | 262 if (result < 0) |
284 return result; | 263 return result; |
285 | 264 |
286 if (result == 0) { | 265 if (result == 0) { |
287 net_log_.AddStringLiteral( | 266 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); |
288 "Connection unexpected closed while reading greeting."); | |
289 return ERR_SOCKS_CONNECTION_FAILED; | 267 return ERR_SOCKS_CONNECTION_FAILED; |
290 } | 268 } |
291 | 269 |
292 bytes_received_ += result; | 270 bytes_received_ += result; |
293 buffer_.append(handshake_buf_->data(), result); | 271 buffer_.append(handshake_buf_->data(), result); |
294 if (bytes_received_ < kGreetReadHeaderSize) { | 272 if (bytes_received_ < kGreetReadHeaderSize) { |
295 next_state_ = STATE_GREET_READ; | 273 next_state_ = STATE_GREET_READ; |
296 return OK; | 274 return OK; |
297 } | 275 } |
298 | 276 |
299 // Got the greet data. | 277 // Got the greet data. |
300 if (buffer_[0] != kSOCKS5Version) { | 278 if (buffer_[0] != kSOCKS5Version) { |
301 net_log_.AddStringLiteral("Unexpected SOCKS version"); | 279 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, |
302 net_log_.AddString(StringPrintf( | 280 "version", buffer_[0]); |
303 "buffer_[0] = 0x%x", static_cast<int>(buffer_[0]))); | |
304 return ERR_SOCKS_CONNECTION_FAILED; | 281 return ERR_SOCKS_CONNECTION_FAILED; |
305 } | 282 } |
306 if (buffer_[1] != 0x00) { | 283 if (buffer_[1] != 0x00) { |
307 net_log_.AddStringLiteral("Unexpected authentication method"); | 284 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, |
308 net_log_.AddString(StringPrintf( | 285 "method", buffer_[1]); |
309 "buffer_[1] = 0x%x", static_cast<int>(buffer_[1]))); | |
310 return ERR_SOCKS_CONNECTION_FAILED; | 286 return ERR_SOCKS_CONNECTION_FAILED; |
311 } | 287 } |
312 | 288 |
313 buffer_.clear(); | 289 buffer_.clear(); |
314 next_state_ = STATE_HANDSHAKE_WRITE; | 290 next_state_ = STATE_HANDSHAKE_WRITE; |
315 return OK; | 291 return OK; |
316 } | 292 } |
317 | 293 |
318 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) | 294 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) |
319 const { | 295 const { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, | 366 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, |
391 &io_callback_); | 367 &io_callback_); |
392 } | 368 } |
393 | 369 |
394 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { | 370 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { |
395 if (result < 0) | 371 if (result < 0) |
396 return result; | 372 return result; |
397 | 373 |
398 // The underlying socket closed unexpectedly. | 374 // The underlying socket closed unexpectedly. |
399 if (result == 0) { | 375 if (result == 0) { |
400 net_log_.AddStringLiteral( | 376 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); |
401 "Connection unexpected closed while reading handshake."); | |
402 return ERR_SOCKS_CONNECTION_FAILED; | 377 return ERR_SOCKS_CONNECTION_FAILED; |
403 } | 378 } |
404 | 379 |
405 buffer_.append(handshake_buf_->data(), result); | 380 buffer_.append(handshake_buf_->data(), result); |
406 bytes_received_ += result; | 381 bytes_received_ += result; |
407 | 382 |
408 // When the first few bytes are read, check how many more are required | 383 // When the first few bytes are read, check how many more are required |
409 // and accordingly increase them | 384 // and accordingly increase them |
410 if (bytes_received_ == kReadHeaderSize) { | 385 if (bytes_received_ == kReadHeaderSize) { |
411 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { | 386 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { |
412 net_log_.AddStringLiteral("Unexpected SOCKS version."); | 387 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, |
413 net_log_.AddString(StringPrintf( | 388 "version", buffer_[0]); |
414 "buffer_[0] = 0x%x; buffer_[2] = 0x%x", | |
415 static_cast<int>(buffer_[0]), | |
416 static_cast<int>(buffer_[2]))); | |
417 return ERR_SOCKS_CONNECTION_FAILED; | 389 return ERR_SOCKS_CONNECTION_FAILED; |
418 } | 390 } |
419 if (buffer_[1] != 0x00) { | 391 if (buffer_[1] != 0x00) { |
420 net_log_.AddStringLiteral("SOCKS server returned a failure code:"); | 392 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_SERVER_ERROR, |
421 const char* error_string = MapSOCKSReplyToErrorString(buffer_[1]); | 393 "error_code", buffer_[1]); |
422 if (error_string) { | |
423 net_log_.AddStringLiteral(error_string); | |
424 } else { | |
425 net_log_.AddString(StringPrintf( | |
426 "buffer_[1] = 0x%x", static_cast<int>(buffer_[1]))); | |
427 } | |
428 return ERR_SOCKS_CONNECTION_FAILED; | 394 return ERR_SOCKS_CONNECTION_FAILED; |
429 } | 395 } |
430 | 396 |
431 // We check the type of IP/Domain the server returns and accordingly | 397 // We check the type of IP/Domain the server returns and accordingly |
432 // increase the size of the response. For domains, we need to read the | 398 // increase the size of the response. For domains, we need to read the |
433 // size of the domain, so the initial request size is upto the domain | 399 // size of the domain, so the initial request size is upto the domain |
434 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is | 400 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is |
435 // read, we substract 1 byte from the additional request size. | 401 // read, we substract 1 byte from the additional request size. |
436 SocksEndPointAddressType address_type = | 402 SocksEndPointAddressType address_type = |
437 static_cast<SocksEndPointAddressType>(buffer_[3]); | 403 static_cast<SocksEndPointAddressType>(buffer_[3]); |
438 if (address_type == kEndPointDomain) | 404 if (address_type == kEndPointDomain) |
439 read_header_size += static_cast<uint8>(buffer_[4]); | 405 read_header_size += static_cast<uint8>(buffer_[4]); |
440 else if (address_type == kEndPointResolvedIPv4) | 406 else if (address_type == kEndPointResolvedIPv4) |
441 read_header_size += sizeof(struct in_addr) - 1; | 407 read_header_size += sizeof(struct in_addr) - 1; |
442 else if (address_type == kEndPointResolvedIPv6) | 408 else if (address_type == kEndPointResolvedIPv6) |
443 read_header_size += sizeof(struct in6_addr) - 1; | 409 read_header_size += sizeof(struct in6_addr) - 1; |
444 else { | 410 else { |
445 net_log_.AddStringLiteral("Unknown address type in response"); | 411 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, |
446 net_log_.AddString(StringPrintf( | 412 "address_type", buffer_[3]); |
447 "buffer_[3] = 0x%x", static_cast<int>(buffer_[3]))); | |
448 return ERR_SOCKS_CONNECTION_FAILED; | 413 return ERR_SOCKS_CONNECTION_FAILED; |
449 } | 414 } |
450 | 415 |
451 read_header_size += 2; // for the port. | 416 read_header_size += 2; // for the port. |
452 next_state_ = STATE_HANDSHAKE_READ; | 417 next_state_ = STATE_HANDSHAKE_READ; |
453 return OK; | 418 return OK; |
454 } | 419 } |
455 | 420 |
456 // When the final bytes are read, setup handshake. We ignore the rest | 421 // When the final bytes are read, setup handshake. We ignore the rest |
457 // of the response since they represent the SOCKSv5 endpoint and have | 422 // of the response since they represent the SOCKSv5 endpoint and have |
458 // no use when doing a tunnel connection. | 423 // no use when doing a tunnel connection. |
459 if (bytes_received_ == read_header_size) { | 424 if (bytes_received_ == read_header_size) { |
460 completed_handshake_ = true; | 425 completed_handshake_ = true; |
461 buffer_.clear(); | 426 buffer_.clear(); |
462 next_state_ = STATE_NONE; | 427 next_state_ = STATE_NONE; |
463 return OK; | 428 return OK; |
464 } | 429 } |
465 | 430 |
466 next_state_ = STATE_HANDSHAKE_READ; | 431 next_state_ = STATE_HANDSHAKE_READ; |
467 return OK; | 432 return OK; |
468 } | 433 } |
469 | 434 |
470 int SOCKS5ClientSocket::GetPeerAddress(AddressList* address) const { | 435 int SOCKS5ClientSocket::GetPeerAddress(AddressList* address) const { |
471 return transport_->socket()->GetPeerAddress(address); | 436 return transport_->socket()->GetPeerAddress(address); |
472 } | 437 } |
473 | 438 |
474 } // namespace net | 439 } // namespace net |
OLD | NEW |