• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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