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