Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / firewallsocketserver.cc
1 /*
2  * libjingle
3  * Copyright 2004--2005, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "talk/base/firewallsocketserver.h"
29
30 #include <assert.h>
31
32 #include <algorithm>
33
34 #include "talk/base/asyncsocket.h"
35 #include "talk/base/logging.h"
36
37 namespace talk_base {
38
39 class FirewallSocket : public AsyncSocketAdapter {
40  public:
41   FirewallSocket(FirewallSocketServer* server, AsyncSocket* socket, int type)
42     : AsyncSocketAdapter(socket), server_(server), type_(type) {
43   }
44
45   virtual int Connect(const SocketAddress& addr) {
46     if (type_ == SOCK_STREAM) {
47       if (!server_->Check(FP_TCP, GetLocalAddress(), addr)) {
48         LOG(LS_VERBOSE) << "FirewallSocket outbound TCP connection from "
49                         << GetLocalAddress().ToSensitiveString() << " to "
50                         << addr.ToSensitiveString() << " denied";
51         // TODO: Handle this asynchronously.
52         SetError(EHOSTUNREACH);
53         return SOCKET_ERROR;
54       }
55     }
56     return AsyncSocketAdapter::Connect(addr);
57   }
58   virtual int Send(const void* pv, size_t cb) {
59     return SendTo(pv, cb, GetRemoteAddress());
60   }
61   virtual int SendTo(const void* pv, size_t cb, const SocketAddress& addr) {
62     if (type_ == SOCK_DGRAM) {
63       if (!server_->Check(FP_UDP, GetLocalAddress(), addr)) {
64         LOG(LS_VERBOSE) << "FirewallSocket outbound UDP packet from "
65                         << GetLocalAddress().ToSensitiveString() << " to "
66                         << addr.ToSensitiveString() << " dropped";
67         return static_cast<int>(cb);
68       }
69     }
70     return AsyncSocketAdapter::SendTo(pv, cb, addr);
71   }
72   virtual int Recv(void* pv, size_t cb) {
73     SocketAddress addr;
74     return RecvFrom(pv, cb, &addr);
75   }
76   virtual int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) {
77     if (type_ == SOCK_DGRAM) {
78       while (true) {
79         int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
80         if (res <= 0)
81           return res;
82         if (server_->Check(FP_UDP, *paddr, GetLocalAddress()))
83           return res;
84         LOG(LS_VERBOSE) << "FirewallSocket inbound UDP packet from "
85                         << paddr->ToSensitiveString() << " to "
86                         << GetLocalAddress().ToSensitiveString() << " dropped";
87       }
88     }
89     return AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
90   }
91
92   virtual int Listen(int backlog) {
93     if (!server_->tcp_listen_enabled()) {
94       LOG(LS_VERBOSE) << "FirewallSocket listen attempt denied";
95       return -1;
96     }
97
98     return AsyncSocketAdapter::Listen(backlog);
99   }
100   virtual AsyncSocket* Accept(SocketAddress* paddr) {
101     SocketAddress addr;
102     while (AsyncSocket* sock = AsyncSocketAdapter::Accept(&addr)) {
103       if (server_->Check(FP_TCP, addr, GetLocalAddress())) {
104         if (paddr)
105           *paddr = addr;
106         return sock;
107       }
108       sock->Close();
109       delete sock;
110       LOG(LS_VERBOSE) << "FirewallSocket inbound TCP connection from "
111                       << addr.ToSensitiveString() << " to "
112                       << GetLocalAddress().ToSensitiveString() << " denied";
113     }
114     return 0;
115   }
116
117  private:
118   FirewallSocketServer* server_;
119   int type_;
120 };
121
122 FirewallSocketServer::FirewallSocketServer(SocketServer* server,
123                                            FirewallManager* manager,
124                                            bool should_delete_server)
125     : server_(server), manager_(manager),
126       should_delete_server_(should_delete_server),
127       udp_sockets_enabled_(true), tcp_sockets_enabled_(true),
128       tcp_listen_enabled_(true) {
129   if (manager_)
130     manager_->AddServer(this);
131 }
132
133 FirewallSocketServer::~FirewallSocketServer() {
134   if (manager_)
135     manager_->RemoveServer(this);
136
137   if (server_ && should_delete_server_) {
138     delete server_;
139     server_ = NULL;
140   }
141 }
142
143 void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p,
144                                    FirewallDirection d,
145                                    const SocketAddress& addr) {
146   SocketAddress src, dst;
147   if (d == FD_IN) {
148     dst = addr;
149   } else {
150     src = addr;
151   }
152   AddRule(allow, p, src, dst);
153 }
154
155
156 void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p,
157                                    const SocketAddress& src,
158                                    const SocketAddress& dst) {
159   Rule r;
160   r.allow = allow;
161   r.p = p;
162   r.src = src;
163   r.dst = dst;
164   CritScope scope(&crit_);
165   rules_.push_back(r);
166 }
167
168 void FirewallSocketServer::ClearRules() {
169   CritScope scope(&crit_);
170   rules_.clear();
171 }
172
173 bool FirewallSocketServer::Check(FirewallProtocol p,
174                                  const SocketAddress& src,
175                                  const SocketAddress& dst) {
176   CritScope scope(&crit_);
177   for (size_t i = 0; i < rules_.size(); ++i) {
178     const Rule& r = rules_[i];
179     if ((r.p != p) && (r.p != FP_ANY))
180       continue;
181     if ((r.src.ipaddr() != src.ipaddr()) && !r.src.IsNil())
182       continue;
183     if ((r.src.port() != src.port()) && (r.src.port() != 0))
184       continue;
185     if ((r.dst.ipaddr() != dst.ipaddr()) && !r.dst.IsNil())
186       continue;
187     if ((r.dst.port() != dst.port()) && (r.dst.port() != 0))
188       continue;
189     return r.allow;
190   }
191   return true;
192 }
193
194 Socket* FirewallSocketServer::CreateSocket(int type) {
195   return CreateSocket(AF_INET, type);
196 }
197
198 Socket* FirewallSocketServer::CreateSocket(int family, int type) {
199   return WrapSocket(server_->CreateAsyncSocket(family, type), type);
200 }
201
202 AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int type) {
203   return CreateAsyncSocket(AF_INET, type);
204 }
205
206 AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int family, int type) {
207   return WrapSocket(server_->CreateAsyncSocket(family, type), type);
208 }
209
210 AsyncSocket* FirewallSocketServer::WrapSocket(AsyncSocket* sock, int type) {
211   if (!sock ||
212       (type == SOCK_STREAM && !tcp_sockets_enabled_) ||
213       (type == SOCK_DGRAM && !udp_sockets_enabled_)) {
214     LOG(LS_VERBOSE) << "FirewallSocketServer socket creation denied";
215     delete sock;
216     return NULL;
217   }
218   return new FirewallSocket(this, sock, type);
219 }
220
221 FirewallManager::FirewallManager() {
222 }
223
224 FirewallManager::~FirewallManager() {
225   assert(servers_.empty());
226 }
227
228 void FirewallManager::AddServer(FirewallSocketServer* server) {
229   CritScope scope(&crit_);
230   servers_.push_back(server);
231 }
232
233 void FirewallManager::RemoveServer(FirewallSocketServer* server) {
234   CritScope scope(&crit_);
235   servers_.erase(std::remove(servers_.begin(), servers_.end(), server),
236                  servers_.end());
237 }
238
239 void FirewallManager::AddRule(bool allow, FirewallProtocol p,
240                               FirewallDirection d, const SocketAddress& addr) {
241   CritScope scope(&crit_);
242   for (std::vector<FirewallSocketServer*>::const_iterator it =
243       servers_.begin(); it != servers_.end(); ++it) {
244     (*it)->AddRule(allow, p, d, addr);
245   }
246 }
247
248 void FirewallManager::ClearRules() {
249   CritScope scope(&crit_);
250   for (std::vector<FirewallSocketServer*>::const_iterator it =
251       servers_.begin(); it != servers_.end(); ++it) {
252     (*it)->ClearRules();
253   }
254 }
255
256 }  // namespace talk_base