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