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/socks5_client_socket.h" | 5 #include "net/socket/socks5_client_socket.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/trace_event.h" | 9 #include "base/trace_event.h" |
10 #include "net/base/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
11 #include "net/base/load_log.h" | 11 #include "net/base/load_log.h" |
12 #include "net/base/net_util.h" | 12 #include "net/base/net_util.h" |
13 #include "net/base/sys_addrinfo.h" | 13 #include "net/base/sys_addrinfo.h" |
14 | 14 |
15 namespace net { | 15 namespace net { |
16 | 16 |
17 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; | 17 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; |
18 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; | 18 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; |
19 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; | 19 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; |
20 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05; | 20 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05; |
21 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01; | 21 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01; |
22 const uint8 SOCKS5ClientSocket::kNullByte = 0x00; | 22 const uint8 SOCKS5ClientSocket::kNullByte = 0x00; |
23 | 23 |
24 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4); | 24 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4); |
25 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6); | 25 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6); |
26 | 26 |
27 SOCKS5ClientSocket::SOCKS5ClientSocket(ClientSocket* transport_socket, | 27 SOCKS5ClientSocket::SOCKS5ClientSocket(ClientSocket* transport_socket, |
28 const HostResolver::RequestInfo& req_info, | 28 const HostResolver::RequestInfo& req_info) |
29 HostResolver* host_resolver) | |
30 : ALLOW_THIS_IN_INITIALIZER_LIST( | 29 : ALLOW_THIS_IN_INITIALIZER_LIST( |
31 io_callback_(this, &SOCKS5ClientSocket::OnIOComplete)), | 30 io_callback_(this, &SOCKS5ClientSocket::OnIOComplete)), |
32 transport_(transport_socket), | 31 transport_(transport_socket), |
33 next_state_(STATE_NONE), | 32 next_state_(STATE_NONE), |
34 address_type_(kEndPointUnresolved), | |
35 user_callback_(NULL), | 33 user_callback_(NULL), |
36 completed_handshake_(false), | 34 completed_handshake_(false), |
37 bytes_sent_(0), | 35 bytes_sent_(0), |
38 bytes_received_(0), | 36 bytes_received_(0), |
39 read_header_size(kReadHeaderSize), | 37 read_header_size(kReadHeaderSize), |
40 host_request_info_(req_info) { | 38 host_request_info_(req_info) { |
41 if (host_resolver) | |
42 host_resolver_.reset(new SingleRequestHostResolver(host_resolver)); | |
43 } | 39 } |
44 | 40 |
45 SOCKS5ClientSocket::~SOCKS5ClientSocket() { | 41 SOCKS5ClientSocket::~SOCKS5ClientSocket() { |
46 Disconnect(); | 42 Disconnect(); |
47 } | 43 } |
48 | 44 |
49 int SOCKS5ClientSocket::Connect(CompletionCallback* callback, | 45 int SOCKS5ClientSocket::Connect(CompletionCallback* callback, |
50 LoadLog* load_log) { | 46 LoadLog* load_log) { |
51 DCHECK(transport_.get()); | 47 DCHECK(transport_.get()); |
52 DCHECK(transport_->IsConnected()); | 48 DCHECK(transport_->IsConnected()); |
53 DCHECK_EQ(STATE_NONE, next_state_); | 49 DCHECK_EQ(STATE_NONE, next_state_); |
54 DCHECK(!user_callback_); | 50 DCHECK(!user_callback_); |
55 | 51 |
56 // If already connected, then just return OK. | 52 // If already connected, then just return OK. |
57 if (completed_handshake_) | 53 if (completed_handshake_) |
58 return OK; | 54 return OK; |
59 | 55 |
60 load_log_ = load_log; | 56 load_log_ = load_log; |
61 LoadLog::BeginEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); | 57 LoadLog::BeginEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); |
62 | 58 |
63 // If a host resolver was given, try to resolve the address locally. | 59 next_state_ = STATE_GREET_WRITE; |
64 // Otherwise let the proxy server handle the resolving. | 60 buffer_.clear(); |
65 if (host_resolver_.get()) { | |
66 next_state_ = STATE_RESOLVE_HOST; | |
67 } else { | |
68 next_state_ = STATE_GREET_WRITE; | |
69 address_type_ = kEndPointFailedDomain; | |
70 } | |
71 | 61 |
72 int rv = DoLoop(OK); | 62 int rv = DoLoop(OK); |
73 if (rv == ERR_IO_PENDING) { | 63 if (rv == ERR_IO_PENDING) { |
74 user_callback_ = callback; | 64 user_callback_ = callback; |
75 } else { | 65 } else { |
76 LoadLog::EndEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); | 66 LoadLog::EndEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); |
77 load_log_ = NULL; | 67 load_log_ = NULL; |
78 } | 68 } |
79 return rv; | 69 return rv; |
80 } | 70 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 } | 134 } |
145 } | 135 } |
146 | 136 |
147 int SOCKS5ClientSocket::DoLoop(int last_io_result) { | 137 int SOCKS5ClientSocket::DoLoop(int last_io_result) { |
148 DCHECK_NE(next_state_, STATE_NONE); | 138 DCHECK_NE(next_state_, STATE_NONE); |
149 int rv = last_io_result; | 139 int rv = last_io_result; |
150 do { | 140 do { |
151 State state = next_state_; | 141 State state = next_state_; |
152 next_state_ = STATE_NONE; | 142 next_state_ = STATE_NONE; |
153 switch (state) { | 143 switch (state) { |
154 case STATE_RESOLVE_HOST: | |
155 DCHECK_EQ(OK, rv); | |
156 rv = DoResolveHost(); | |
157 break; | |
158 case STATE_RESOLVE_HOST_COMPLETE: | |
159 rv = DoResolveHostComplete(rv); | |
160 break; | |
161 case STATE_GREET_WRITE: | 144 case STATE_GREET_WRITE: |
162 DCHECK_EQ(OK, rv); | 145 DCHECK_EQ(OK, rv); |
163 rv = DoGreetWrite(); | 146 rv = DoGreetWrite(); |
164 break; | 147 break; |
165 case STATE_GREET_WRITE_COMPLETE: | 148 case STATE_GREET_WRITE_COMPLETE: |
166 rv = DoGreetWriteComplete(rv); | 149 rv = DoGreetWriteComplete(rv); |
167 break; | 150 break; |
168 case STATE_GREET_READ: | 151 case STATE_GREET_READ: |
169 DCHECK_EQ(OK, rv); | 152 DCHECK_EQ(OK, rv); |
170 rv = DoGreetRead(); | 153 rv = DoGreetRead(); |
(...skipping 17 matching lines...) Expand all Loading... |
188 break; | 171 break; |
189 default: | 172 default: |
190 NOTREACHED() << "bad state"; | 173 NOTREACHED() << "bad state"; |
191 rv = ERR_UNEXPECTED; | 174 rv = ERR_UNEXPECTED; |
192 break; | 175 break; |
193 } | 176 } |
194 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 177 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
195 return rv; | 178 return rv; |
196 } | 179 } |
197 | 180 |
198 int SOCKS5ClientSocket::DoResolveHost() { | |
199 DCHECK_EQ(kEndPointUnresolved, address_type_); | |
200 | |
201 next_state_ = STATE_RESOLVE_HOST_COMPLETE; | |
202 return host_resolver_->Resolve( | |
203 host_request_info_, &addresses_, &io_callback_, load_log_); | |
204 } | |
205 | |
206 int SOCKS5ClientSocket::DoResolveHostComplete(int result) { | |
207 DCHECK_EQ(kEndPointUnresolved, address_type_); | |
208 | |
209 bool ok = (result == OK); | |
210 next_state_ = STATE_GREET_WRITE; | |
211 if (ok) { | |
212 DCHECK(addresses_.head()); | |
213 struct sockaddr* host_info = addresses_.head()->ai_addr; | |
214 if (host_info->sa_family == AF_INET) { | |
215 address_type_ = kEndPointResolvedIPv4; | |
216 } else if (host_info->sa_family == AF_INET6) { | |
217 address_type_ = kEndPointResolvedIPv6; | |
218 } | |
219 } else { | |
220 address_type_ = kEndPointFailedDomain; | |
221 } | |
222 | |
223 buffer_.clear(); | |
224 | |
225 // Even if DNS resolution fails, we send OK since the server | |
226 // resolves the domain. | |
227 return OK; | |
228 } | |
229 | |
230 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication | 181 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication |
231 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; | 182 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; |
232 | 183 |
233 int SOCKS5ClientSocket::DoGreetWrite() { | 184 int SOCKS5ClientSocket::DoGreetWrite() { |
234 if (buffer_.empty()) { | 185 if (buffer_.empty()) { |
235 buffer_ = std::string(kSOCKS5GreetWriteData, | 186 buffer_ = std::string(kSOCKS5GreetWriteData, |
236 arraysize(kSOCKS5GreetWriteData)); | 187 arraysize(kSOCKS5GreetWriteData)); |
237 bytes_sent_ = 0; | 188 bytes_sent_ = 0; |
238 } | 189 } |
239 | 190 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 if (buffer_[0] != kSOCKS5Version || buffer_[1] != 0x00) | 236 if (buffer_[0] != kSOCKS5Version || buffer_[1] != 0x00) |
286 return ERR_INVALID_RESPONSE; // Unknown error | 237 return ERR_INVALID_RESPONSE; // Unknown error |
287 | 238 |
288 buffer_.clear(); | 239 buffer_.clear(); |
289 next_state_ = STATE_HANDSHAKE_WRITE; | 240 next_state_ = STATE_HANDSHAKE_WRITE; |
290 return OK; | 241 return OK; |
291 } | 242 } |
292 | 243 |
293 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) | 244 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) |
294 const { | 245 const { |
295 DCHECK_NE(kEndPointUnresolved, address_type_); | |
296 DCHECK(handshake->empty()); | 246 DCHECK(handshake->empty()); |
297 | 247 |
298 handshake->push_back(kSOCKS5Version); | 248 handshake->push_back(kSOCKS5Version); |
299 handshake->push_back(kTunnelCommand); // Connect command | 249 handshake->push_back(kTunnelCommand); // Connect command |
300 handshake->push_back(kNullByte); // Reserved null | 250 handshake->push_back(kNullByte); // Reserved null |
301 | 251 |
302 handshake->push_back(address_type_); // The type of connection | 252 handshake->push_back(kEndPointDomain); // The type of the address. |
303 if (address_type_ == kEndPointFailedDomain) { | |
304 if(256 <= host_request_info_.hostname().size()) | |
305 return ERR_ADDRESS_INVALID; | |
306 | 253 |
307 // First add the size of the hostname, followed by the hostname. | 254 // We only have 1 byte to send the length in, so if the hostname is |
308 handshake->push_back(static_cast<unsigned char>( | 255 // longer than this we can't send it! |
309 host_request_info_.hostname().size())); | 256 if(256 <= host_request_info_.hostname().size()) |
310 handshake->append(host_request_info_.hostname()); | 257 return ERR_INVALID_URL; |
311 | 258 |
312 } else if (address_type_ == kEndPointResolvedIPv4) { | 259 // First add the size of the hostname, followed by the hostname. |
313 struct sockaddr_in* ipv4_host = | 260 handshake->push_back(static_cast<unsigned char>( |
314 reinterpret_cast<struct sockaddr_in*>(addresses_.head()->ai_addr); | 261 host_request_info_.hostname().size())); |
315 handshake->append(reinterpret_cast<char*>(&ipv4_host->sin_addr), | 262 handshake->append(host_request_info_.hostname()); |
316 sizeof(ipv4_host->sin_addr)); | |
317 | |
318 } else if (address_type_ == kEndPointResolvedIPv6) { | |
319 struct sockaddr_in6* ipv6_host = | |
320 reinterpret_cast<struct sockaddr_in6*>(addresses_.head()->ai_addr); | |
321 handshake->append(reinterpret_cast<char*>(&ipv6_host->sin6_addr), | |
322 sizeof(ipv6_host->sin6_addr)); | |
323 | |
324 } else { | |
325 NOTREACHED(); | |
326 } | |
327 | 263 |
328 uint16 nw_port = htons(host_request_info_.port()); | 264 uint16 nw_port = htons(host_request_info_.port()); |
329 handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port)); | 265 handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port)); |
330 return OK; | 266 return OK; |
331 } | 267 } |
332 | 268 |
333 // Writes the SOCKS handshake data to the underlying socket connection. | 269 // Writes the SOCKS handshake data to the underlying socket connection. |
334 int SOCKS5ClientSocket::DoHandshakeWrite() { | 270 int SOCKS5ClientSocket::DoHandshakeWrite() { |
335 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; | 271 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; |
336 | 272 |
337 if (buffer_.empty()) { | 273 if (buffer_.empty()) { |
338 int rv = BuildHandshakeWriteBuffer(&buffer_); | 274 int rv = BuildHandshakeWriteBuffer(&buffer_); |
339 if (rv != OK) | 275 if (rv != OK) |
340 return rv; | 276 return rv; |
341 bytes_sent_ = 0; | 277 bytes_sent_ = 0; |
342 } | 278 } |
343 | 279 |
344 int handshake_buf_len = buffer_.size() - bytes_sent_; | 280 int handshake_buf_len = buffer_.size() - bytes_sent_; |
345 DCHECK_LT(0, handshake_buf_len); | 281 DCHECK_LT(0, handshake_buf_len); |
346 handshake_buf_ = new IOBuffer(handshake_buf_len); | 282 handshake_buf_ = new IOBuffer(handshake_buf_len); |
347 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], | 283 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], |
348 handshake_buf_len); | 284 handshake_buf_len); |
349 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); | 285 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); |
350 } | 286 } |
351 | 287 |
352 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) { | 288 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) { |
353 DCHECK_NE(kEndPointUnresolved, address_type_); | |
354 | |
355 if (result < 0) | 289 if (result < 0) |
356 return result; | 290 return result; |
357 | 291 |
358 // We ignore the case when result is 0, since the underlying Write | 292 // We ignore the case when result is 0, since the underlying Write |
359 // may return spurious writes while waiting on the socket. | 293 // may return spurious writes while waiting on the socket. |
360 | 294 |
361 bytes_sent_ += result; | 295 bytes_sent_ += result; |
362 if (bytes_sent_ == buffer_.size()) { | 296 if (bytes_sent_ == buffer_.size()) { |
363 next_state_ = STATE_HANDSHAKE_READ; | 297 next_state_ = STATE_HANDSHAKE_READ; |
364 buffer_.clear(); | 298 buffer_.clear(); |
365 } else if (bytes_sent_ < buffer_.size()) { | 299 } else if (bytes_sent_ < buffer_.size()) { |
366 next_state_ = STATE_HANDSHAKE_WRITE; | 300 next_state_ = STATE_HANDSHAKE_WRITE; |
367 } else { | 301 } else { |
368 NOTREACHED(); | 302 NOTREACHED(); |
369 } | 303 } |
370 | 304 |
371 return OK; | 305 return OK; |
372 } | 306 } |
373 | 307 |
374 int SOCKS5ClientSocket::DoHandshakeRead() { | 308 int SOCKS5ClientSocket::DoHandshakeRead() { |
375 DCHECK_NE(kEndPointUnresolved, address_type_); | |
376 | |
377 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 309 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
378 | 310 |
379 if (buffer_.empty()) { | 311 if (buffer_.empty()) { |
380 bytes_received_ = 0; | 312 bytes_received_ = 0; |
381 read_header_size = kReadHeaderSize; | 313 read_header_size = kReadHeaderSize; |
382 } | 314 } |
383 | 315 |
384 int handshake_buf_len = read_header_size - bytes_received_; | 316 int handshake_buf_len = read_header_size - bytes_received_; |
385 handshake_buf_ = new IOBuffer(handshake_buf_len); | 317 handshake_buf_ = new IOBuffer(handshake_buf_len); |
386 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); | 318 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); |
387 } | 319 } |
388 | 320 |
389 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { | 321 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { |
390 DCHECK_NE(kEndPointUnresolved, address_type_); | |
391 | |
392 if (result < 0) | 322 if (result < 0) |
393 return result; | 323 return result; |
394 | 324 |
395 // The underlying socket closed unexpectedly. | 325 // The underlying socket closed unexpectedly. |
396 if (result == 0) | 326 if (result == 0) |
397 return ERR_CONNECTION_CLOSED; | 327 return ERR_CONNECTION_CLOSED; |
398 | 328 |
399 buffer_.append(handshake_buf_->data(), result); | 329 buffer_.append(handshake_buf_->data(), result); |
400 bytes_received_ += result; | 330 bytes_received_ += result; |
401 | 331 |
402 // When the first few bytes are read, check how many more are required | 332 // When the first few bytes are read, check how many more are required |
403 // and accordingly increase them | 333 // and accordingly increase them |
404 if (bytes_received_ == kReadHeaderSize) { | 334 if (bytes_received_ == kReadHeaderSize) { |
405 // TODO(arindam): add error codes to net/error_list.h | 335 // TODO(arindam): add error codes to net/error_list.h |
406 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) | 336 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) |
407 return ERR_INVALID_RESPONSE; | 337 return ERR_INVALID_RESPONSE; |
408 if (buffer_[1] != 0x00) | 338 if (buffer_[1] != 0x00) |
409 return ERR_FAILED; | 339 return ERR_FAILED; |
410 | 340 |
411 // We check the type of IP/Domain the server returns and accordingly | 341 // We check the type of IP/Domain the server returns and accordingly |
412 // increase the size of the response. For domains, we need to read the | 342 // increase the size of the response. For domains, we need to read the |
413 // size of the domain, so the initial request size is upto the domain | 343 // size of the domain, so the initial request size is upto the domain |
414 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is | 344 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is |
415 // read, we substract 1 byte from the additional request size. | 345 // read, we substract 1 byte from the additional request size. |
416 SocksEndPointAddressType address_type = | 346 SocksEndPointAddressType address_type = |
417 static_cast<SocksEndPointAddressType>(buffer_[3]); | 347 static_cast<SocksEndPointAddressType>(buffer_[3]); |
418 if (address_type == kEndPointFailedDomain) | 348 if (address_type == kEndPointDomain) |
419 read_header_size += static_cast<uint8>(buffer_[4]); | 349 read_header_size += static_cast<uint8>(buffer_[4]); |
420 else if (address_type == kEndPointResolvedIPv4) | 350 else if (address_type == kEndPointResolvedIPv4) |
421 read_header_size += sizeof(struct in_addr) - 1; | 351 read_header_size += sizeof(struct in_addr) - 1; |
422 else if (address_type == kEndPointResolvedIPv6) | 352 else if (address_type == kEndPointResolvedIPv6) |
423 read_header_size += sizeof(struct in6_addr) - 1; | 353 read_header_size += sizeof(struct in6_addr) - 1; |
424 else | 354 else |
425 return ERR_INVALID_RESPONSE; | 355 return ERR_INVALID_RESPONSE; |
426 | 356 |
427 read_header_size += 2; // for the port. | 357 read_header_size += 2; // for the port. |
428 next_state_ = STATE_HANDSHAKE_READ; | 358 next_state_ = STATE_HANDSHAKE_READ; |
(...skipping 15 matching lines...) Expand all Loading... |
444 } | 374 } |
445 | 375 |
446 #if defined(OS_LINUX) | 376 #if defined(OS_LINUX) |
447 int SOCKS5ClientSocket::GetPeerName(struct sockaddr* name, | 377 int SOCKS5ClientSocket::GetPeerName(struct sockaddr* name, |
448 socklen_t* namelen) { | 378 socklen_t* namelen) { |
449 return transport_->GetPeerName(name, namelen); | 379 return transport_->GetPeerName(name, namelen); |
450 } | 380 } |
451 #endif | 381 #endif |
452 | 382 |
453 } // namespace net | 383 } // namespace net |
OLD | NEW |