diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/libwebrtc/rtc_base/server_socket_adapters.cc | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/rtc_base/server_socket_adapters.cc')
-rw-r--r-- | third_party/libwebrtc/rtc_base/server_socket_adapters.cc | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/server_socket_adapters.cc b/third_party/libwebrtc/rtc_base/server_socket_adapters.cc new file mode 100644 index 0000000000..673083c7cd --- /dev/null +++ b/third_party/libwebrtc/rtc_base/server_socket_adapters.cc @@ -0,0 +1,186 @@ +/* + * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "rtc_base/server_socket_adapters.h" + +#include <string> + +#include "rtc_base/byte_buffer.h" + +namespace rtc { + +AsyncProxyServerSocket::AsyncProxyServerSocket(Socket* socket, + size_t buffer_size) + : BufferedReadAdapter(socket, buffer_size) {} + +AsyncProxyServerSocket::~AsyncProxyServerSocket() = default; + +AsyncSSLServerSocket::AsyncSSLServerSocket(Socket* socket) + : BufferedReadAdapter(socket, 1024) { + BufferInput(true); +} + +void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) { + // We only accept client hello messages. + const ArrayView<const uint8_t> client_hello = + AsyncSSLSocket::SslClientHello(); + if (*len < client_hello.size()) { + return; + } + + if (memcmp(client_hello.data(), data, client_hello.size()) != 0) { + Close(); + SignalCloseEvent(this, 0); + return; + } + + *len -= client_hello.size(); + + // Clients should not send more data until the handshake is completed. + RTC_DCHECK(*len == 0); + + const ArrayView<const uint8_t> server_hello = + AsyncSSLSocket::SslServerHello(); + // Send a server hello back to the client. + DirectSend(server_hello.data(), server_hello.size()); + + // Handshake completed for us, redirect input to our parent. + BufferInput(false); +} + +AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(Socket* socket) + : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) { + BufferInput(true); +} + +void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) { + RTC_DCHECK(state_ < SS_CONNECT_PENDING); + + ByteBufferReader response(data, *len); + if (state_ == SS_HELLO) { + HandleHello(&response); + } else if (state_ == SS_AUTH) { + HandleAuth(&response); + } else if (state_ == SS_CONNECT) { + HandleConnect(&response); + } + + // Consume parsed data + *len = response.Length(); + memmove(data, response.Data(), *len); +} + +void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) { + BufferedReadAdapter::DirectSend(buf.Data(), buf.Length()); +} + +void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) { + uint8_t ver, num_methods; + if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&num_methods)) { + Error(0); + return; + } + + if (ver != 5) { + Error(0); + return; + } + + // Handle either no-auth (0) or user/pass auth (2) + uint8_t method = 0xFF; + if (num_methods > 0 && !request->ReadUInt8(&method)) { + Error(0); + return; + } + + SendHelloReply(method); + if (method == 0) { + state_ = SS_CONNECT; + } else if (method == 2) { + state_ = SS_AUTH; + } else { + state_ = SS_ERROR; + } +} + +void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) { + ByteBufferWriter response; + response.WriteUInt8(5); // Socks Version + response.WriteUInt8(method); // Auth method + DirectSend(response); +} + +void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) { + uint8_t ver, user_len, pass_len; + std::string user, pass; + if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&user_len) || + !request->ReadString(&user, user_len) || !request->ReadUInt8(&pass_len) || + !request->ReadString(&pass, pass_len)) { + Error(0); + return; + } + + SendAuthReply(0); + state_ = SS_CONNECT; +} + +void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) { + ByteBufferWriter response; + response.WriteUInt8(1); // Negotiation Version + response.WriteUInt8(result); + DirectSend(response); +} + +void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) { + uint8_t ver, command, reserved, addr_type; + uint32_t ip; + uint16_t port; + if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&command) || + !request->ReadUInt8(&reserved) || !request->ReadUInt8(&addr_type) || + !request->ReadUInt32(&ip) || !request->ReadUInt16(&port)) { + Error(0); + return; + } + + if (ver != 5 || command != 1 || reserved != 0 || addr_type != 1) { + Error(0); + return; + } + + SignalConnectRequest(this, SocketAddress(ip, port)); + state_ = SS_CONNECT_PENDING; +} + +void AsyncSocksProxyServerSocket::SendConnectResult(int result, + const SocketAddress& addr) { + if (state_ != SS_CONNECT_PENDING) + return; + + ByteBufferWriter response; + response.WriteUInt8(5); // Socks version + response.WriteUInt8((result != 0)); // 0x01 is generic error + response.WriteUInt8(0); // reserved + response.WriteUInt8(1); // IPv4 address + response.WriteUInt32(addr.ip()); + response.WriteUInt16(addr.port()); + DirectSend(response); + BufferInput(false); + state_ = SS_TUNNEL; +} + +void AsyncSocksProxyServerSocket::Error(int error) { + state_ = SS_ERROR; + BufferInput(false); + Close(); + SetError(SOCKET_EACCES); + SignalCloseEvent(this, error); +} + +} // namespace rtc |