• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "rtc_base/server_socket_adapters.h"
12 
13 #include <string>
14 
15 #include "rtc_base/byte_buffer.h"
16 
17 namespace rtc {
18 
AsyncProxyServerSocket(Socket * socket,size_t buffer_size)19 AsyncProxyServerSocket::AsyncProxyServerSocket(Socket* socket,
20                                                size_t buffer_size)
21     : BufferedReadAdapter(socket, buffer_size) {}
22 
23 AsyncProxyServerSocket::~AsyncProxyServerSocket() = default;
24 
AsyncSSLServerSocket(Socket * socket)25 AsyncSSLServerSocket::AsyncSSLServerSocket(Socket* socket)
26     : BufferedReadAdapter(socket, 1024) {
27   BufferInput(true);
28 }
29 
ProcessInput(char * data,size_t * len)30 void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
31   // We only accept client hello messages.
32   const ArrayView<const uint8_t> client_hello =
33       AsyncSSLSocket::SslClientHello();
34   if (*len < client_hello.size()) {
35     return;
36   }
37 
38   if (memcmp(client_hello.data(), data, client_hello.size()) != 0) {
39     Close();
40     SignalCloseEvent(this, 0);
41     return;
42   }
43 
44   *len -= client_hello.size();
45 
46   // Clients should not send more data until the handshake is completed.
47   RTC_DCHECK(*len == 0);
48 
49   const ArrayView<const uint8_t> server_hello =
50       AsyncSSLSocket::SslServerHello();
51   // Send a server hello back to the client.
52   DirectSend(server_hello.data(), server_hello.size());
53 
54   // Handshake completed for us, redirect input to our parent.
55   BufferInput(false);
56 }
57 
AsyncSocksProxyServerSocket(Socket * socket)58 AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(Socket* socket)
59     : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
60   BufferInput(true);
61 }
62 
ProcessInput(char * data,size_t * len)63 void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
64   RTC_DCHECK(state_ < SS_CONNECT_PENDING);
65 
66   ByteBufferReader response(data, *len);
67   if (state_ == SS_HELLO) {
68     HandleHello(&response);
69   } else if (state_ == SS_AUTH) {
70     HandleAuth(&response);
71   } else if (state_ == SS_CONNECT) {
72     HandleConnect(&response);
73   }
74 
75   // Consume parsed data
76   *len = response.Length();
77   memmove(data, response.Data(), *len);
78 }
79 
DirectSend(const ByteBufferWriter & buf)80 void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) {
81   BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
82 }
83 
HandleHello(ByteBufferReader * request)84 void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) {
85   uint8_t ver, num_methods;
86   if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&num_methods)) {
87     Error(0);
88     return;
89   }
90 
91   if (ver != 5) {
92     Error(0);
93     return;
94   }
95 
96   // Handle either no-auth (0) or user/pass auth (2)
97   uint8_t method = 0xFF;
98   if (num_methods > 0 && !request->ReadUInt8(&method)) {
99     Error(0);
100     return;
101   }
102 
103   SendHelloReply(method);
104   if (method == 0) {
105     state_ = SS_CONNECT;
106   } else if (method == 2) {
107     state_ = SS_AUTH;
108   } else {
109     state_ = SS_ERROR;
110   }
111 }
112 
SendHelloReply(uint8_t method)113 void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) {
114   ByteBufferWriter response;
115   response.WriteUInt8(5);       // Socks Version
116   response.WriteUInt8(method);  // Auth method
117   DirectSend(response);
118 }
119 
HandleAuth(ByteBufferReader * request)120 void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) {
121   uint8_t ver, user_len, pass_len;
122   std::string user, pass;
123   if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&user_len) ||
124       !request->ReadString(&user, user_len) || !request->ReadUInt8(&pass_len) ||
125       !request->ReadString(&pass, pass_len)) {
126     Error(0);
127     return;
128   }
129 
130   SendAuthReply(0);
131   state_ = SS_CONNECT;
132 }
133 
SendAuthReply(uint8_t result)134 void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) {
135   ByteBufferWriter response;
136   response.WriteUInt8(1);  // Negotiation Version
137   response.WriteUInt8(result);
138   DirectSend(response);
139 }
140 
HandleConnect(ByteBufferReader * request)141 void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) {
142   uint8_t ver, command, reserved, addr_type;
143   uint32_t ip;
144   uint16_t port;
145   if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&command) ||
146       !request->ReadUInt8(&reserved) || !request->ReadUInt8(&addr_type) ||
147       !request->ReadUInt32(&ip) || !request->ReadUInt16(&port)) {
148     Error(0);
149     return;
150   }
151 
152   if (ver != 5 || command != 1 || reserved != 0 || addr_type != 1) {
153     Error(0);
154     return;
155   }
156 
157   SignalConnectRequest(this, SocketAddress(ip, port));
158   state_ = SS_CONNECT_PENDING;
159 }
160 
SendConnectResult(int result,const SocketAddress & addr)161 void AsyncSocksProxyServerSocket::SendConnectResult(int result,
162                                                     const SocketAddress& addr) {
163   if (state_ != SS_CONNECT_PENDING)
164     return;
165 
166   ByteBufferWriter response;
167   response.WriteUInt8(5);              // Socks version
168   response.WriteUInt8((result != 0));  // 0x01 is generic error
169   response.WriteUInt8(0);              // reserved
170   response.WriteUInt8(1);              // IPv4 address
171   response.WriteUInt32(addr.ip());
172   response.WriteUInt16(addr.port());
173   DirectSend(response);
174   BufferInput(false);
175   state_ = SS_TUNNEL;
176 }
177 
Error(int error)178 void AsyncSocksProxyServerSocket::Error(int error) {
179   state_ = SS_ERROR;
180   BufferInput(false);
181   Close();
182   SetError(SOCKET_EACCES);
183   SignalCloseEvent(this, error);
184 }
185 
186 }  // namespace rtc
187