OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/socket/socks_client_socket.h" | 5 #include "net/socket/socks_client_socket.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
9 #if defined(OS_WIN) | 9 #if defined(OS_WIN) |
10 #include <ws2tcpip.h> | 10 #include <ws2tcpip.h> |
(...skipping 10 matching lines...) Expand all Loading... |
21 // Every SOCKS server requests a user-id from the client. It is optional | 21 // Every SOCKS server requests a user-id from the client. It is optional |
22 // and we send an empty string. | 22 // and we send an empty string. |
23 static const char kEmptyUserId[] = ""; | 23 static const char kEmptyUserId[] = ""; |
24 | 24 |
25 // The SOCKS4a implementation suggests to use an invalid IP in case the DNS | 25 // The SOCKS4a implementation suggests to use an invalid IP in case the DNS |
26 // resolution at client fails. | 26 // resolution at client fails. |
27 static const uint8 kInvalidIp[] = { 0, 0, 0, 127 }; | 27 static const uint8 kInvalidIp[] = { 0, 0, 0, 127 }; |
28 | 28 |
29 // For SOCKS4, the client sends 8 bytes plus the size of the user-id. | 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. | 30 // For SOCKS4A, this increases to accomodate the unresolved hostname. |
31 static const int kWriteHeaderSize = 8; | 31 static const unsigned int kWriteHeaderSize = 8; |
32 | 32 |
33 // For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement. | 33 // For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement. |
34 static const int kReadHeaderSize = 8; | 34 static const unsigned int kReadHeaderSize = 8; |
35 | 35 |
36 // Server Response codes for SOCKS. | 36 // Server Response codes for SOCKS. |
37 static const uint8 kServerResponseOk = 0x5A; | 37 static const uint8 kServerResponseOk = 0x5A; |
38 static const uint8 kServerResponseRejected = 0x5B; | 38 static const uint8 kServerResponseRejected = 0x5B; |
39 static const uint8 kServerResponseNotReachable = 0x5C; | 39 static const uint8 kServerResponseNotReachable = 0x5C; |
40 static const uint8 kServerResponseMismatchedUserId = 0x5D; | 40 static const uint8 kServerResponseMismatchedUserId = 0x5D; |
41 | 41 |
42 static const uint8 kSOCKSVersion4 = 0x04; | 42 static const uint8 kSOCKSVersion4 = 0x04; |
43 static const uint8 kSOCKSStreamRequest = 0x01; | 43 static const uint8 kSOCKSStreamRequest = 0x01; |
44 | 44 |
(...skipping 20 matching lines...) Expand all Loading... |
65 | 65 |
66 SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket, | 66 SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket, |
67 const HostResolver::RequestInfo& req_info, | 67 const HostResolver::RequestInfo& req_info, |
68 HostResolver* host_resolver) | 68 HostResolver* host_resolver) |
69 : ALLOW_THIS_IN_INITIALIZER_LIST( | 69 : ALLOW_THIS_IN_INITIALIZER_LIST( |
70 io_callback_(this, &SOCKSClientSocket::OnIOComplete)), | 70 io_callback_(this, &SOCKSClientSocket::OnIOComplete)), |
71 transport_(transport_socket), | 71 transport_(transport_socket), |
72 next_state_(STATE_NONE), | 72 next_state_(STATE_NONE), |
73 socks_version_(kSOCKS4Unresolved), | 73 socks_version_(kSOCKS4Unresolved), |
74 user_callback_(NULL), | 74 user_callback_(NULL), |
75 handshake_buf_len_(0), | |
76 buffer_(NULL), | |
77 buffer_len_(0), | |
78 completed_handshake_(false), | 75 completed_handshake_(false), |
79 bytes_sent_(0), | 76 bytes_sent_(0), |
80 bytes_received_(0), | 77 bytes_received_(0), |
81 resolver_(host_resolver), | 78 host_resolver_(host_resolver), |
82 host_request_info_(req_info) { | 79 host_request_info_(req_info) { |
83 } | 80 } |
84 | 81 |
85 SOCKSClientSocket::~SOCKSClientSocket() { | 82 SOCKSClientSocket::~SOCKSClientSocket() { |
86 Disconnect(); | 83 Disconnect(); |
87 } | 84 } |
88 | 85 |
89 int SOCKSClientSocket::Connect(CompletionCallback* callback) { | 86 int SOCKSClientSocket::Connect(CompletionCallback* callback) { |
90 DCHECK(transport_.get()); | 87 DCHECK(transport_.get()); |
91 DCHECK(transport_->IsConnected()); | 88 DCHECK(transport_->IsConnected()); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 break; | 189 break; |
193 } | 190 } |
194 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 191 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
195 return rv; | 192 return rv; |
196 } | 193 } |
197 | 194 |
198 int SOCKSClientSocket::DoResolveHost() { | 195 int SOCKSClientSocket::DoResolveHost() { |
199 DCHECK_EQ(kSOCKS4Unresolved, socks_version_); | 196 DCHECK_EQ(kSOCKS4Unresolved, socks_version_); |
200 | 197 |
201 next_state_ = STATE_RESOLVE_HOST_COMPLETE; | 198 next_state_ = STATE_RESOLVE_HOST_COMPLETE; |
202 return resolver_.Resolve(host_request_info_, &addresses_, &io_callback_); | 199 return host_resolver_.Resolve(host_request_info_, &addresses_, &io_callback_); |
203 } | 200 } |
204 | 201 |
205 int SOCKSClientSocket::DoResolveHostComplete(int result) { | 202 int SOCKSClientSocket::DoResolveHostComplete(int result) { |
206 DCHECK_EQ(kSOCKS4Unresolved, socks_version_); | 203 DCHECK_EQ(kSOCKS4Unresolved, socks_version_); |
207 | 204 |
208 bool ok = (result == OK); | 205 bool ok = (result == OK); |
209 next_state_ = STATE_HANDSHAKE_WRITE; | 206 next_state_ = STATE_HANDSHAKE_WRITE; |
210 if (ok) { | 207 if (ok) { |
211 DCHECK(addresses_.head()); | 208 DCHECK(addresses_.head()); |
212 | 209 |
(...skipping 13 matching lines...) Expand all Loading... |
226 } | 223 } |
227 | 224 |
228 // Even if DNS resolution fails, we send OK since the server | 225 // Even if DNS resolution fails, we send OK since the server |
229 // resolves the domain. | 226 // resolves the domain. |
230 return OK; | 227 return OK; |
231 } | 228 } |
232 | 229 |
233 // Builds the buffer that is to be sent to the server. | 230 // Builds the buffer that is to be sent to the server. |
234 // We check whether the SOCKS proxy is 4 or 4A. | 231 // 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. | 232 // In case it is 4A, the record size increases by size of the hostname. |
236 void SOCKSClientSocket::BuildHandshakeWriteBuffer() { | 233 const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const { |
237 DCHECK_NE(kSOCKS4Unresolved, socks_version_); | 234 DCHECK_NE(kSOCKS4Unresolved, socks_version_); |
238 | 235 |
239 int record_size = kWriteHeaderSize + arraysize(kEmptyUserId); | 236 SOCKS4ServerRequest request; |
240 if (socks_version_ == kSOCKS4a) { | 237 request.version = kSOCKSVersion4; |
241 record_size += host_request_info_.hostname().size() + 1; | 238 request.command = kSOCKSStreamRequest; |
242 } | 239 request.nw_port = htons(host_request_info_.port()); |
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 | 240 |
254 if (socks_version_ == kSOCKS4) { | 241 if (socks_version_ == kSOCKS4) { |
255 const struct addrinfo* ai = addresses_.head(); | 242 const struct addrinfo* ai = addresses_.head(); |
256 DCHECK(ai); | 243 DCHECK(ai); |
257 // If the sockaddr is IPv6, we have already marked the version to socks4a | 244 // If the sockaddr is IPv6, we have already marked the version to socks4a |
258 // and so this step does not get hit. | 245 // and so this step does not get hit. |
259 struct sockaddr_in *ipv4_host = | 246 struct sockaddr_in* ipv4_host = |
260 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); | 247 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); |
261 memcpy(&request->ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr)); | 248 memcpy(&request.ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr)); |
262 | 249 |
263 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai); | 250 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai); |
264 } else if (socks_version_ == kSOCKS4a) { | 251 } else if (socks_version_ == kSOCKS4a) { |
265 // invalid IP of the form 0.0.0.127 | 252 // invalid IP of the form 0.0.0.127 |
266 memcpy(&request->ip, kInvalidIp, arraysize(kInvalidIp)); | 253 memcpy(&request.ip, kInvalidIp, arraysize(kInvalidIp)); |
267 } else { | 254 } else { |
268 NOTREACHED(); | 255 NOTREACHED(); |
269 } | 256 } |
270 | 257 |
271 memcpy(&buffer_[kWriteHeaderSize], kEmptyUserId, arraysize(kEmptyUserId)); | 258 std::string handshake_data(reinterpret_cast<char*>(&request), |
| 259 sizeof(request)); |
| 260 handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId)); |
272 | 261 |
| 262 // In case we are passing the domain also, pass the hostname |
| 263 // terminated with a null character. |
273 if (socks_version_ == kSOCKS4a) { | 264 if (socks_version_ == kSOCKS4a) { |
274 memcpy(&buffer_[kWriteHeaderSize + arraysize(kEmptyUserId)], | 265 handshake_data.append(host_request_info_.hostname()); |
275 host_request_info_.hostname().c_str(), | 266 handshake_data.push_back('\0'); |
276 host_request_info_.hostname().size() + 1); | |
277 } | 267 } |
| 268 |
| 269 return handshake_data; |
278 } | 270 } |
279 | 271 |
280 // Writes the SOCKS handshake data to the underlying socket connection. | 272 // Writes the SOCKS handshake data to the underlying socket connection. |
281 int SOCKSClientSocket::DoHandshakeWrite() { | 273 int SOCKSClientSocket::DoHandshakeWrite() { |
282 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; | 274 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; |
283 | 275 |
284 if (!buffer_.get()) { | 276 if (buffer_.empty()) { |
285 BuildHandshakeWriteBuffer(); | 277 buffer_ = BuildHandshakeWriteBuffer(); |
286 bytes_sent_ = 0; | 278 bytes_sent_ = 0; |
287 } | 279 } |
288 | 280 |
289 handshake_buf_len_ = buffer_len_ - bytes_sent_; | 281 int handshake_buf_len = buffer_.size() - bytes_sent_; |
290 DCHECK_GT(handshake_buf_len_, 0); | 282 DCHECK_GT(handshake_buf_len, 0); |
291 handshake_buf_ = new IOBuffer(handshake_buf_len_); | 283 handshake_buf_ = new IOBuffer(handshake_buf_len); |
292 memcpy(handshake_buf_.get()->data(), &buffer_[bytes_sent_], | 284 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], |
293 handshake_buf_len_); | 285 handshake_buf_len); |
294 return transport_->Write(handshake_buf_, handshake_buf_len_, &io_callback_); | 286 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); |
295 } | 287 } |
296 | 288 |
297 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) { | 289 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) { |
298 DCHECK_NE(kSOCKS4Unresolved, socks_version_); | 290 DCHECK_NE(kSOCKS4Unresolved, socks_version_); |
299 | 291 |
300 if (result < 0) | 292 if (result < 0) |
301 return result; | 293 return result; |
302 | 294 |
| 295 // We ignore the case when result is 0, since the underlying Write |
| 296 // may return spurious writes while waiting on the socket. |
| 297 |
303 bytes_sent_ += result; | 298 bytes_sent_ += result; |
304 if (bytes_sent_ == buffer_len_) { | 299 if (bytes_sent_ == buffer_.size()) { |
305 next_state_ = STATE_HANDSHAKE_READ; | 300 next_state_ = STATE_HANDSHAKE_READ; |
306 buffer_.reset(NULL); | 301 buffer_.clear(); |
307 } else if (bytes_sent_ < buffer_len_) { | 302 } else if (bytes_sent_ < buffer_.size()) { |
308 next_state_ = STATE_HANDSHAKE_WRITE; | 303 next_state_ = STATE_HANDSHAKE_WRITE; |
309 } else { | 304 } else { |
310 return ERR_UNEXPECTED; | 305 return ERR_UNEXPECTED; |
311 } | 306 } |
312 | 307 |
313 return OK; | 308 return OK; |
314 } | 309 } |
315 | 310 |
316 int SOCKSClientSocket::DoHandshakeRead() { | 311 int SOCKSClientSocket::DoHandshakeRead() { |
317 DCHECK_NE(kSOCKS4Unresolved, socks_version_); | 312 DCHECK_NE(kSOCKS4Unresolved, socks_version_); |
318 | 313 |
319 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 314 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
320 | 315 |
321 if (!buffer_.get()) { | 316 if (buffer_.empty()) { |
322 buffer_.reset(new char[kReadHeaderSize]); | |
323 buffer_len_ = kReadHeaderSize; | |
324 bytes_received_ = 0; | 317 bytes_received_ = 0; |
325 } | 318 } |
326 | 319 |
327 handshake_buf_len_ = buffer_len_ - bytes_received_; | 320 int handshake_buf_len = kReadHeaderSize - bytes_received_; |
328 handshake_buf_ = new IOBuffer(handshake_buf_len_); | 321 handshake_buf_ = new IOBuffer(handshake_buf_len); |
329 return transport_->Read(handshake_buf_, handshake_buf_len_, &io_callback_); | 322 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); |
330 } | 323 } |
331 | 324 |
332 int SOCKSClientSocket::DoHandshakeReadComplete(int result) { | 325 int SOCKSClientSocket::DoHandshakeReadComplete(int result) { |
333 DCHECK_NE(kSOCKS4Unresolved, socks_version_); | 326 DCHECK_NE(kSOCKS4Unresolved, socks_version_); |
334 | 327 |
335 if (result < 0) | 328 if (result < 0) |
336 return result; | 329 return result; |
337 if (bytes_received_ + result > buffer_len_) | 330 |
| 331 // The underlying socket closed unexpectedly. |
| 332 if (result == 0) |
| 333 return ERR_CONNECTION_CLOSED; |
| 334 |
| 335 if (bytes_received_ + result > kReadHeaderSize) |
338 return ERR_INVALID_RESPONSE; | 336 return ERR_INVALID_RESPONSE; |
339 | 337 |
340 memcpy(buffer_.get() + bytes_received_, handshake_buf_->data(), result); | 338 buffer_.append(handshake_buf_->data(), result); |
341 bytes_received_ += result; | 339 bytes_received_ += result; |
342 if (bytes_received_ < buffer_len_) { | 340 if (bytes_received_ < kReadHeaderSize) { |
343 next_state_ = STATE_HANDSHAKE_READ; | 341 next_state_ = STATE_HANDSHAKE_READ; |
344 return OK; | 342 return OK; |
345 } | 343 } |
346 | 344 |
347 SOCKS4ServerResponse* response = | 345 const SOCKS4ServerResponse* response = |
348 reinterpret_cast<SOCKS4ServerResponse*>(buffer_.get()); | 346 reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data()); |
349 | 347 |
350 if (response->reserved_null != 0x00) { | 348 if (response->reserved_null != 0x00) { |
351 LOG(ERROR) << "Unknown response from SOCKS server."; | 349 LOG(ERROR) << "Unknown response from SOCKS server."; |
352 return ERR_INVALID_RESPONSE; | 350 return ERR_INVALID_RESPONSE; |
353 } | 351 } |
354 | 352 |
355 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h | 353 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h |
356 switch (response->code) { | 354 switch (response->code) { |
357 case kServerResponseOk: | 355 case kServerResponseOk: |
358 completed_handshake_ = true; | 356 completed_handshake_ = true; |
(...skipping 22 matching lines...) Expand all Loading... |
381 // Needed by ssl_client_socket_nss. | 379 // Needed by ssl_client_socket_nss. |
382 int SOCKSClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { | 380 int SOCKSClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { |
383 // Default implementation just permits some unit tests to link. | 381 // Default implementation just permits some unit tests to link. |
384 NOTREACHED(); | 382 NOTREACHED(); |
385 return ERR_UNEXPECTED; | 383 return ERR_UNEXPECTED; |
386 } | 384 } |
387 #endif | 385 #endif |
388 | 386 |
389 } // namespace net | 387 } // namespace net |
390 | 388 |
OLD | NEW |