xref: /aosp_15_r20/external/webrtc/rtc_base/server_socket_adapters.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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