Home | History | Annotate | Download | only in base
      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:
     24   FirewallSocket(FirewallSocketServer* server, AsyncSocket* socket, int type)
     25     : AsyncSocketAdapter(socket), server_(server), type_(type) {
     26   }
     27 
     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   }
     41   int Send(const void* pv, size_t cb) override {
     42     return SendTo(pv, cb, GetRemoteAddress());
     43   }
     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   }
     55   int Recv(void* pv, size_t cb) override {
     56     SocketAddress addr;
     57     return RecvFrom(pv, cb, &addr);
     58   }
     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 
     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   }
     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 
    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 
    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 
    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 
    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 
    151 void FirewallSocketServer::ClearRules() {
    152   CritScope scope(&crit_);
    153   rules_.clear();
    154 }
    155 
    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 
    177 Socket* FirewallSocketServer::CreateSocket(int type) {
    178   return CreateSocket(AF_INET, type);
    179 }
    180 
    181 Socket* FirewallSocketServer::CreateSocket(int family, int type) {
    182   return WrapSocket(server_->CreateAsyncSocket(family, type), type);
    183 }
    184 
    185 AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int type) {
    186   return CreateAsyncSocket(AF_INET, type);
    187 }
    188 
    189 AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int family, int type) {
    190   return WrapSocket(server_->CreateAsyncSocket(family, type), type);
    191 }
    192 
    193 void FirewallSocketServer::SetMessageQueue(MessageQueue* queue) {
    194   server_->SetMessageQueue(queue);
    195 }
    196 
    197 bool FirewallSocketServer::Wait(int cms, bool process_io) {
    198   return server_->Wait(cms, process_io);
    199 }
    200 
    201 void FirewallSocketServer::WakeUp() {
    202   return server_->WakeUp();
    203 }
    204 
    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 
    216 FirewallManager::FirewallManager() {
    217 }
    218 
    219 FirewallManager::~FirewallManager() {
    220   assert(servers_.empty());
    221 }
    222 
    223 void FirewallManager::AddServer(FirewallSocketServer* server) {
    224   CritScope scope(&crit_);
    225   servers_.push_back(server);
    226 }
    227 
    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 
    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 
    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