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,AsyncSocket * socket,int type)28 FirewallSocket(FirewallSocketServer* server, AsyncSocket* 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 AsyncSocket* Accept(SocketAddress* paddr) override {
100 SocketAddress addr;
101 while (AsyncSocket* 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_->CreateAsyncSocket(family, type), type);
207 }
208
CreateAsyncSocket(int family,int type)209 AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int family, int type) {
210 return WrapSocket(server_->CreateAsyncSocket(family, type), type);
211 }
212
SetMessageQueue(Thread * queue)213 void FirewallSocketServer::SetMessageQueue(Thread* queue) {
214 server_->SetMessageQueue(queue);
215 }
216
Wait(int cms,bool process_io)217 bool FirewallSocketServer::Wait(int cms, bool process_io) {
218 return server_->Wait(cms, process_io);
219 }
220
WakeUp()221 void FirewallSocketServer::WakeUp() {
222 return server_->WakeUp();
223 }
224
WrapSocket(AsyncSocket * sock,int type)225 AsyncSocket* FirewallSocketServer::WrapSocket(AsyncSocket* sock, int type) {
226 if (!sock || (type == SOCK_STREAM && !tcp_sockets_enabled_) ||
227 (type == SOCK_DGRAM && !udp_sockets_enabled_)) {
228 RTC_LOG(LS_VERBOSE) << "FirewallSocketServer socket creation denied";
229 delete sock;
230 return nullptr;
231 }
232 return new FirewallSocket(this, sock, type);
233 }
234
FirewallManager()235 FirewallManager::FirewallManager() {}
236
~FirewallManager()237 FirewallManager::~FirewallManager() {
238 RTC_DCHECK(servers_.empty());
239 }
240
AddServer(FirewallSocketServer * server)241 void FirewallManager::AddServer(FirewallSocketServer* server) {
242 webrtc::MutexLock scope(&mutex_);
243 servers_.push_back(server);
244 }
245
RemoveServer(FirewallSocketServer * server)246 void FirewallManager::RemoveServer(FirewallSocketServer* server) {
247 webrtc::MutexLock scope(&mutex_);
248 servers_.erase(std::remove(servers_.begin(), servers_.end(), server),
249 servers_.end());
250 }
251
AddRule(bool allow,FirewallProtocol p,FirewallDirection d,const SocketAddress & addr)252 void FirewallManager::AddRule(bool allow,
253 FirewallProtocol p,
254 FirewallDirection d,
255 const SocketAddress& addr) {
256 webrtc::MutexLock scope(&mutex_);
257 for (std::vector<FirewallSocketServer*>::const_iterator it = servers_.begin();
258 it != servers_.end(); ++it) {
259 (*it)->AddRule(allow, p, d, addr);
260 }
261 }
262
ClearRules()263 void FirewallManager::ClearRules() {
264 webrtc::MutexLock scope(&mutex_);
265 for (std::vector<FirewallSocketServer*>::const_iterator it = servers_.begin();
266 it != servers_.end(); ++it) {
267 (*it)->ClearRules();
268 }
269 }
270
271 } // namespace rtc
272