diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/rtc_base/firewall_socket_server.cc | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/rtc_base/firewall_socket_server.cc')
-rw-r--r-- | third_party/libwebrtc/rtc_base/firewall_socket_server.cc | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/firewall_socket_server.cc b/third_party/libwebrtc/rtc_base/firewall_socket_server.cc new file mode 100644 index 0000000000..db88d19a15 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/firewall_socket_server.cc @@ -0,0 +1,268 @@ +/* + * 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/firewall_socket_server.h" + +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include <string> + +#include "absl/algorithm/container.h" +#include "rtc_base/async_socket.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" + +namespace rtc { + +class FirewallSocket : public AsyncSocketAdapter { + public: + FirewallSocket(FirewallSocketServer* server, Socket* socket, int type) + : AsyncSocketAdapter(socket), server_(server), type_(type) {} + + int Bind(const SocketAddress& addr) override { + if (!server_->IsBindableIp(addr.ipaddr())) { + SetError(EINVAL); + return SOCKET_ERROR; + } + return AsyncSocketAdapter::Bind(addr); + } + + int Connect(const SocketAddress& addr) override { + if (type_ == SOCK_STREAM) { + if (!server_->Check(FP_TCP, GetLocalAddress(), addr)) { + RTC_LOG(LS_VERBOSE) << "FirewallSocket outbound TCP connection from " + << GetLocalAddress().ToSensitiveString() << " to " + << addr.ToSensitiveString() << " denied"; + // TODO: Handle this asynchronously. + SetError(EHOSTUNREACH); + return SOCKET_ERROR; + } + } + return AsyncSocketAdapter::Connect(addr); + } + int Send(const void* pv, size_t cb) override { + return SendTo(pv, cb, GetRemoteAddress()); + } + int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override { + RTC_DCHECK(type_ == SOCK_DGRAM || type_ == SOCK_STREAM); + FirewallProtocol protocol = (type_ == SOCK_DGRAM) ? FP_UDP : FP_TCP; + if (!server_->Check(protocol, GetLocalAddress(), addr)) { + RTC_LOG(LS_VERBOSE) << "FirewallSocket outbound packet with type " + << type_ << " from " + << GetLocalAddress().ToSensitiveString() << " to " + << addr.ToSensitiveString() << " dropped"; + return static_cast<int>(cb); + } + return AsyncSocketAdapter::SendTo(pv, cb, addr); + } + int Recv(void* pv, size_t cb, int64_t* timestamp) override { + SocketAddress addr; + return RecvFrom(pv, cb, &addr, timestamp); + } + int RecvFrom(void* pv, + size_t cb, + SocketAddress* paddr, + int64_t* timestamp) override { + if (type_ == SOCK_DGRAM) { + while (true) { + int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr, timestamp); + if (res <= 0) + return res; + if (server_->Check(FP_UDP, *paddr, GetLocalAddress())) + return res; + RTC_LOG(LS_VERBOSE) + << "FirewallSocket inbound UDP packet from " + << paddr->ToSensitiveString() << " to " + << GetLocalAddress().ToSensitiveString() << " dropped"; + } + } + return AsyncSocketAdapter::RecvFrom(pv, cb, paddr, timestamp); + } + + int Listen(int backlog) override { + if (!server_->tcp_listen_enabled()) { + RTC_LOG(LS_VERBOSE) << "FirewallSocket listen attempt denied"; + return -1; + } + + return AsyncSocketAdapter::Listen(backlog); + } + Socket* Accept(SocketAddress* paddr) override { + SocketAddress addr; + while (Socket* sock = AsyncSocketAdapter::Accept(&addr)) { + if (server_->Check(FP_TCP, addr, GetLocalAddress())) { + if (paddr) + *paddr = addr; + return sock; + } + sock->Close(); + delete sock; + RTC_LOG(LS_VERBOSE) << "FirewallSocket inbound TCP connection from " + << addr.ToSensitiveString() << " to " + << GetLocalAddress().ToSensitiveString() << " denied"; + } + return 0; + } + + private: + FirewallSocketServer* server_; + int type_; +}; + +FirewallSocketServer::FirewallSocketServer(SocketServer* server, + FirewallManager* manager, + bool should_delete_server) + : server_(server), + manager_(manager), + should_delete_server_(should_delete_server), + udp_sockets_enabled_(true), + tcp_sockets_enabled_(true), + tcp_listen_enabled_(true) { + if (manager_) + manager_->AddServer(this); +} + +FirewallSocketServer::~FirewallSocketServer() { + if (manager_) + manager_->RemoveServer(this); + + if (server_ && should_delete_server_) { + delete server_; + server_ = nullptr; + } +} + +void FirewallSocketServer::AddRule(bool allow, + FirewallProtocol p, + FirewallDirection d, + const SocketAddress& addr) { + SocketAddress any; + if (d == FD_IN || d == FD_ANY) { + AddRule(allow, p, any, addr); + } + if (d == FD_OUT || d == FD_ANY) { + AddRule(allow, p, addr, any); + } +} + +void FirewallSocketServer::AddRule(bool allow, + FirewallProtocol p, + const SocketAddress& src, + const SocketAddress& dst) { + Rule r; + r.allow = allow; + r.p = p; + r.src = src; + r.dst = dst; + webrtc::MutexLock scope(&mutex_); + rules_.push_back(r); +} + +void FirewallSocketServer::ClearRules() { + webrtc::MutexLock scope(&mutex_); + rules_.clear(); +} + +bool FirewallSocketServer::Check(FirewallProtocol p, + const SocketAddress& src, + const SocketAddress& dst) { + webrtc::MutexLock scope(&mutex_); + for (size_t i = 0; i < rules_.size(); ++i) { + const Rule& r = rules_[i]; + if ((r.p != p) && (r.p != FP_ANY)) + continue; + if ((r.src.ipaddr() != src.ipaddr()) && !r.src.IsNil()) + continue; + if ((r.src.port() != src.port()) && (r.src.port() != 0)) + continue; + if ((r.dst.ipaddr() != dst.ipaddr()) && !r.dst.IsNil()) + continue; + if ((r.dst.port() != dst.port()) && (r.dst.port() != 0)) + continue; + return r.allow; + } + return true; +} + +void FirewallSocketServer::SetUnbindableIps( + const std::vector<rtc::IPAddress>& unbindable_ips) { + unbindable_ips_ = unbindable_ips; +} + +bool FirewallSocketServer::IsBindableIp(const rtc::IPAddress& ip) { + return !absl::c_linear_search(unbindable_ips_, ip); +} + +Socket* FirewallSocketServer::CreateSocket(int family, int type) { + return WrapSocket(server_->CreateSocket(family, type), type); +} + +void FirewallSocketServer::SetMessageQueue(Thread* queue) { + server_->SetMessageQueue(queue); +} + +bool FirewallSocketServer::Wait(webrtc::TimeDelta max_wait_duration, + bool process_io) { + return server_->Wait(max_wait_duration, process_io); +} + +void FirewallSocketServer::WakeUp() { + return server_->WakeUp(); +} + +Socket* FirewallSocketServer::WrapSocket(Socket* sock, int type) { + if (!sock || (type == SOCK_STREAM && !tcp_sockets_enabled_) || + (type == SOCK_DGRAM && !udp_sockets_enabled_)) { + RTC_LOG(LS_VERBOSE) << "FirewallSocketServer socket creation denied"; + delete sock; + return nullptr; + } + return new FirewallSocket(this, sock, type); +} + +FirewallManager::FirewallManager() {} + +FirewallManager::~FirewallManager() { + RTC_DCHECK(servers_.empty()); +} + +void FirewallManager::AddServer(FirewallSocketServer* server) { + webrtc::MutexLock scope(&mutex_); + servers_.push_back(server); +} + +void FirewallManager::RemoveServer(FirewallSocketServer* server) { + webrtc::MutexLock scope(&mutex_); + servers_.erase(std::remove(servers_.begin(), servers_.end(), server), + servers_.end()); +} + +void FirewallManager::AddRule(bool allow, + FirewallProtocol p, + FirewallDirection d, + const SocketAddress& addr) { + webrtc::MutexLock scope(&mutex_); + for (std::vector<FirewallSocketServer*>::const_iterator it = servers_.begin(); + it != servers_.end(); ++it) { + (*it)->AddRule(allow, p, d, addr); + } +} + +void FirewallManager::ClearRules() { + webrtc::MutexLock scope(&mutex_); + for (std::vector<FirewallSocketServer*>::const_iterator it = servers_.begin(); + it != servers_.end(); ++it) { + (*it)->ClearRules(); + } +} + +} // namespace rtc |