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