1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_base/firewall_socket_server.h"
12
13 #include <errno.h>
14 #include <stddef.h>
15 #include <stdint.h>
16
17 #include <string>
18
19 #include "absl/algorithm/container.h"
20 #include "rtc_base/async_socket.h"
21 #include "rtc_base/checks.h"
22 #include "rtc_base/logging.h"
23
24 namespace rtc {
25
26 class FirewallSocket : public AsyncSocketAdapter {
27 public:
FirewallSocket(FirewallSocketServer * server,Socket * socket,int type)28 FirewallSocket(FirewallSocketServer* server, Socket* socket, int type)
29 : AsyncSocketAdapter(socket), server_(server), type_(type) {}
30
Bind(const SocketAddress & addr)31 int Bind(const SocketAddress& addr) override {
32 if (!server_->IsBindableIp(addr.ipaddr())) {
33 SetError(EINVAL);
34 return SOCKET_ERROR;
35 }
36 return AsyncSocketAdapter::Bind(addr);
37 }
38
Connect(const SocketAddress & addr)39 int Connect(const SocketAddress& addr) override {
40 if (type_ == SOCK_STREAM) {
41 if (!server_->Check(FP_TCP, GetLocalAddress(), addr)) {
42 RTC_LOG(LS_VERBOSE) << "FirewallSocket outbound TCP connection from "
43 << GetLocalAddress().ToSensitiveString() << " to "
44 << addr.ToSensitiveString() << " denied";
45 // TODO: Handle this asynchronously.
46 SetError(EHOSTUNREACH);
47 return SOCKET_ERROR;
48 }
49 }
50 return AsyncSocketAdapter::Connect(addr);
51 }
Send(const void * pv,size_t cb)52 int Send(const void* pv, size_t cb) override {
53 return SendTo(pv, cb, GetRemoteAddress());
54 }
SendTo(const void * pv,size_t cb,const SocketAddress & addr)55 int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override {
56 RTC_DCHECK(type_ == SOCK_DGRAM || type_ == SOCK_STREAM);
57 FirewallProtocol protocol = (type_ == SOCK_DGRAM) ? FP_UDP : FP_TCP;
58 if (!server_->Check(protocol, GetLocalAddress(), addr)) {
59 RTC_LOG(LS_VERBOSE) << "FirewallSocket outbound packet with type "
60 << type_ << " from "
61 << GetLocalAddress().ToSensitiveString() << " to "
62 << addr.ToSensitiveString() << " dropped";
63 return static_cast<int>(cb);
64 }
65 return AsyncSocketAdapter::SendTo(pv, cb, addr);
66 }
Recv(void * pv,size_t cb,int64_t * timestamp)67 int Recv(void* pv, size_t cb, int64_t* timestamp) override {
68 SocketAddress addr;
69 return RecvFrom(pv, cb, &addr, timestamp);
70 }
RecvFrom(void * pv,size_t cb,SocketAddress * paddr,int64_t * timestamp)71 int RecvFrom(void* pv,
72 size_t cb,
73 SocketAddress* paddr,
74 int64_t* timestamp) override {
75 if (type_ == SOCK_DGRAM) {
76 while (true) {
77 int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr, timestamp);
78 if (res <= 0)
79 return res;
80 if (server_->Check(FP_UDP, *paddr, GetLocalAddress()))
81 return res;
82 RTC_LOG(LS_VERBOSE)
83 << "FirewallSocket inbound UDP packet from "
84 << paddr->ToSensitiveString() << " to "
85 << GetLocalAddress().ToSensitiveString() << " dropped";
86 }
87 }
88 return AsyncSocketAdapter::RecvFrom(pv, cb, paddr, timestamp);
89 }
90
Listen(int backlog)91 int Listen(int backlog) override {
92 if (!server_->tcp_listen_enabled()) {
93 RTC_LOG(LS_VERBOSE) << "FirewallSocket listen attempt denied";
94 return -1;
95 }
96
97 return AsyncSocketAdapter::Listen(backlog);
98 }
Accept(SocketAddress * paddr)99 Socket* Accept(SocketAddress* paddr) override {
100 SocketAddress addr;
101 while (Socket* sock = AsyncSocketAdapter::Accept(&addr)) {
102 if (server_->Check(FP_TCP, addr, GetLocalAddress())) {
103 if (paddr)
104 *paddr = addr;
105 return sock;
106 }
107 sock->Close();
108 delete sock;
109 RTC_LOG(LS_VERBOSE) << "FirewallSocket inbound TCP connection from "
110 << addr.ToSensitiveString() << " to "
111 << GetLocalAddress().ToSensitiveString() << " denied";
112 }
113 return 0;
114 }
115
116 private:
117 FirewallSocketServer* server_;
118 int type_;
119 };
120
FirewallSocketServer(SocketServer * server,FirewallManager * manager,bool should_delete_server)121 FirewallSocketServer::FirewallSocketServer(SocketServer* server,
122 FirewallManager* manager,
123 bool should_delete_server)
124 : server_(server),
125 manager_(manager),
126 should_delete_server_(should_delete_server),
127 udp_sockets_enabled_(true),
128 tcp_sockets_enabled_(true),
129 tcp_listen_enabled_(true) {
130 if (manager_)
131 manager_->AddServer(this);
132 }
133
~FirewallSocketServer()134 FirewallSocketServer::~FirewallSocketServer() {
135 if (manager_)
136 manager_->RemoveServer(this);
137
138 if (server_ && should_delete_server_) {
139 delete server_;
140 server_ = nullptr;
141 }
142 }
143
AddRule(bool allow,FirewallProtocol p,FirewallDirection d,const SocketAddress & addr)144 void FirewallSocketServer::AddRule(bool allow,
145 FirewallProtocol p,
146 FirewallDirection d,
147 const SocketAddress& addr) {
148 SocketAddress any;
149 if (d == FD_IN || d == FD_ANY) {
150 AddRule(allow, p, any, addr);
151 }
152 if (d == FD_OUT || d == FD_ANY) {
153 AddRule(allow, p, addr, any);
154 }
155 }
156
AddRule(bool allow,FirewallProtocol p,const SocketAddress & src,const SocketAddress & dst)157 void FirewallSocketServer::AddRule(bool allow,
158 FirewallProtocol p,
159 const SocketAddress& src,
160 const SocketAddress& dst) {
161 Rule r;
162 r.allow = allow;
163 r.p = p;
164 r.src = src;
165 r.dst = dst;
166 webrtc::MutexLock scope(&mutex_);
167 rules_.push_back(r);
168 }
169
ClearRules()170 void FirewallSocketServer::ClearRules() {
171 webrtc::MutexLock scope(&mutex_);
172 rules_.clear();
173 }
174
Check(FirewallProtocol p,const SocketAddress & src,const SocketAddress & dst)175 bool FirewallSocketServer::Check(FirewallProtocol p,
176 const SocketAddress& src,
177 const SocketAddress& dst) {
178 webrtc::MutexLock scope(&mutex_);
179 for (size_t i = 0; i < rules_.size(); ++i) {
180 const Rule& r = rules_[i];
181 if ((r.p != p) && (r.p != FP_ANY))
182 continue;
183 if ((r.src.ipaddr() != src.ipaddr()) && !r.src.IsNil())
184 continue;
185 if ((r.src.port() != src.port()) && (r.src.port() != 0))
186 continue;
187 if ((r.dst.ipaddr() != dst.ipaddr()) && !r.dst.IsNil())
188 continue;
189 if ((r.dst.port() != dst.port()) && (r.dst.port() != 0))
190 continue;
191 return r.allow;
192 }
193 return true;
194 }
195
SetUnbindableIps(const std::vector<rtc::IPAddress> & unbindable_ips)196 void FirewallSocketServer::SetUnbindableIps(
197 const std::vector<rtc::IPAddress>& unbindable_ips) {
198 unbindable_ips_ = unbindable_ips;
199 }
200
IsBindableIp(const rtc::IPAddress & ip)201 bool FirewallSocketServer::IsBindableIp(const rtc::IPAddress& ip) {
202 return !absl::c_linear_search(unbindable_ips_, ip);
203 }
204
CreateSocket(int family,int type)205 Socket* FirewallSocketServer::CreateSocket(int family, int type) {
206 return WrapSocket(server_->CreateSocket(family, type), type);
207 }
208
SetMessageQueue(Thread * queue)209 void FirewallSocketServer::SetMessageQueue(Thread* queue) {
210 server_->SetMessageQueue(queue);
211 }
212
Wait(webrtc::TimeDelta max_wait_duration,bool process_io)213 bool FirewallSocketServer::Wait(webrtc::TimeDelta max_wait_duration,
214 bool process_io) {
215 return server_->Wait(max_wait_duration, process_io);
216 }
217
WakeUp()218 void FirewallSocketServer::WakeUp() {
219 return server_->WakeUp();
220 }
221
WrapSocket(Socket * sock,int type)222 Socket* FirewallSocketServer::WrapSocket(Socket* sock, int type) {
223 if (!sock || (type == SOCK_STREAM && !tcp_sockets_enabled_) ||
224 (type == SOCK_DGRAM && !udp_sockets_enabled_)) {
225 RTC_LOG(LS_VERBOSE) << "FirewallSocketServer socket creation denied";
226 delete sock;
227 return nullptr;
228 }
229 return new FirewallSocket(this, sock, type);
230 }
231
FirewallManager()232 FirewallManager::FirewallManager() {}
233
~FirewallManager()234 FirewallManager::~FirewallManager() {
235 RTC_DCHECK(servers_.empty());
236 }
237
AddServer(FirewallSocketServer * server)238 void FirewallManager::AddServer(FirewallSocketServer* server) {
239 webrtc::MutexLock scope(&mutex_);
240 servers_.push_back(server);
241 }
242
RemoveServer(FirewallSocketServer * server)243 void FirewallManager::RemoveServer(FirewallSocketServer* server) {
244 webrtc::MutexLock scope(&mutex_);
245 servers_.erase(std::remove(servers_.begin(), servers_.end(), server),
246 servers_.end());
247 }
248
AddRule(bool allow,FirewallProtocol p,FirewallDirection d,const SocketAddress & addr)249 void FirewallManager::AddRule(bool allow,
250 FirewallProtocol p,
251 FirewallDirection d,
252 const SocketAddress& addr) {
253 webrtc::MutexLock scope(&mutex_);
254 for (std::vector<FirewallSocketServer*>::const_iterator it = servers_.begin();
255 it != servers_.end(); ++it) {
256 (*it)->AddRule(allow, p, d, addr);
257 }
258 }
259
ClearRules()260 void FirewallManager::ClearRules() {
261 webrtc::MutexLock scope(&mutex_);
262 for (std::vector<FirewallSocketServer*>::const_iterator it = servers_.begin();
263 it != servers_.end(); ++it) {
264 (*it)->ClearRules();
265 }
266 }
267
268 } // namespace rtc
269