| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 int SOCKS5ClientSocket::Connect(const CompletionCallback& callback) { | 67 int SOCKS5ClientSocket::Connect(const CompletionCallback& callback) { |
| 68 DCHECK(transport_.get()); | 68 DCHECK(transport_.get()); |
| 69 DCHECK(transport_->socket()); | 69 DCHECK(transport_->socket()); |
| 70 DCHECK_EQ(STATE_NONE, next_state_); | 70 DCHECK_EQ(STATE_NONE, next_state_); |
| 71 DCHECK(user_callback_.is_null()); | 71 DCHECK(user_callback_.is_null()); |
| 72 | 72 |
| 73 // If already connected, then just return OK. | 73 // If already connected, then just return OK. |
| 74 if (completed_handshake_) | 74 if (completed_handshake_) |
| 75 return OK; | 75 return OK; |
| 76 | 76 |
| 77 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL); | 77 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT); |
| 78 | 78 |
| 79 next_state_ = STATE_GREET_WRITE; | 79 next_state_ = STATE_GREET_WRITE; |
| 80 buffer_.clear(); | 80 buffer_.clear(); |
| 81 | 81 |
| 82 int rv = DoLoop(OK); | 82 int rv = DoLoop(OK); |
| 83 if (rv == ERR_IO_PENDING) { | 83 if (rv == ERR_IO_PENDING) { |
| 84 user_callback_ = callback; | 84 user_callback_ = callback; |
| 85 } else { | 85 } else { |
| 86 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv); | 86 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv); |
| 87 } | 87 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 // clear user_callback_ up front. | 204 // clear user_callback_ up front. |
| 205 CompletionCallback c = user_callback_; | 205 CompletionCallback c = user_callback_; |
| 206 user_callback_.Reset(); | 206 user_callback_.Reset(); |
| 207 c.Run(result); | 207 c.Run(result); |
| 208 } | 208 } |
| 209 | 209 |
| 210 void SOCKS5ClientSocket::OnIOComplete(int result) { | 210 void SOCKS5ClientSocket::OnIOComplete(int result) { |
| 211 DCHECK_NE(STATE_NONE, next_state_); | 211 DCHECK_NE(STATE_NONE, next_state_); |
| 212 int rv = DoLoop(result); | 212 int rv = DoLoop(result); |
| 213 if (rv != ERR_IO_PENDING) { | 213 if (rv != ERR_IO_PENDING) { |
| 214 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL); | 214 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT); |
| 215 DoCallback(rv); | 215 DoCallback(rv); |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 | 218 |
| 219 int SOCKS5ClientSocket::DoLoop(int last_io_result) { | 219 int SOCKS5ClientSocket::DoLoop(int last_io_result) { |
| 220 DCHECK_NE(next_state_, STATE_NONE); | 220 DCHECK_NE(next_state_, STATE_NONE); |
| 221 int rv = last_io_result; | 221 int rv = last_io_result; |
| 222 do { | 222 do { |
| 223 State state = next_state_; | 223 State state = next_state_; |
| 224 next_state_ = STATE_NONE; | 224 next_state_ = STATE_NONE; |
| 225 switch (state) { | 225 switch (state) { |
| 226 case STATE_GREET_WRITE: | 226 case STATE_GREET_WRITE: |
| 227 DCHECK_EQ(OK, rv); | 227 DCHECK_EQ(OK, rv); |
| 228 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE, NULL); | 228 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE); |
| 229 rv = DoGreetWrite(); | 229 rv = DoGreetWrite(); |
| 230 break; | 230 break; |
| 231 case STATE_GREET_WRITE_COMPLETE: | 231 case STATE_GREET_WRITE_COMPLETE: |
| 232 rv = DoGreetWriteComplete(rv); | 232 rv = DoGreetWriteComplete(rv); |
| 233 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv); | 233 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv); |
| 234 break; | 234 break; |
| 235 case STATE_GREET_READ: | 235 case STATE_GREET_READ: |
| 236 DCHECK_EQ(OK, rv); | 236 DCHECK_EQ(OK, rv); |
| 237 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ, NULL); | 237 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ); |
| 238 rv = DoGreetRead(); | 238 rv = DoGreetRead(); |
| 239 break; | 239 break; |
| 240 case STATE_GREET_READ_COMPLETE: | 240 case STATE_GREET_READ_COMPLETE: |
| 241 rv = DoGreetReadComplete(rv); | 241 rv = DoGreetReadComplete(rv); |
| 242 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv); | 242 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv); |
| 243 break; | 243 break; |
| 244 case STATE_HANDSHAKE_WRITE: | 244 case STATE_HANDSHAKE_WRITE: |
| 245 DCHECK_EQ(OK, rv); | 245 DCHECK_EQ(OK, rv); |
| 246 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, NULL); | 246 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE); |
| 247 rv = DoHandshakeWrite(); | 247 rv = DoHandshakeWrite(); |
| 248 break; | 248 break; |
| 249 case STATE_HANDSHAKE_WRITE_COMPLETE: | 249 case STATE_HANDSHAKE_WRITE_COMPLETE: |
| 250 rv = DoHandshakeWriteComplete(rv); | 250 rv = DoHandshakeWriteComplete(rv); |
| 251 net_log_.EndEventWithNetErrorCode( | 251 net_log_.EndEventWithNetErrorCode( |
| 252 NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv); | 252 NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv); |
| 253 break; | 253 break; |
| 254 case STATE_HANDSHAKE_READ: | 254 case STATE_HANDSHAKE_READ: |
| 255 DCHECK_EQ(OK, rv); | 255 DCHECK_EQ(OK, rv); |
| 256 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ, NULL); | 256 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ); |
| 257 rv = DoHandshakeRead(); | 257 rv = DoHandshakeRead(); |
| 258 break; | 258 break; |
| 259 case STATE_HANDSHAKE_READ_COMPLETE: | 259 case STATE_HANDSHAKE_READ_COMPLETE: |
| 260 rv = DoHandshakeReadComplete(rv); | 260 rv = DoHandshakeReadComplete(rv); |
| 261 net_log_.EndEventWithNetErrorCode( | 261 net_log_.EndEventWithNetErrorCode( |
| 262 NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv); | 262 NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv); |
| 263 break; | 263 break; |
| 264 default: | 264 default: |
| 265 NOTREACHED() << "bad state"; | 265 NOTREACHED() << "bad state"; |
| 266 rv = ERR_UNEXPECTED; | 266 rv = ERR_UNEXPECTED; |
| 267 break; | 267 break; |
| 268 } | 268 } |
| 269 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 269 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
| 270 return rv; | 270 return rv; |
| 271 } | 271 } |
| 272 | 272 |
| 273 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication | 273 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication |
| 274 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; | 274 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; |
| 275 | 275 |
| 276 int SOCKS5ClientSocket::DoGreetWrite() { | 276 int SOCKS5ClientSocket::DoGreetWrite() { |
| 277 // Since we only have 1 byte to send the hostname length in, if the | 277 // Since we only have 1 byte to send the hostname length in, if the |
| 278 // URL has a hostname longer than 255 characters we can't send it. | 278 // URL has a hostname longer than 255 characters we can't send it. |
| 279 if (0xFF < host_request_info_.hostname().size()) { | 279 if (0xFF < host_request_info_.hostname().size()) { |
| 280 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG, NULL); | 280 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG); |
| 281 return ERR_SOCKS_CONNECTION_FAILED; | 281 return ERR_SOCKS_CONNECTION_FAILED; |
| 282 } | 282 } |
| 283 | 283 |
| 284 if (buffer_.empty()) { | 284 if (buffer_.empty()) { |
| 285 buffer_ = std::string(kSOCKS5GreetWriteData, | 285 buffer_ = std::string(kSOCKS5GreetWriteData, |
| 286 arraysize(kSOCKS5GreetWriteData)); | 286 arraysize(kSOCKS5GreetWriteData)); |
| 287 bytes_sent_ = 0; | 287 bytes_sent_ = 0; |
| 288 } | 288 } |
| 289 | 289 |
| 290 next_state_ = STATE_GREET_WRITE_COMPLETE; | 290 next_state_ = STATE_GREET_WRITE_COMPLETE; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 317 handshake_buf_ = new IOBuffer(handshake_buf_len); | 317 handshake_buf_ = new IOBuffer(handshake_buf_len); |
| 318 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, | 318 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, |
| 319 io_callback_); | 319 io_callback_); |
| 320 } | 320 } |
| 321 | 321 |
| 322 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { | 322 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { |
| 323 if (result < 0) | 323 if (result < 0) |
| 324 return result; | 324 return result; |
| 325 | 325 |
| 326 if (result == 0) { | 326 if (result == 0) { |
| 327 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING, | 327 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); |
| 328 NULL); | |
| 329 return ERR_SOCKS_CONNECTION_FAILED; | 328 return ERR_SOCKS_CONNECTION_FAILED; |
| 330 } | 329 } |
| 331 | 330 |
| 332 bytes_received_ += result; | 331 bytes_received_ += result; |
| 333 buffer_.append(handshake_buf_->data(), result); | 332 buffer_.append(handshake_buf_->data(), result); |
| 334 if (bytes_received_ < kGreetReadHeaderSize) { | 333 if (bytes_received_ < kGreetReadHeaderSize) { |
| 335 next_state_ = STATE_GREET_READ; | 334 next_state_ = STATE_GREET_READ; |
| 336 return OK; | 335 return OK; |
| 337 } | 336 } |
| 338 | 337 |
| 339 // Got the greet data. | 338 // Got the greet data. |
| 340 if (buffer_[0] != kSOCKS5Version) { | 339 if (buffer_[0] != kSOCKS5Version) { |
| 341 net_log_.AddEvent( | 340 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, |
| 342 NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, | 341 NetLog::IntegerCallback("version", buffer_[0])); |
| 343 make_scoped_refptr(new NetLogIntegerParameter("version", buffer_[0]))); | |
| 344 return ERR_SOCKS_CONNECTION_FAILED; | 342 return ERR_SOCKS_CONNECTION_FAILED; |
| 345 } | 343 } |
| 346 if (buffer_[1] != 0x00) { | 344 if (buffer_[1] != 0x00) { |
| 347 net_log_.AddEvent( | 345 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, |
| 348 NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, | 346 NetLog::IntegerCallback("method", buffer_[1])); |
| 349 make_scoped_refptr(new NetLogIntegerParameter("method", buffer_[1]))); | |
| 350 return ERR_SOCKS_CONNECTION_FAILED; | 347 return ERR_SOCKS_CONNECTION_FAILED; |
| 351 } | 348 } |
| 352 | 349 |
| 353 buffer_.clear(); | 350 buffer_.clear(); |
| 354 next_state_ = STATE_HANDSHAKE_WRITE; | 351 next_state_ = STATE_HANDSHAKE_WRITE; |
| 355 return OK; | 352 return OK; |
| 356 } | 353 } |
| 357 | 354 |
| 358 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) | 355 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) |
| 359 const { | 356 const { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, | 427 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, |
| 431 io_callback_); | 428 io_callback_); |
| 432 } | 429 } |
| 433 | 430 |
| 434 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { | 431 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { |
| 435 if (result < 0) | 432 if (result < 0) |
| 436 return result; | 433 return result; |
| 437 | 434 |
| 438 // The underlying socket closed unexpectedly. | 435 // The underlying socket closed unexpectedly. |
| 439 if (result == 0) { | 436 if (result == 0) { |
| 440 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE, | 437 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); |
| 441 NULL); | |
| 442 return ERR_SOCKS_CONNECTION_FAILED; | 438 return ERR_SOCKS_CONNECTION_FAILED; |
| 443 } | 439 } |
| 444 | 440 |
| 445 buffer_.append(handshake_buf_->data(), result); | 441 buffer_.append(handshake_buf_->data(), result); |
| 446 bytes_received_ += result; | 442 bytes_received_ += result; |
| 447 | 443 |
| 448 // When the first few bytes are read, check how many more are required | 444 // When the first few bytes are read, check how many more are required |
| 449 // and accordingly increase them | 445 // and accordingly increase them |
| 450 if (bytes_received_ == kReadHeaderSize) { | 446 if (bytes_received_ == kReadHeaderSize) { |
| 451 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { | 447 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { |
| 452 net_log_.AddEvent( | 448 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, |
| 453 NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, | 449 NetLog::IntegerCallback("version", buffer_[0])); |
| 454 make_scoped_refptr( | |
| 455 new NetLogIntegerParameter("version", buffer_[0]))); | |
| 456 return ERR_SOCKS_CONNECTION_FAILED; | 450 return ERR_SOCKS_CONNECTION_FAILED; |
| 457 } | 451 } |
| 458 if (buffer_[1] != 0x00) { | 452 if (buffer_[1] != 0x00) { |
| 459 net_log_.AddEvent( | 453 net_log_.AddEvent(NetLog::TYPE_SOCKS_SERVER_ERROR, |
| 460 NetLog::TYPE_SOCKS_SERVER_ERROR, | 454 NetLog::IntegerCallback("error_code", buffer_[1])); |
| 461 make_scoped_refptr( | |
| 462 new NetLogIntegerParameter("error_code", buffer_[1]))); | |
| 463 return ERR_SOCKS_CONNECTION_FAILED; | 455 return ERR_SOCKS_CONNECTION_FAILED; |
| 464 } | 456 } |
| 465 | 457 |
| 466 // We check the type of IP/Domain the server returns and accordingly | 458 // We check the type of IP/Domain the server returns and accordingly |
| 467 // increase the size of the response. For domains, we need to read the | 459 // increase the size of the response. For domains, we need to read the |
| 468 // size of the domain, so the initial request size is upto the domain | 460 // size of the domain, so the initial request size is upto the domain |
| 469 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is | 461 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is |
| 470 // read, we substract 1 byte from the additional request size. | 462 // read, we substract 1 byte from the additional request size. |
| 471 SocksEndPointAddressType address_type = | 463 SocksEndPointAddressType address_type = |
| 472 static_cast<SocksEndPointAddressType>(buffer_[3]); | 464 static_cast<SocksEndPointAddressType>(buffer_[3]); |
| 473 if (address_type == kEndPointDomain) | 465 if (address_type == kEndPointDomain) |
| 474 read_header_size += static_cast<uint8>(buffer_[4]); | 466 read_header_size += static_cast<uint8>(buffer_[4]); |
| 475 else if (address_type == kEndPointResolvedIPv4) | 467 else if (address_type == kEndPointResolvedIPv4) |
| 476 read_header_size += sizeof(struct in_addr) - 1; | 468 read_header_size += sizeof(struct in_addr) - 1; |
| 477 else if (address_type == kEndPointResolvedIPv6) | 469 else if (address_type == kEndPointResolvedIPv6) |
| 478 read_header_size += sizeof(struct in6_addr) - 1; | 470 read_header_size += sizeof(struct in6_addr) - 1; |
| 479 else { | 471 else { |
| 480 net_log_.AddEvent( | 472 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, |
| 481 NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, | 473 NetLog::IntegerCallback("address_type", buffer_[3])); |
| 482 make_scoped_refptr( | |
| 483 new NetLogIntegerParameter("address_type", buffer_[3]))); | |
| 484 return ERR_SOCKS_CONNECTION_FAILED; | 474 return ERR_SOCKS_CONNECTION_FAILED; |
| 485 } | 475 } |
| 486 | 476 |
| 487 read_header_size += 2; // for the port. | 477 read_header_size += 2; // for the port. |
| 488 next_state_ = STATE_HANDSHAKE_READ; | 478 next_state_ = STATE_HANDSHAKE_READ; |
| 489 return OK; | 479 return OK; |
| 490 } | 480 } |
| 491 | 481 |
| 492 // When the final bytes are read, setup handshake. We ignore the rest | 482 // When the final bytes are read, setup handshake. We ignore the rest |
| 493 // of the response since they represent the SOCKSv5 endpoint and have | 483 // of the response since they represent the SOCKSv5 endpoint and have |
| (...skipping 11 matching lines...) Expand all Loading... |
| 505 | 495 |
| 506 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { | 496 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { |
| 507 return transport_->socket()->GetPeerAddress(address); | 497 return transport_->socket()->GetPeerAddress(address); |
| 508 } | 498 } |
| 509 | 499 |
| 510 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { | 500 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { |
| 511 return transport_->socket()->GetLocalAddress(address); | 501 return transport_->socket()->GetLocalAddress(address); |
| 512 } | 502 } |
| 513 | 503 |
| 514 } // namespace net | 504 } // namespace net |
| OLD | NEW |