summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/rtc_base/firewall_socket_server.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/rtc_base/firewall_socket_server.cc
parentInitial commit. (diff)
downloadfirefox-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.cc268
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