• 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 "webrtc/base/firewallsocketserver.h"
12 
13 #include <assert.h>
14 
15 #include <algorithm>
16 
17 #include "webrtc/base/asyncsocket.h"
18 #include "webrtc/base/logging.h"
19 
20 namespace rtc {
21 
22 class FirewallSocket : public AsyncSocketAdapter {
23  public:
FirewallSocket(FirewallSocketServer * server,AsyncSocket * socket,int type)24   FirewallSocket(FirewallSocketServer* server, AsyncSocket* socket, int type)
25     : AsyncSocketAdapter(socket), server_(server), type_(type) {
26   }
27 
Connect(const SocketAddress & addr)28   int Connect(const SocketAddress& addr) override {
29     if (type_ == SOCK_STREAM) {
30       if (!server_->Check(FP_TCP, GetLocalAddress(), addr)) {
31         LOG(LS_VERBOSE) << "FirewallSocket outbound TCP connection from "
32                         << GetLocalAddress().ToSensitiveString() << " to "
33                         << addr.ToSensitiveString() << " denied";
34         // TODO: Handle this asynchronously.
35         SetError(EHOSTUNREACH);
36         return SOCKET_ERROR;
37       }
38     }
39     return AsyncSocketAdapter::Connect(addr);
40   }
Send(const void * pv,size_t cb)41   int Send(const void* pv, size_t cb) override {
42     return SendTo(pv, cb, GetRemoteAddress());
43   }
SendTo(const void * pv,size_t cb,const SocketAddress & addr)44   int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override {
45     if (type_ == SOCK_DGRAM) {
46       if (!server_->Check(FP_UDP, GetLocalAddress(), addr)) {
47         LOG(LS_VERBOSE) << "FirewallSocket outbound UDP packet from "
48                         << GetLocalAddress().ToSensitiveString() << " to "
49                         << addr.ToSensitiveString() << " dropped";
50         return static_cast<int>(cb);
51       }
52     }
53     return AsyncSocketAdapter::SendTo(pv, cb, addr);
54   }
Recv(void * pv,size_t cb)55   int Recv(void* pv, size_t cb) override {
56     SocketAddress addr;
57     return RecvFrom(pv, cb, &addr);
58   }
RecvFrom(void * pv,size_t cb,SocketAddress * paddr)59   int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override {
60     if (type_ == SOCK_DGRAM) {
61       while (true) {
62         int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
63         if (res <= 0)
64           return res;
65         if (server_->Check(FP_UDP, *paddr, GetLocalAddress()))
66           return res;
67         LOG(LS_VERBOSE) << "FirewallSocket inbound UDP packet from "
68                         << paddr->ToSensitiveString() << " to "
69                         << GetLocalAddress().ToSensitiveString() << " dropped";
70       }
71     }
72     return AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
73   }
74 
Listen(int backlog)75   int Listen(int backlog) override {
76     if (!server_->tcp_listen_enabled()) {
77       LOG(LS_VERBOSE) << "FirewallSocket listen attempt denied";
78       return -1;
79     }
80 
81     return AsyncSocketAdapter::Listen(backlog);
82   }
Accept(SocketAddress * paddr)83   AsyncSocket* Accept(SocketAddress* paddr) override {
84     SocketAddress addr;
85     while (AsyncSocket* sock = AsyncSocketAdapter::Accept(&addr)) {
86       if (server_->Check(FP_TCP, addr, GetLocalAddress())) {
87         if (paddr)
88           *paddr = addr;
89         return sock;
90       }
91       sock->Close();
92       delete sock;
93       LOG(LS_VERBOSE) << "FirewallSocket inbound TCP connection from "
94                       << addr.ToSensitiveString() << " to "
95                       << GetLocalAddress().ToSensitiveString() << " denied";
96     }
97     return 0;
98   }
99 
100  private:
101   FirewallSocketServer* server_;
102   int type_;
103 };
104 
FirewallSocketServer(SocketServer * server,FirewallManager * manager,bool should_delete_server)105 FirewallSocketServer::FirewallSocketServer(SocketServer* server,
106                                            FirewallManager* manager,
107                                            bool should_delete_server)
108     : server_(server), manager_(manager),
109       should_delete_server_(should_delete_server),
110       udp_sockets_enabled_(true), tcp_sockets_enabled_(true),
111       tcp_listen_enabled_(true) {
112   if (manager_)
113     manager_->AddServer(this);
114 }
115 
~FirewallSocketServer()116 FirewallSocketServer::~FirewallSocketServer() {
117   if (manager_)
118     manager_->RemoveServer(this);
119 
120   if (server_ && should_delete_server_) {
121     delete server_;
122     server_ = NULL;
123   }
124 }
125 
AddRule(bool allow,FirewallProtocol p,FirewallDirection d,const SocketAddress & addr)126 void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p,
127                                    FirewallDirection d,
128                                    const SocketAddress& addr) {
129   SocketAddress any;
130   if (d == FD_IN || d == FD_ANY) {
131     AddRule(allow, p, any, addr);
132   }
133   if (d == FD_OUT || d == FD_ANY) {
134     AddRule(allow, p, addr, any);
135   }
136 }
137 
138 
AddRule(bool allow,FirewallProtocol p,const SocketAddress & src,const SocketAddress & dst)139 void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p,
140                                    const SocketAddress& src,
141                                    const SocketAddress& dst) {
142   Rule r;
143   r.allow = allow;
144   r.p = p;
145   r.src = src;
146   r.dst = dst;
147   CritScope scope(&crit_);
148   rules_.push_back(r);
149 }
150 
ClearRules()151 void FirewallSocketServer::ClearRules() {
152   CritScope scope(&crit_);
153   rules_.clear();
154 }
155 
Check(FirewallProtocol p,const SocketAddress & src,const SocketAddress & dst)156 bool FirewallSocketServer::Check(FirewallProtocol p,
157                                  const SocketAddress& src,
158                                  const SocketAddress& dst) {
159   CritScope scope(&crit_);
160   for (size_t i = 0; i < rules_.size(); ++i) {
161     const Rule& r = rules_[i];
162     if ((r.p != p) && (r.p != FP_ANY))
163       continue;
164     if ((r.src.ipaddr() != src.ipaddr()) && !r.src.IsNil())
165       continue;
166     if ((r.src.port() != src.port()) && (r.src.port() != 0))
167       continue;
168     if ((r.dst.ipaddr() != dst.ipaddr()) && !r.dst.IsNil())
169       continue;
170     if ((r.dst.port() != dst.port()) && (r.dst.port() != 0))
171       continue;
172     return r.allow;
173   }
174   return true;
175 }
176 
CreateSocket(int type)177 Socket* FirewallSocketServer::CreateSocket(int type) {
178   return CreateSocket(AF_INET, type);
179 }
180 
CreateSocket(int family,int type)181 Socket* FirewallSocketServer::CreateSocket(int family, int type) {
182   return WrapSocket(server_->CreateAsyncSocket(family, type), type);
183 }
184 
CreateAsyncSocket(int type)185 AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int type) {
186   return CreateAsyncSocket(AF_INET, type);
187 }
188 
CreateAsyncSocket(int family,int type)189 AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int family, int type) {
190   return WrapSocket(server_->CreateAsyncSocket(family, type), type);
191 }
192 
SetMessageQueue(MessageQueue * queue)193 void FirewallSocketServer::SetMessageQueue(MessageQueue* queue) {
194   server_->SetMessageQueue(queue);
195 }
196 
Wait(int cms,bool process_io)197 bool FirewallSocketServer::Wait(int cms, bool process_io) {
198   return server_->Wait(cms, process_io);
199 }
200 
WakeUp()201 void FirewallSocketServer::WakeUp() {
202   return server_->WakeUp();
203 }
204 
WrapSocket(AsyncSocket * sock,int type)205 AsyncSocket* FirewallSocketServer::WrapSocket(AsyncSocket* sock, int type) {
206   if (!sock ||
207       (type == SOCK_STREAM && !tcp_sockets_enabled_) ||
208       (type == SOCK_DGRAM && !udp_sockets_enabled_)) {
209     LOG(LS_VERBOSE) << "FirewallSocketServer socket creation denied";
210     delete sock;
211     return NULL;
212   }
213   return new FirewallSocket(this, sock, type);
214 }
215 
FirewallManager()216 FirewallManager::FirewallManager() {
217 }
218 
~FirewallManager()219 FirewallManager::~FirewallManager() {
220   assert(servers_.empty());
221 }
222 
AddServer(FirewallSocketServer * server)223 void FirewallManager::AddServer(FirewallSocketServer* server) {
224   CritScope scope(&crit_);
225   servers_.push_back(server);
226 }
227 
RemoveServer(FirewallSocketServer * server)228 void FirewallManager::RemoveServer(FirewallSocketServer* server) {
229   CritScope scope(&crit_);
230   servers_.erase(std::remove(servers_.begin(), servers_.end(), server),
231                  servers_.end());
232 }
233 
AddRule(bool allow,FirewallProtocol p,FirewallDirection d,const SocketAddress & addr)234 void FirewallManager::AddRule(bool allow, FirewallProtocol p,
235                               FirewallDirection d, const SocketAddress& addr) {
236   CritScope scope(&crit_);
237   for (std::vector<FirewallSocketServer*>::const_iterator it =
238       servers_.begin(); it != servers_.end(); ++it) {
239     (*it)->AddRule(allow, p, d, addr);
240   }
241 }
242 
ClearRules()243 void FirewallManager::ClearRules() {
244   CritScope scope(&crit_);
245   for (std::vector<FirewallSocketServer*>::const_iterator it =
246       servers_.begin(); it != servers_.end(); ++it) {
247     (*it)->ClearRules();
248   }
249 }
250 
251 }  // namespace rtc
252