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