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