1/* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#if defined(_MSC_VER) && _MSC_VER < 1300 12#pragma warning(disable:4786) 13#endif 14 15#include <time.h> 16#include <errno.h> 17 18#if defined(WEBRTC_WIN) 19#define WIN32_LEAN_AND_MEAN 20#include <windows.h> 21#include <winsock2.h> 22#include <ws2tcpip.h> 23#define SECURITY_WIN32 24#include <security.h> 25#endif 26 27#include "webrtc/base/bytebuffer.h" 28#include "webrtc/base/common.h" 29#include "webrtc/base/httpcommon.h" 30#include "webrtc/base/logging.h" 31#include "webrtc/base/socketadapters.h" 32#include "webrtc/base/stringencode.h" 33#include "webrtc/base/stringutils.h" 34 35#if defined(WEBRTC_WIN) 36#include "webrtc/base/sec_buffer.h" 37#endif // WEBRTC_WIN 38 39namespace rtc { 40 41BufferedReadAdapter::BufferedReadAdapter(AsyncSocket* socket, size_t size) 42 : AsyncSocketAdapter(socket), buffer_size_(size), 43 data_len_(0), buffering_(false) { 44 buffer_ = new char[buffer_size_]; 45} 46 47BufferedReadAdapter::~BufferedReadAdapter() { 48 delete [] buffer_; 49} 50 51int BufferedReadAdapter::Send(const void *pv, size_t cb) { 52 if (buffering_) { 53 // TODO: Spoof error better; Signal Writeable 54 socket_->SetError(EWOULDBLOCK); 55 return -1; 56 } 57 return AsyncSocketAdapter::Send(pv, cb); 58} 59 60int BufferedReadAdapter::Recv(void *pv, size_t cb) { 61 if (buffering_) { 62 socket_->SetError(EWOULDBLOCK); 63 return -1; 64 } 65 66 size_t read = 0; 67 68 if (data_len_) { 69 read = _min(cb, data_len_); 70 memcpy(pv, buffer_, read); 71 data_len_ -= read; 72 if (data_len_ > 0) { 73 memmove(buffer_, buffer_ + read, data_len_); 74 } 75 pv = static_cast<char *>(pv) + read; 76 cb -= read; 77 } 78 79 // FIX: If cb == 0, we won't generate another read event 80 81 int res = AsyncSocketAdapter::Recv(pv, cb); 82 if (res < 0) 83 return res; 84 85 return res + static_cast<int>(read); 86} 87 88void BufferedReadAdapter::BufferInput(bool on) { 89 buffering_ = on; 90} 91 92void BufferedReadAdapter::OnReadEvent(AsyncSocket * socket) { 93 ASSERT(socket == socket_); 94 95 if (!buffering_) { 96 AsyncSocketAdapter::OnReadEvent(socket); 97 return; 98 } 99 100 if (data_len_ >= buffer_size_) { 101 LOG(INFO) << "Input buffer overflow"; 102 ASSERT(false); 103 data_len_ = 0; 104 } 105 106 int len = socket_->Recv(buffer_ + data_len_, buffer_size_ - data_len_); 107 if (len < 0) { 108 // TODO: Do something better like forwarding the error to the user. 109 LOG_ERR(INFO) << "Recv"; 110 return; 111 } 112 113 data_len_ += len; 114 115 ProcessInput(buffer_, &data_len_); 116} 117 118/////////////////////////////////////////////////////////////////////////////// 119 120// This is a SSL v2 CLIENT_HELLO message. 121// TODO: Should this have a session id? The response doesn't have a 122// certificate, so the hello should have a session id. 123static const uint8 kSslClientHello[] = { 124 0x80, 0x46, // msg len 125 0x01, // CLIENT_HELLO 126 0x03, 0x01, // SSL 3.1 127 0x00, 0x2d, // ciphersuite len 128 0x00, 0x00, // session id len 129 0x00, 0x10, // challenge len 130 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x07, 0x00, 0xc0, // ciphersuites 131 0x06, 0x00, 0x40, 0x02, 0x00, 0x80, 0x04, 0x00, 0x80, // 132 0x00, 0x00, 0x04, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, // 133 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, // 134 0x00, 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, // 135 0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc, // challenge 136 0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea // 137}; 138 139// This is a TLSv1 SERVER_HELLO message. 140static const uint8 kSslServerHello[] = { 141 0x16, // handshake message 142 0x03, 0x01, // SSL 3.1 143 0x00, 0x4a, // message len 144 0x02, // SERVER_HELLO 145 0x00, 0x00, 0x46, // handshake len 146 0x03, 0x01, // SSL 3.1 147 0x42, 0x85, 0x45, 0xa7, 0x27, 0xa9, 0x5d, 0xa0, // server random 148 0xb3, 0xc5, 0xe7, 0x53, 0xda, 0x48, 0x2b, 0x3f, // 149 0xc6, 0x5a, 0xca, 0x89, 0xc1, 0x58, 0x52, 0xa1, // 150 0x78, 0x3c, 0x5b, 0x17, 0x46, 0x00, 0x85, 0x3f, // 151 0x20, // session id len 152 0x0e, 0xd3, 0x06, 0x72, 0x5b, 0x5b, 0x1b, 0x5f, // session id 153 0x15, 0xac, 0x13, 0xf9, 0x88, 0x53, 0x9d, 0x9b, // 154 0xe8, 0x3d, 0x7b, 0x0c, 0x30, 0x32, 0x6e, 0x38, // 155 0x4d, 0xa2, 0x75, 0x57, 0x41, 0x6c, 0x34, 0x5c, // 156 0x00, 0x04, // RSA/RC4-128/MD5 157 0x00 // null compression 158}; 159 160AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket) 161 : BufferedReadAdapter(socket, 1024) { 162} 163 164int AsyncSSLSocket::Connect(const SocketAddress& addr) { 165 // Begin buffering before we connect, so that there isn't a race condition 166 // between potential senders and receiving the OnConnectEvent signal 167 BufferInput(true); 168 return BufferedReadAdapter::Connect(addr); 169} 170 171void AsyncSSLSocket::OnConnectEvent(AsyncSocket * socket) { 172 ASSERT(socket == socket_); 173 // TODO: we could buffer output too... 174 VERIFY(sizeof(kSslClientHello) == 175 DirectSend(kSslClientHello, sizeof(kSslClientHello))); 176} 177 178void AsyncSSLSocket::ProcessInput(char* data, size_t* len) { 179 if (*len < sizeof(kSslServerHello)) 180 return; 181 182 if (memcmp(kSslServerHello, data, sizeof(kSslServerHello)) != 0) { 183 Close(); 184 SignalCloseEvent(this, 0); // TODO: error code? 185 return; 186 } 187 188 *len -= sizeof(kSslServerHello); 189 if (*len > 0) { 190 memmove(data, data + sizeof(kSslServerHello), *len); 191 } 192 193 bool remainder = (*len > 0); 194 BufferInput(false); 195 SignalConnectEvent(this); 196 197 // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble 198 if (remainder) 199 SignalReadEvent(this); 200} 201 202AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* socket) 203 : BufferedReadAdapter(socket, 1024) { 204 BufferInput(true); 205} 206 207void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) { 208 // We only accept client hello messages. 209 if (*len < sizeof(kSslClientHello)) { 210 return; 211 } 212 213 if (memcmp(kSslClientHello, data, sizeof(kSslClientHello)) != 0) { 214 Close(); 215 SignalCloseEvent(this, 0); 216 return; 217 } 218 219 *len -= sizeof(kSslClientHello); 220 221 // Clients should not send more data until the handshake is completed. 222 ASSERT(*len == 0); 223 224 // Send a server hello back to the client. 225 DirectSend(kSslServerHello, sizeof(kSslServerHello)); 226 227 // Handshake completed for us, redirect input to our parent. 228 BufferInput(false); 229} 230 231/////////////////////////////////////////////////////////////////////////////// 232 233AsyncHttpsProxySocket::AsyncHttpsProxySocket(AsyncSocket* socket, 234 const std::string& user_agent, 235 const SocketAddress& proxy, 236 const std::string& username, 237 const CryptString& password) 238 : BufferedReadAdapter(socket, 1024), proxy_(proxy), agent_(user_agent), 239 user_(username), pass_(password), force_connect_(false), state_(PS_ERROR), 240 context_(0) { 241} 242 243AsyncHttpsProxySocket::~AsyncHttpsProxySocket() { 244 delete context_; 245} 246 247int AsyncHttpsProxySocket::Connect(const SocketAddress& addr) { 248 int ret; 249 LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::Connect(" 250 << proxy_.ToSensitiveString() << ")"; 251 dest_ = addr; 252 state_ = PS_INIT; 253 if (ShouldIssueConnect()) { 254 BufferInput(true); 255 } 256 ret = BufferedReadAdapter::Connect(proxy_); 257 // TODO: Set state_ appropriately if Connect fails. 258 return ret; 259} 260 261SocketAddress AsyncHttpsProxySocket::GetRemoteAddress() const { 262 return dest_; 263} 264 265int AsyncHttpsProxySocket::Close() { 266 headers_.clear(); 267 state_ = PS_ERROR; 268 dest_.Clear(); 269 delete context_; 270 context_ = NULL; 271 return BufferedReadAdapter::Close(); 272} 273 274Socket::ConnState AsyncHttpsProxySocket::GetState() const { 275 if (state_ < PS_TUNNEL) { 276 return CS_CONNECTING; 277 } else if (state_ == PS_TUNNEL) { 278 return CS_CONNECTED; 279 } else { 280 return CS_CLOSED; 281 } 282} 283 284void AsyncHttpsProxySocket::OnConnectEvent(AsyncSocket * socket) { 285 LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::OnConnectEvent"; 286 if (!ShouldIssueConnect()) { 287 state_ = PS_TUNNEL; 288 BufferedReadAdapter::OnConnectEvent(socket); 289 return; 290 } 291 SendRequest(); 292} 293 294void AsyncHttpsProxySocket::OnCloseEvent(AsyncSocket * socket, int err) { 295 LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::OnCloseEvent(" << err << ")"; 296 if ((state_ == PS_WAIT_CLOSE) && (err == 0)) { 297 state_ = PS_ERROR; 298 Connect(dest_); 299 } else { 300 BufferedReadAdapter::OnCloseEvent(socket, err); 301 } 302} 303 304void AsyncHttpsProxySocket::ProcessInput(char* data, size_t* len) { 305 size_t start = 0; 306 for (size_t pos = start; state_ < PS_TUNNEL && pos < *len;) { 307 if (state_ == PS_SKIP_BODY) { 308 size_t consume = _min(*len - pos, content_length_); 309 pos += consume; 310 start = pos; 311 content_length_ -= consume; 312 if (content_length_ == 0) { 313 EndResponse(); 314 } 315 continue; 316 } 317 318 if (data[pos++] != '\n') 319 continue; 320 321 size_t len = pos - start - 1; 322 if ((len > 0) && (data[start + len - 1] == '\r')) 323 --len; 324 325 data[start + len] = 0; 326 ProcessLine(data + start, len); 327 start = pos; 328 } 329 330 *len -= start; 331 if (*len > 0) { 332 memmove(data, data + start, *len); 333 } 334 335 if (state_ != PS_TUNNEL) 336 return; 337 338 bool remainder = (*len > 0); 339 BufferInput(false); 340 SignalConnectEvent(this); 341 342 // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble 343 if (remainder) 344 SignalReadEvent(this); // TODO: signal this?? 345} 346 347bool AsyncHttpsProxySocket::ShouldIssueConnect() const { 348 // TODO: Think about whether a more sophisticated test 349 // than dest port == 80 is needed. 350 return force_connect_ || (dest_.port() != 80); 351} 352 353void AsyncHttpsProxySocket::SendRequest() { 354 std::stringstream ss; 355 ss << "CONNECT " << dest_.ToString() << " HTTP/1.0\r\n"; 356 ss << "User-Agent: " << agent_ << "\r\n"; 357 ss << "Host: " << dest_.HostAsURIString() << "\r\n"; 358 ss << "Content-Length: 0\r\n"; 359 ss << "Proxy-Connection: Keep-Alive\r\n"; 360 ss << headers_; 361 ss << "\r\n"; 362 std::string str = ss.str(); 363 DirectSend(str.c_str(), str.size()); 364 state_ = PS_LEADER; 365 expect_close_ = true; 366 content_length_ = 0; 367 headers_.clear(); 368 369 LOG(LS_VERBOSE) << "AsyncHttpsProxySocket >> " << str; 370} 371 372void AsyncHttpsProxySocket::ProcessLine(char * data, size_t len) { 373 LOG(LS_VERBOSE) << "AsyncHttpsProxySocket << " << data; 374 375 if (len == 0) { 376 if (state_ == PS_TUNNEL_HEADERS) { 377 state_ = PS_TUNNEL; 378 } else if (state_ == PS_ERROR_HEADERS) { 379 Error(defer_error_); 380 return; 381 } else if (state_ == PS_SKIP_HEADERS) { 382 if (content_length_) { 383 state_ = PS_SKIP_BODY; 384 } else { 385 EndResponse(); 386 return; 387 } 388 } else { 389 static bool report = false; 390 if (!unknown_mechanisms_.empty() && !report) { 391 report = true; 392 std::string msg( 393 "Unable to connect to the Google Talk service due to an incompatibility " 394 "with your proxy.\r\nPlease help us resolve this issue by submitting the " 395 "following information to us using our technical issue submission form " 396 "at:\r\n\r\n" 397 "http://www.google.com/support/talk/bin/request.py\r\n\r\n" 398 "We apologize for the inconvenience.\r\n\r\n" 399 "Information to submit to Google: " 400 ); 401 //std::string msg("Please report the following information to foo@bar.com:\r\nUnknown methods: "); 402 msg.append(unknown_mechanisms_); 403#if defined(WEBRTC_WIN) 404 MessageBoxA(0, msg.c_str(), "Oops!", MB_OK); 405#endif 406#if defined(WEBRTC_POSIX) 407 // TODO: Raise a signal so the UI can be separated. 408 LOG(LS_ERROR) << "Oops!\n\n" << msg; 409#endif 410 } 411 // Unexpected end of headers 412 Error(0); 413 return; 414 } 415 } else if (state_ == PS_LEADER) { 416 unsigned int code; 417 if (sscanf(data, "HTTP/%*u.%*u %u", &code) != 1) { 418 Error(0); 419 return; 420 } 421 switch (code) { 422 case 200: 423 // connection good! 424 state_ = PS_TUNNEL_HEADERS; 425 return; 426#if defined(HTTP_STATUS_PROXY_AUTH_REQ) && (HTTP_STATUS_PROXY_AUTH_REQ != 407) 427#error Wrong code for HTTP_STATUS_PROXY_AUTH_REQ 428#endif 429 case 407: // HTTP_STATUS_PROXY_AUTH_REQ 430 state_ = PS_AUTHENTICATE; 431 return; 432 default: 433 defer_error_ = 0; 434 state_ = PS_ERROR_HEADERS; 435 return; 436 } 437 } else if ((state_ == PS_AUTHENTICATE) 438 && (_strnicmp(data, "Proxy-Authenticate:", 19) == 0)) { 439 std::string response, auth_method; 440 switch (HttpAuthenticate(data + 19, len - 19, 441 proxy_, "CONNECT", "/", 442 user_, pass_, context_, response, auth_method)) { 443 case HAR_IGNORE: 444 LOG(LS_VERBOSE) << "Ignoring Proxy-Authenticate: " << auth_method; 445 if (!unknown_mechanisms_.empty()) 446 unknown_mechanisms_.append(", "); 447 unknown_mechanisms_.append(auth_method); 448 break; 449 case HAR_RESPONSE: 450 headers_ = "Proxy-Authorization: "; 451 headers_.append(response); 452 headers_.append("\r\n"); 453 state_ = PS_SKIP_HEADERS; 454 unknown_mechanisms_.clear(); 455 break; 456 case HAR_CREDENTIALS: 457 defer_error_ = SOCKET_EACCES; 458 state_ = PS_ERROR_HEADERS; 459 unknown_mechanisms_.clear(); 460 break; 461 case HAR_ERROR: 462 defer_error_ = 0; 463 state_ = PS_ERROR_HEADERS; 464 unknown_mechanisms_.clear(); 465 break; 466 } 467 } else if (_strnicmp(data, "Content-Length:", 15) == 0) { 468 content_length_ = strtoul(data + 15, 0, 0); 469 } else if (_strnicmp(data, "Proxy-Connection: Keep-Alive", 28) == 0) { 470 expect_close_ = false; 471 /* 472 } else if (_strnicmp(data, "Connection: close", 17) == 0) { 473 expect_close_ = true; 474 */ 475 } 476} 477 478void AsyncHttpsProxySocket::EndResponse() { 479 if (!expect_close_) { 480 SendRequest(); 481 return; 482 } 483 484 // No point in waiting for the server to close... let's close now 485 // TODO: Refactor out PS_WAIT_CLOSE 486 state_ = PS_WAIT_CLOSE; 487 BufferedReadAdapter::Close(); 488 OnCloseEvent(this, 0); 489} 490 491void AsyncHttpsProxySocket::Error(int error) { 492 BufferInput(false); 493 Close(); 494 SetError(error); 495 SignalCloseEvent(this, error); 496} 497 498/////////////////////////////////////////////////////////////////////////////// 499 500AsyncSocksProxySocket::AsyncSocksProxySocket(AsyncSocket* socket, 501 const SocketAddress& proxy, 502 const std::string& username, 503 const CryptString& password) 504 : BufferedReadAdapter(socket, 1024), state_(SS_ERROR), proxy_(proxy), 505 user_(username), pass_(password) { 506} 507 508int AsyncSocksProxySocket::Connect(const SocketAddress& addr) { 509 int ret; 510 dest_ = addr; 511 state_ = SS_INIT; 512 BufferInput(true); 513 ret = BufferedReadAdapter::Connect(proxy_); 514 // TODO: Set state_ appropriately if Connect fails. 515 return ret; 516} 517 518SocketAddress AsyncSocksProxySocket::GetRemoteAddress() const { 519 return dest_; 520} 521 522int AsyncSocksProxySocket::Close() { 523 state_ = SS_ERROR; 524 dest_.Clear(); 525 return BufferedReadAdapter::Close(); 526} 527 528Socket::ConnState AsyncSocksProxySocket::GetState() const { 529 if (state_ < SS_TUNNEL) { 530 return CS_CONNECTING; 531 } else if (state_ == SS_TUNNEL) { 532 return CS_CONNECTED; 533 } else { 534 return CS_CLOSED; 535 } 536} 537 538void AsyncSocksProxySocket::OnConnectEvent(AsyncSocket* socket) { 539 SendHello(); 540} 541 542void AsyncSocksProxySocket::ProcessInput(char* data, size_t* len) { 543 ASSERT(state_ < SS_TUNNEL); 544 545 ByteBuffer response(data, *len); 546 547 if (state_ == SS_HELLO) { 548 uint8 ver, method; 549 if (!response.ReadUInt8(&ver) || 550 !response.ReadUInt8(&method)) 551 return; 552 553 if (ver != 5) { 554 Error(0); 555 return; 556 } 557 558 if (method == 0) { 559 SendConnect(); 560 } else if (method == 2) { 561 SendAuth(); 562 } else { 563 Error(0); 564 return; 565 } 566 } else if (state_ == SS_AUTH) { 567 uint8 ver, status; 568 if (!response.ReadUInt8(&ver) || 569 !response.ReadUInt8(&status)) 570 return; 571 572 if ((ver != 1) || (status != 0)) { 573 Error(SOCKET_EACCES); 574 return; 575 } 576 577 SendConnect(); 578 } else if (state_ == SS_CONNECT) { 579 uint8 ver, rep, rsv, atyp; 580 if (!response.ReadUInt8(&ver) || 581 !response.ReadUInt8(&rep) || 582 !response.ReadUInt8(&rsv) || 583 !response.ReadUInt8(&atyp)) 584 return; 585 586 if ((ver != 5) || (rep != 0)) { 587 Error(0); 588 return; 589 } 590 591 uint16 port; 592 if (atyp == 1) { 593 uint32 addr; 594 if (!response.ReadUInt32(&addr) || 595 !response.ReadUInt16(&port)) 596 return; 597 LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port; 598 } else if (atyp == 3) { 599 uint8 len; 600 std::string addr; 601 if (!response.ReadUInt8(&len) || 602 !response.ReadString(&addr, len) || 603 !response.ReadUInt16(&port)) 604 return; 605 LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port; 606 } else if (atyp == 4) { 607 std::string addr; 608 if (!response.ReadString(&addr, 16) || 609 !response.ReadUInt16(&port)) 610 return; 611 LOG(LS_VERBOSE) << "Bound on <IPV6>:" << port; 612 } else { 613 Error(0); 614 return; 615 } 616 617 state_ = SS_TUNNEL; 618 } 619 620 // Consume parsed data 621 *len = response.Length(); 622 memcpy(data, response.Data(), *len); 623 624 if (state_ != SS_TUNNEL) 625 return; 626 627 bool remainder = (*len > 0); 628 BufferInput(false); 629 SignalConnectEvent(this); 630 631 // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble 632 if (remainder) 633 SignalReadEvent(this); // TODO: signal this?? 634} 635 636void AsyncSocksProxySocket::SendHello() { 637 ByteBuffer request; 638 request.WriteUInt8(5); // Socks Version 639 if (user_.empty()) { 640 request.WriteUInt8(1); // Authentication Mechanisms 641 request.WriteUInt8(0); // No authentication 642 } else { 643 request.WriteUInt8(2); // Authentication Mechanisms 644 request.WriteUInt8(0); // No authentication 645 request.WriteUInt8(2); // Username/Password 646 } 647 DirectSend(request.Data(), request.Length()); 648 state_ = SS_HELLO; 649} 650 651void AsyncSocksProxySocket::SendAuth() { 652 ByteBuffer request; 653 request.WriteUInt8(1); // Negotiation Version 654 request.WriteUInt8(static_cast<uint8>(user_.size())); 655 request.WriteString(user_); // Username 656 request.WriteUInt8(static_cast<uint8>(pass_.GetLength())); 657 size_t len = pass_.GetLength() + 1; 658 char * sensitive = new char[len]; 659 pass_.CopyTo(sensitive, true); 660 request.WriteString(sensitive); // Password 661 memset(sensitive, 0, len); 662 delete [] sensitive; 663 DirectSend(request.Data(), request.Length()); 664 state_ = SS_AUTH; 665} 666 667void AsyncSocksProxySocket::SendConnect() { 668 ByteBuffer request; 669 request.WriteUInt8(5); // Socks Version 670 request.WriteUInt8(1); // CONNECT 671 request.WriteUInt8(0); // Reserved 672 if (dest_.IsUnresolved()) { 673 std::string hostname = dest_.hostname(); 674 request.WriteUInt8(3); // DOMAINNAME 675 request.WriteUInt8(static_cast<uint8>(hostname.size())); 676 request.WriteString(hostname); // Destination Hostname 677 } else { 678 request.WriteUInt8(1); // IPV4 679 request.WriteUInt32(dest_.ip()); // Destination IP 680 } 681 request.WriteUInt16(dest_.port()); // Destination Port 682 DirectSend(request.Data(), request.Length()); 683 state_ = SS_CONNECT; 684} 685 686void AsyncSocksProxySocket::Error(int error) { 687 state_ = SS_ERROR; 688 BufferInput(false); 689 Close(); 690 SetError(SOCKET_EACCES); 691 SignalCloseEvent(this, error); 692} 693 694AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* socket) 695 : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) { 696 BufferInput(true); 697} 698 699void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) { 700 // TODO: See if the whole message has arrived 701 ASSERT(state_ < SS_CONNECT_PENDING); 702 703 ByteBuffer response(data, *len); 704 if (state_ == SS_HELLO) { 705 HandleHello(&response); 706 } else if (state_ == SS_AUTH) { 707 HandleAuth(&response); 708 } else if (state_ == SS_CONNECT) { 709 HandleConnect(&response); 710 } 711 712 // Consume parsed data 713 *len = response.Length(); 714 memcpy(data, response.Data(), *len); 715} 716 717void AsyncSocksProxyServerSocket::DirectSend(const ByteBuffer& buf) { 718 BufferedReadAdapter::DirectSend(buf.Data(), buf.Length()); 719} 720 721void AsyncSocksProxyServerSocket::HandleHello(ByteBuffer* request) { 722 uint8 ver, num_methods; 723 if (!request->ReadUInt8(&ver) || 724 !request->ReadUInt8(&num_methods)) { 725 Error(0); 726 return; 727 } 728 729 if (ver != 5) { 730 Error(0); 731 return; 732 } 733 734 // Handle either no-auth (0) or user/pass auth (2) 735 uint8 method = 0xFF; 736 if (num_methods > 0 && !request->ReadUInt8(&method)) { 737 Error(0); 738 return; 739 } 740 741 // TODO: Ask the server which method to use. 742 SendHelloReply(method); 743 if (method == 0) { 744 state_ = SS_CONNECT; 745 } else if (method == 2) { 746 state_ = SS_AUTH; 747 } else { 748 state_ = SS_ERROR; 749 } 750} 751 752void AsyncSocksProxyServerSocket::SendHelloReply(uint8 method) { 753 ByteBuffer response; 754 response.WriteUInt8(5); // Socks Version 755 response.WriteUInt8(method); // Auth method 756 DirectSend(response); 757} 758 759void AsyncSocksProxyServerSocket::HandleAuth(ByteBuffer* request) { 760 uint8 ver, user_len, pass_len; 761 std::string user, pass; 762 if (!request->ReadUInt8(&ver) || 763 !request->ReadUInt8(&user_len) || 764 !request->ReadString(&user, user_len) || 765 !request->ReadUInt8(&pass_len) || 766 !request->ReadString(&pass, pass_len)) { 767 Error(0); 768 return; 769 } 770 771 // TODO: Allow for checking of credentials. 772 SendAuthReply(0); 773 state_ = SS_CONNECT; 774} 775 776void AsyncSocksProxyServerSocket::SendAuthReply(uint8 result) { 777 ByteBuffer response; 778 response.WriteUInt8(1); // Negotiation Version 779 response.WriteUInt8(result); 780 DirectSend(response); 781} 782 783void AsyncSocksProxyServerSocket::HandleConnect(ByteBuffer* request) { 784 uint8 ver, command, reserved, addr_type; 785 uint32 ip; 786 uint16 port; 787 if (!request->ReadUInt8(&ver) || 788 !request->ReadUInt8(&command) || 789 !request->ReadUInt8(&reserved) || 790 !request->ReadUInt8(&addr_type) || 791 !request->ReadUInt32(&ip) || 792 !request->ReadUInt16(&port)) { 793 Error(0); 794 return; 795 } 796 797 if (ver != 5 || command != 1 || 798 reserved != 0 || addr_type != 1) { 799 Error(0); 800 return; 801 } 802 803 SignalConnectRequest(this, SocketAddress(ip, port)); 804 state_ = SS_CONNECT_PENDING; 805} 806 807void AsyncSocksProxyServerSocket::SendConnectResult(int result, 808 const SocketAddress& addr) { 809 if (state_ != SS_CONNECT_PENDING) 810 return; 811 812 ByteBuffer response; 813 response.WriteUInt8(5); // Socks version 814 response.WriteUInt8((result != 0)); // 0x01 is generic error 815 response.WriteUInt8(0); // reserved 816 response.WriteUInt8(1); // IPv4 address 817 response.WriteUInt32(addr.ip()); 818 response.WriteUInt16(addr.port()); 819 DirectSend(response); 820 BufferInput(false); 821 state_ = SS_TUNNEL; 822} 823 824void AsyncSocksProxyServerSocket::Error(int error) { 825 state_ = SS_ERROR; 826 BufferInput(false); 827 Close(); 828 SetError(SOCKET_EACCES); 829 SignalCloseEvent(this, error); 830} 831 832/////////////////////////////////////////////////////////////////////////////// 833 834LoggingSocketAdapter::LoggingSocketAdapter(AsyncSocket* socket, 835 LoggingSeverity level, 836 const char * label, bool hex_mode) 837 : AsyncSocketAdapter(socket), level_(level), hex_mode_(hex_mode) { 838 label_.append("["); 839 label_.append(label); 840 label_.append("]"); 841} 842 843int LoggingSocketAdapter::Send(const void *pv, size_t cb) { 844 int res = AsyncSocketAdapter::Send(pv, cb); 845 if (res > 0) 846 LogMultiline(level_, label_.c_str(), false, pv, res, hex_mode_, &lms_); 847 return res; 848} 849 850int LoggingSocketAdapter::SendTo(const void *pv, size_t cb, 851 const SocketAddress& addr) { 852 int res = AsyncSocketAdapter::SendTo(pv, cb, addr); 853 if (res > 0) 854 LogMultiline(level_, label_.c_str(), false, pv, res, hex_mode_, &lms_); 855 return res; 856} 857 858int LoggingSocketAdapter::Recv(void *pv, size_t cb) { 859 int res = AsyncSocketAdapter::Recv(pv, cb); 860 if (res > 0) 861 LogMultiline(level_, label_.c_str(), true, pv, res, hex_mode_, &lms_); 862 return res; 863} 864 865int LoggingSocketAdapter::RecvFrom(void *pv, size_t cb, SocketAddress *paddr) { 866 int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr); 867 if (res > 0) 868 LogMultiline(level_, label_.c_str(), true, pv, res, hex_mode_, &lms_); 869 return res; 870} 871 872int LoggingSocketAdapter::Close() { 873 LogMultiline(level_, label_.c_str(), false, NULL, 0, hex_mode_, &lms_); 874 LogMultiline(level_, label_.c_str(), true, NULL, 0, hex_mode_, &lms_); 875 LOG_V(level_) << label_ << " Closed locally"; 876 return socket_->Close(); 877} 878 879void LoggingSocketAdapter::OnConnectEvent(AsyncSocket * socket) { 880 LOG_V(level_) << label_ << " Connected"; 881 AsyncSocketAdapter::OnConnectEvent(socket); 882} 883 884void LoggingSocketAdapter::OnCloseEvent(AsyncSocket * socket, int err) { 885 LogMultiline(level_, label_.c_str(), false, NULL, 0, hex_mode_, &lms_); 886 LogMultiline(level_, label_.c_str(), true, NULL, 0, hex_mode_, &lms_); 887 LOG_V(level_) << label_ << " Closed with error: " << err; 888 AsyncSocketAdapter::OnCloseEvent(socket, err); 889} 890 891/////////////////////////////////////////////////////////////////////////////// 892 893} // namespace rtc 894