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