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(AsyncSocket * socket,size_t buffer_size)19 AsyncProxyServerSocket::AsyncProxyServerSocket(AsyncSocket* socket,
20 size_t buffer_size)
21 : BufferedReadAdapter(socket, buffer_size) {}
22
23 AsyncProxyServerSocket::~AsyncProxyServerSocket() = default;
24
AsyncSSLServerSocket(AsyncSocket * socket)25 AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* 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(AsyncSocket * socket)58 AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* 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