Home | History | Annotate | Download | only in socket
      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
      3 // found in the LICENSE file.
      4 
      5 #include "net/socket/socks5_client_socket.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/compiler_specific.h"
      9 #include "base/debug/trace_event.h"
     10 #include "base/format_macros.h"
     11 #include "base/string_util.h"
     12 #include "net/base/io_buffer.h"
     13 #include "net/base/net_log.h"
     14 #include "net/base/net_util.h"
     15 #include "net/base/sys_addrinfo.h"
     16 #include "net/socket/client_socket_handle.h"
     17 
     18 namespace net {
     19 
     20 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2;
     21 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10;
     22 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5;
     23 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05;
     24 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01;
     25 const uint8 SOCKS5ClientSocket::kNullByte = 0x00;
     26 
     27 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4);
     28 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6);
     29 
     30 SOCKS5ClientSocket::SOCKS5ClientSocket(
     31     ClientSocketHandle* transport_socket,
     32     const HostResolver::RequestInfo& req_info)
     33     : ALLOW_THIS_IN_INITIALIZER_LIST(
     34           io_callback_(this, &SOCKS5ClientSocket::OnIOComplete)),
     35       transport_(transport_socket),
     36       next_state_(STATE_NONE),
     37       user_callback_(NULL),
     38       completed_handshake_(false),
     39       bytes_sent_(0),
     40       bytes_received_(0),
     41       read_header_size(kReadHeaderSize),
     42       host_request_info_(req_info),
     43       net_log_(transport_socket->socket()->NetLog()) {
     44 }
     45 
     46 SOCKS5ClientSocket::SOCKS5ClientSocket(
     47     ClientSocket* transport_socket,
     48     const HostResolver::RequestInfo& req_info)
     49     : ALLOW_THIS_IN_INITIALIZER_LIST(
     50           io_callback_(this, &SOCKS5ClientSocket::OnIOComplete)),
     51       transport_(new ClientSocketHandle()),
     52       next_state_(STATE_NONE),
     53       user_callback_(NULL),
     54       completed_handshake_(false),
     55       bytes_sent_(0),
     56       bytes_received_(0),
     57       read_header_size(kReadHeaderSize),
     58       host_request_info_(req_info),
     59       net_log_(transport_socket->NetLog()) {
     60   transport_->set_socket(transport_socket);
     61 }
     62 
     63 SOCKS5ClientSocket::~SOCKS5ClientSocket() {
     64   Disconnect();
     65 }
     66 
     67 #ifdef ANDROID
     68 // TODO(kristianm): Find out if Connect should block
     69 #endif
     70 int SOCKS5ClientSocket::Connect(CompletionCallback* callback
     71 #ifdef ANDROID
     72                                 , bool wait_for_connect
     73                                 , bool valid_uid
     74                                 , uid_t calling_uid
     75 #endif
     76                                ) {
     77   DCHECK(transport_.get());
     78   DCHECK(transport_->socket());
     79   DCHECK_EQ(STATE_NONE, next_state_);
     80   DCHECK(!user_callback_);
     81 
     82   // If already connected, then just return OK.
     83   if (completed_handshake_)
     84     return OK;
     85 
     86   net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL);
     87 
     88   next_state_ = STATE_GREET_WRITE;
     89   buffer_.clear();
     90 
     91   int rv = DoLoop(OK);
     92   if (rv == ERR_IO_PENDING) {
     93     user_callback_ = callback;
     94   } else {
     95     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv);
     96   }
     97   return rv;
     98 }
     99 
    100 void SOCKS5ClientSocket::Disconnect() {
    101   completed_handshake_ = false;
    102   transport_->socket()->Disconnect();
    103 
    104   // Reset other states to make sure they aren't mistakenly used later.
    105   // These are the states initialized by Connect().
    106   next_state_ = STATE_NONE;
    107   user_callback_ = NULL;
    108 }
    109 
    110 bool SOCKS5ClientSocket::IsConnected() const {
    111   return completed_handshake_ && transport_->socket()->IsConnected();
    112 }
    113 
    114 bool SOCKS5ClientSocket::IsConnectedAndIdle() const {
    115   return completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
    116 }
    117 
    118 const BoundNetLog& SOCKS5ClientSocket::NetLog() const {
    119   return net_log_;
    120 }
    121 
    122 void SOCKS5ClientSocket::SetSubresourceSpeculation() {
    123   if (transport_.get() && transport_->socket()) {
    124     transport_->socket()->SetSubresourceSpeculation();
    125   } else {
    126     NOTREACHED();
    127   }
    128 }
    129 
    130 void SOCKS5ClientSocket::SetOmniboxSpeculation() {
    131   if (transport_.get() && transport_->socket()) {
    132     transport_->socket()->SetOmniboxSpeculation();
    133   } else {
    134     NOTREACHED();
    135   }
    136 }
    137 
    138 bool SOCKS5ClientSocket::WasEverUsed() const {
    139   if (transport_.get() && transport_->socket()) {
    140     return transport_->socket()->WasEverUsed();
    141   }
    142   NOTREACHED();
    143   return false;
    144 }
    145 
    146 bool SOCKS5ClientSocket::UsingTCPFastOpen() const {
    147   if (transport_.get() && transport_->socket()) {
    148     return transport_->socket()->UsingTCPFastOpen();
    149   }
    150   NOTREACHED();
    151   return false;
    152 }
    153 
    154 // Read is called by the transport layer above to read. This can only be done
    155 // if the SOCKS handshake is complete.
    156 int SOCKS5ClientSocket::Read(IOBuffer* buf, int buf_len,
    157                              CompletionCallback* callback) {
    158   DCHECK(completed_handshake_);
    159   DCHECK_EQ(STATE_NONE, next_state_);
    160   DCHECK(!user_callback_);
    161 
    162   return transport_->socket()->Read(buf, buf_len, callback);
    163 }
    164 
    165 // Write is called by the transport layer. This can only be done if the
    166 // SOCKS handshake is complete.
    167 int SOCKS5ClientSocket::Write(IOBuffer* buf, int buf_len,
    168                              CompletionCallback* callback) {
    169   DCHECK(completed_handshake_);
    170   DCHECK_EQ(STATE_NONE, next_state_);
    171   DCHECK(!user_callback_);
    172 
    173   return transport_->socket()->Write(buf, buf_len, callback);
    174 }
    175 
    176 bool SOCKS5ClientSocket::SetReceiveBufferSize(int32 size) {
    177   return transport_->socket()->SetReceiveBufferSize(size);
    178 }
    179 
    180 bool SOCKS5ClientSocket::SetSendBufferSize(int32 size) {
    181   return transport_->socket()->SetSendBufferSize(size);
    182 }
    183 
    184 void SOCKS5ClientSocket::DoCallback(int result) {
    185   DCHECK_NE(ERR_IO_PENDING, result);
    186   DCHECK(user_callback_);
    187 
    188   // Since Run() may result in Read being called,
    189   // clear user_callback_ up front.
    190   CompletionCallback* c = user_callback_;
    191   user_callback_ = NULL;
    192   c->Run(result);
    193 }
    194 
    195 void SOCKS5ClientSocket::OnIOComplete(int result) {
    196   DCHECK_NE(STATE_NONE, next_state_);
    197   int rv = DoLoop(result);
    198   if (rv != ERR_IO_PENDING) {
    199     net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL);
    200     DoCallback(rv);
    201   }
    202 }
    203 
    204 int SOCKS5ClientSocket::DoLoop(int last_io_result) {
    205   DCHECK_NE(next_state_, STATE_NONE);
    206   int rv = last_io_result;
    207   do {
    208     State state = next_state_;
    209     next_state_ = STATE_NONE;
    210     switch (state) {
    211       case STATE_GREET_WRITE:
    212         DCHECK_EQ(OK, rv);
    213         net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE, NULL);
    214         rv = DoGreetWrite();
    215         break;
    216       case STATE_GREET_WRITE_COMPLETE:
    217         rv = DoGreetWriteComplete(rv);
    218         net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv);
    219         break;
    220       case STATE_GREET_READ:
    221         DCHECK_EQ(OK, rv);
    222         net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ, NULL);
    223         rv = DoGreetRead();
    224         break;
    225       case STATE_GREET_READ_COMPLETE:
    226         rv = DoGreetReadComplete(rv);
    227         net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv);
    228         break;
    229       case STATE_HANDSHAKE_WRITE:
    230         DCHECK_EQ(OK, rv);
    231         net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, NULL);
    232         rv = DoHandshakeWrite();
    233         break;
    234       case STATE_HANDSHAKE_WRITE_COMPLETE:
    235         rv = DoHandshakeWriteComplete(rv);
    236         net_log_.EndEventWithNetErrorCode(
    237             NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv);
    238         break;
    239       case STATE_HANDSHAKE_READ:
    240         DCHECK_EQ(OK, rv);
    241         net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ, NULL);
    242         rv = DoHandshakeRead();
    243         break;
    244       case STATE_HANDSHAKE_READ_COMPLETE:
    245         rv = DoHandshakeReadComplete(rv);
    246         net_log_.EndEventWithNetErrorCode(
    247             NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv);
    248         break;
    249       default:
    250         NOTREACHED() << "bad state";
    251         rv = ERR_UNEXPECTED;
    252         break;
    253     }
    254   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    255   return rv;
    256 }
    257 
    258 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 };  // no authentication
    259 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 };
    260 
    261 int SOCKS5ClientSocket::DoGreetWrite() {
    262   // Since we only have 1 byte to send the hostname length in, if the
    263   // URL has a hostname longer than 255 characters we can't send it.
    264   if (0xFF < host_request_info_.hostname().size()) {
    265     net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG, NULL);
    266     return ERR_SOCKS_CONNECTION_FAILED;
    267   }
    268 
    269   if (buffer_.empty()) {
    270     buffer_ = std::string(kSOCKS5GreetWriteData,
    271                           arraysize(kSOCKS5GreetWriteData));
    272     bytes_sent_ = 0;
    273   }
    274 
    275   next_state_ = STATE_GREET_WRITE_COMPLETE;
    276   size_t handshake_buf_len = buffer_.size() - bytes_sent_;
    277   handshake_buf_ = new IOBuffer(handshake_buf_len);
    278   memcpy(handshake_buf_->data(), &buffer_.data()[bytes_sent_],
    279          handshake_buf_len);
    280   return transport_->socket()->Write(handshake_buf_, handshake_buf_len,
    281                                      &io_callback_);
    282 }
    283 
    284 int SOCKS5ClientSocket::DoGreetWriteComplete(int result) {
    285   if (result < 0)
    286     return result;
    287 
    288   bytes_sent_ += result;
    289   if (bytes_sent_ == buffer_.size()) {
    290     buffer_.clear();
    291     bytes_received_ = 0;
    292     next_state_ = STATE_GREET_READ;
    293   } else {
    294     next_state_ = STATE_GREET_WRITE;
    295   }
    296   return OK;
    297 }
    298 
    299 int SOCKS5ClientSocket::DoGreetRead() {
    300   next_state_ = STATE_GREET_READ_COMPLETE;
    301   size_t handshake_buf_len = kGreetReadHeaderSize - bytes_received_;
    302   handshake_buf_ = new IOBuffer(handshake_buf_len);
    303   return transport_->socket()->Read(handshake_buf_, handshake_buf_len,
    304                                     &io_callback_);
    305 }
    306 
    307 int SOCKS5ClientSocket::DoGreetReadComplete(int result) {
    308   if (result < 0)
    309     return result;
    310 
    311   if (result == 0) {
    312     net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING,
    313                       NULL);
    314     return ERR_SOCKS_CONNECTION_FAILED;
    315   }
    316 
    317   bytes_received_ += result;
    318   buffer_.append(handshake_buf_->data(), result);
    319   if (bytes_received_ < kGreetReadHeaderSize) {
    320     next_state_ = STATE_GREET_READ;
    321     return OK;
    322   }
    323 
    324   // Got the greet data.
    325   if (buffer_[0] != kSOCKS5Version) {
    326     net_log_.AddEvent(
    327         NetLog::TYPE_SOCKS_UNEXPECTED_VERSION,
    328         make_scoped_refptr(new NetLogIntegerParameter("version", buffer_[0])));
    329     return ERR_SOCKS_CONNECTION_FAILED;
    330   }
    331   if (buffer_[1] != 0x00) {
    332     net_log_.AddEvent(
    333         NetLog::TYPE_SOCKS_UNEXPECTED_AUTH,
    334         make_scoped_refptr(new NetLogIntegerParameter("method", buffer_[1])));
    335     return ERR_SOCKS_CONNECTION_FAILED;
    336   }
    337 
    338   buffer_.clear();
    339   next_state_ = STATE_HANDSHAKE_WRITE;
    340   return OK;
    341 }
    342 
    343 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake)
    344     const {
    345   DCHECK(handshake->empty());
    346 
    347   handshake->push_back(kSOCKS5Version);
    348   handshake->push_back(kTunnelCommand);  // Connect command
    349   handshake->push_back(kNullByte);  // Reserved null
    350 
    351   handshake->push_back(kEndPointDomain);  // The type of the address.
    352 
    353   DCHECK_GE(static_cast<size_t>(0xFF), host_request_info_.hostname().size());
    354 
    355   // First add the size of the hostname, followed by the hostname.
    356   handshake->push_back(static_cast<unsigned char>(
    357       host_request_info_.hostname().size()));
    358   handshake->append(host_request_info_.hostname());
    359 
    360   uint16 nw_port = htons(host_request_info_.port());
    361   handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port));
    362   return OK;
    363 }
    364 
    365 // Writes the SOCKS handshake data to the underlying socket connection.
    366 int SOCKS5ClientSocket::DoHandshakeWrite() {
    367   next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
    368 
    369   if (buffer_.empty()) {
    370     int rv = BuildHandshakeWriteBuffer(&buffer_);
    371     if (rv != OK)
    372       return rv;
    373     bytes_sent_ = 0;
    374   }
    375 
    376   int handshake_buf_len = buffer_.size() - bytes_sent_;
    377   DCHECK_LT(0, handshake_buf_len);
    378   handshake_buf_ = new IOBuffer(handshake_buf_len);
    379   memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
    380          handshake_buf_len);
    381   return transport_->socket()->Write(handshake_buf_, handshake_buf_len,
    382                                      &io_callback_);
    383 }
    384 
    385 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) {
    386   if (result < 0)
    387     return result;
    388 
    389   // We ignore the case when result is 0, since the underlying Write
    390   // may return spurious writes while waiting on the socket.
    391 
    392   bytes_sent_ += result;
    393   if (bytes_sent_ == buffer_.size()) {
    394     next_state_ = STATE_HANDSHAKE_READ;
    395     buffer_.clear();
    396   } else if (bytes_sent_ < buffer_.size()) {
    397     next_state_ = STATE_HANDSHAKE_WRITE;
    398   } else {
    399     NOTREACHED();
    400   }
    401 
    402   return OK;
    403 }
    404 
    405 int SOCKS5ClientSocket::DoHandshakeRead() {
    406   next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
    407 
    408   if (buffer_.empty()) {
    409     bytes_received_ = 0;
    410     read_header_size = kReadHeaderSize;
    411   }
    412 
    413   int handshake_buf_len = read_header_size - bytes_received_;
    414   handshake_buf_ = new IOBuffer(handshake_buf_len);
    415   return transport_->socket()->Read(handshake_buf_, handshake_buf_len,
    416                                     &io_callback_);
    417 }
    418 
    419 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) {
    420   if (result < 0)
    421     return result;
    422 
    423   // The underlying socket closed unexpectedly.
    424   if (result == 0) {
    425     net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE,
    426                       NULL);
    427     return ERR_SOCKS_CONNECTION_FAILED;
    428   }
    429 
    430   buffer_.append(handshake_buf_->data(), result);
    431   bytes_received_ += result;
    432 
    433   // When the first few bytes are read, check how many more are required
    434   // and accordingly increase them
    435   if (bytes_received_ == kReadHeaderSize) {
    436     if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) {
    437       net_log_.AddEvent(
    438           NetLog::TYPE_SOCKS_UNEXPECTED_VERSION,
    439           make_scoped_refptr(
    440               new NetLogIntegerParameter("version", buffer_[0])));
    441       return ERR_SOCKS_CONNECTION_FAILED;
    442     }
    443     if (buffer_[1] != 0x00) {
    444       net_log_.AddEvent(
    445           NetLog::TYPE_SOCKS_SERVER_ERROR,
    446           make_scoped_refptr(
    447               new NetLogIntegerParameter("error_code", buffer_[1])));
    448       return ERR_SOCKS_CONNECTION_FAILED;
    449     }
    450 
    451     // We check the type of IP/Domain the server returns and accordingly
    452     // increase the size of the response. For domains, we need to read the
    453     // size of the domain, so the initial request size is upto the domain
    454     // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is
    455     // read, we substract 1 byte from the additional request size.
    456     SocksEndPointAddressType address_type =
    457         static_cast<SocksEndPointAddressType>(buffer_[3]);
    458     if (address_type == kEndPointDomain)
    459       read_header_size += static_cast<uint8>(buffer_[4]);
    460     else if (address_type == kEndPointResolvedIPv4)
    461       read_header_size += sizeof(struct in_addr) - 1;
    462     else if (address_type == kEndPointResolvedIPv6)
    463       read_header_size += sizeof(struct in6_addr) - 1;
    464     else {
    465       net_log_.AddEvent(
    466           NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE,
    467           make_scoped_refptr(
    468               new NetLogIntegerParameter("address_type", buffer_[3])));
    469       return ERR_SOCKS_CONNECTION_FAILED;
    470     }
    471 
    472     read_header_size += 2;  // for the port.
    473     next_state_ = STATE_HANDSHAKE_READ;
    474     return OK;
    475   }
    476 
    477   // When the final bytes are read, setup handshake. We ignore the rest
    478   // of the response since they represent the SOCKSv5 endpoint and have
    479   // no use when doing a tunnel connection.
    480   if (bytes_received_ == read_header_size) {
    481     completed_handshake_ = true;
    482     buffer_.clear();
    483     next_state_ = STATE_NONE;
    484     return OK;
    485   }
    486 
    487   next_state_ = STATE_HANDSHAKE_READ;
    488   return OK;
    489 }
    490 
    491 int SOCKS5ClientSocket::GetPeerAddress(AddressList* address) const {
    492   return transport_->socket()->GetPeerAddress(address);
    493 }
    494 
    495 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const {
    496   return transport_->socket()->GetLocalAddress(address);
    497 }
    498 
    499 }  // namespace net
    500