1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/socks_client_socket.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/trace_event.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/load_log.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_util.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/sys_addrinfo.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Every SOCKS server requests a user-id from the client. It is optional 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and we send an empty string. 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char kEmptyUserId[] = ""; 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The SOCKS4a implementation suggests to use an invalid IP in case the DNS 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// resolution at client fails. 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kInvalidIp[] = { 0, 0, 0, 127 }; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// For SOCKS4, the client sends 8 bytes plus the size of the user-id. 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// For SOCKS4A, this increases to accomodate the unresolved hostname. 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const unsigned int kWriteHeaderSize = 8; 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement. 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const unsigned int kReadHeaderSize = 8; 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Server Response codes for SOCKS. 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kServerResponseOk = 0x5A; 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kServerResponseRejected = 0x5B; 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kServerResponseNotReachable = 0x5C; 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kServerResponseMismatchedUserId = 0x5D; 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kSOCKSVersion4 = 0x04; 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kSOCKSStreamRequest = 0x01; 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A struct holding the essential details of the SOCKS4/4a Server Request. 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The port in the header is stored in network byte order. 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct SOCKS4ServerRequest { 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 version; 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 command; 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16 nw_port; 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 ip[4]; 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(sizeof(SOCKS4ServerRequest) == kWriteHeaderSize, 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socks4_server_request_struct_wrong_size); 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A struct holding details of the SOCKS4/4a Server Response. 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct SOCKS4ServerResponse { 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 reserved_null; 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 code; 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16 port; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 ip[4]; 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(sizeof(SOCKS4ServerResponse) == kReadHeaderSize, 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socks4_server_response_struct_wrong_size); 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket, 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HostResolver::RequestInfo& req_info, 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HostResolver* host_resolver) 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : ALLOW_THIS_IN_INITIALIZER_LIST( 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_callback_(this, &SOCKSClientSocket::OnIOComplete)), 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_(transport_socket), 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_(STATE_NONE), 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socks_version_(kSOCKS4Unresolved), 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_(NULL), 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott completed_handshake_(false), 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent_(0), 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_received_(0), 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_resolver_(host_resolver), 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_request_info_(req_info) { 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSOCKSClientSocket::~SOCKSClientSocket() { 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Disconnect(); 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::Connect(CompletionCallback* callback, 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LoadLog* load_log) { 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(transport_.get()); 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(transport_->IsConnected()); 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(STATE_NONE, next_state_); 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If already connected, then just return OK. 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (completed_handshake_) 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_RESOLVE_HOST; 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott load_log_ = load_log; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LoadLog::BeginEvent(load_log, LoadLog::TYPE_SOCKS_CONNECT); 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoLoop(OK); 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == ERR_IO_PENDING) { 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LoadLog::EndEvent(load_log, LoadLog::TYPE_SOCKS_CONNECT); 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott load_log_ = NULL; 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SOCKSClientSocket::Disconnect() { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott completed_handshake_ = false; 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_resolver_.Cancel(); 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_->Disconnect(); 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reset other states to make sure they aren't mistakenly used later. 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // These are the states initialized by Connect(). 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_NONE; 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = NULL; 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott load_log_ = NULL; 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SOCKSClientSocket::IsConnected() const { 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return completed_handshake_ && transport_->IsConnected(); 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SOCKSClientSocket::IsConnectedAndIdle() const { 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return completed_handshake_ && transport_->IsConnectedAndIdle(); 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Read is called by the transport layer above to read. This can only be done 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// if the SOCKS handshake is complete. 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::Read(IOBuffer* buf, int buf_len, 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(completed_handshake_); 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(STATE_NONE, next_state_); 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transport_->Read(buf, buf_len, callback); 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Write is called by the transport layer. This can only be done if the 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SOCKS handshake is complete. 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::Write(IOBuffer* buf, int buf_len, 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(completed_handshake_); 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(STATE_NONE, next_state_); 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transport_->Write(buf, buf_len, callback); 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SOCKSClientSocket::SetReceiveBufferSize(int32 size) { 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transport_->SetReceiveBufferSize(size); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SOCKSClientSocket::SetSendBufferSize(int32 size) { 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transport_->SetSendBufferSize(size); 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SOCKSClientSocket::DoCallback(int result) { 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(ERR_IO_PENDING, result); 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(user_callback_); 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Since Run() may result in Read being called, 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // clear user_callback_ up front. 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = user_callback_; 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = NULL; 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(INFO) << "Finished setting up SOCKS handshake"; 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(result); 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SOCKSClientSocket::OnIOComplete(int result) { 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(STATE_NONE, next_state_); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoLoop(result); 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != ERR_IO_PENDING) { 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LoadLog::EndEvent(load_log_, LoadLog::TYPE_SOCKS_CONNECT); 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott load_log_ = NULL; 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoCallback(rv); 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoLoop(int last_io_result) { 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(next_state_, STATE_NONE); 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = last_io_result; 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott State state = next_state_; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_NONE; 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (state) { 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_RESOLVE_HOST: 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, rv); 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoResolveHost(); 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_RESOLVE_HOST_COMPLETE: 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoResolveHostComplete(rv); 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE_WRITE: 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, rv); 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeWrite(); 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE_WRITE_COMPLETE: 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeWriteComplete(rv); 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE_READ: 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, rv); 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeRead(); 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE_READ_COMPLETE: 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeReadComplete(rv); 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "bad state"; 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = ERR_UNEXPECTED; 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoResolveHost() { 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(kSOCKS4Unresolved, socks_version_); 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_RESOLVE_HOST_COMPLETE; 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return host_resolver_.Resolve( 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_request_info_, &addresses_, &io_callback_, load_log_); 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoResolveHostComplete(int result) { 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(kSOCKS4Unresolved, socks_version_); 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool ok = (result == OK); 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_WRITE; 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ok) { 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(addresses_.head()); 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the host is resolved to an IPv6 address, we revert to SOCKS4a 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // since IPv6 is unsupported by SOCKS4/4a protocol. 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct sockaddr *host_info = addresses_.head()->ai_addr; 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (host_info->sa_family == AF_INET) { 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(INFO) << "Resolved host. Using SOCKS4 to communicate"; 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socks_version_ = kSOCKS4; 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(INFO) << "Resolved host but to IPv6. Using SOCKS4a to communicate"; 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socks_version_ = kSOCKS4a; 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(INFO) << "Could not resolve host. Using SOCKS4a to communicate"; 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socks_version_ = kSOCKS4a; 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Even if DNS resolution fails, we send OK since the server 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // resolves the domain. 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Builds the buffer that is to be sent to the server. 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We check whether the SOCKS proxy is 4 or 4A. 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// In case it is 4A, the record size increases by size of the hostname. 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const { 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(kSOCKS4Unresolved, socks_version_); 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SOCKS4ServerRequest request; 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request.version = kSOCKSVersion4; 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request.command = kSOCKSStreamRequest; 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request.nw_port = htons(host_request_info_.port()); 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (socks_version_ == kSOCKS4) { 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const struct addrinfo* ai = addresses_.head(); 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(ai); 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the sockaddr is IPv6, we have already marked the version to socks4a 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // and so this step does not get hit. 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct sockaddr_in* ipv4_host = 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(&request.ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr)); 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai); 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (socks_version_ == kSOCKS4a) { 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // invalid IP of the form 0.0.0.127 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(&request.ip, kInvalidIp, arraysize(kInvalidIp)); 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string handshake_data(reinterpret_cast<char*>(&request), 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(request)); 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId)); 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In case we are passing the domain also, pass the hostname 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // terminated with a null character. 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (socks_version_ == kSOCKS4a) { 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_data.append(host_request_info_.hostname()); 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_data.push_back('\0'); 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return handshake_data; 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Writes the SOCKS handshake data to the underlying socket connection. 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoHandshakeWrite() { 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (buffer_.empty()) { 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_ = BuildHandshakeWriteBuffer(); 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent_ = 0; 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int handshake_buf_len = buffer_.size() - bytes_sent_; 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GT(handshake_buf_len, 0); 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_buf_ = new IOBuffer(handshake_buf_len); 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_buf_len); 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoHandshakeWriteComplete(int result) { 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(kSOCKS4Unresolved, socks_version_); 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We ignore the case when result is 0, since the underlying Write 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // may return spurious writes while waiting on the socket. 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent_ += result; 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_sent_ == buffer_.size()) { 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_READ; 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_.clear(); 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (bytes_sent_ < buffer_.size()) { 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_WRITE; 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoHandshakeRead() { 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(kSOCKS4Unresolved, socks_version_); 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_READ_COMPLETE; 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (buffer_.empty()) { 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_received_ = 0; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int handshake_buf_len = kReadHeaderSize - bytes_received_; 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_buf_ = new IOBuffer(handshake_buf_len); 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoHandshakeReadComplete(int result) { 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(kSOCKS4Unresolved, socks_version_); 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The underlying socket closed unexpectedly. 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == 0) 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_CLOSED; 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_received_ + result > kReadHeaderSize) 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_INVALID_RESPONSE; 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_.append(handshake_buf_->data(), result); 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_received_ += result; 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_received_ < kReadHeaderSize) { 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_READ; 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const SOCKS4ServerResponse* response = 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data()); 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response->reserved_null != 0x00) { 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Unknown response from SOCKS server."; 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_INVALID_RESPONSE; 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (response->code) { 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kServerResponseOk: 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott completed_handshake_ = true; 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kServerResponseRejected: 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "SOCKS request rejected or failed"; 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_FAILED; 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kServerResponseNotReachable: 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "SOCKS request failed because client is not running " 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "identd (or not reachable from the server)"; 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_NAME_NOT_RESOLVED; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kServerResponseMismatchedUserId: 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "SOCKS request failed because client's identd could " 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "not confirm the user ID string in the request"; 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_FAILED; 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "SOCKS server sent unknown response"; 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_INVALID_RESPONSE; 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: we ignore the last 6 bytes as specified by the SOCKS protocol 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::GetPeerName(struct sockaddr* name, 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socklen_t* namelen) { 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transport_->GetPeerName(name, namelen); 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 406