blob: 1cdd1bcbebdcacc6ef244d3010c94770d3c5e532 [file] [log] [blame]
henrike@webrtc.orgf7795df2014-05-13 18:00:26 +00001/*
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(int 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(int 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