"Fossies" - the Fresh Open Source Software Archive

Member "snort3_extra-3.0.3-1/src/inspectors/domain_filter/domain_filter.cc" (23 Sep 2020, 7265 Bytes) of package /linux/misc/snort3_extra-3.0.3-1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "domain_filter.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.0.0-beta2_vs_3.0.3-1.

    1 //--------------------------------------------------------------------------
    2 // Copyright (C) 2018-2020 Cisco and/or its affiliates. All rights reserved.
    3 //
    4 // This program is free software; you can redistribute it and/or modify it
    5 // under the terms of the GNU General Public License Version 2 as published
    6 // by the Free Software Foundation.  You may not use, modify or distribute
    7 // this program under any other version of the GNU General Public License.
    8 //
    9 // This program is distributed in the hope that it will be useful, but
   10 // WITHOUT ANY WARRANTY; without even the implied warranty of
   11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12 // General Public License for more details.
   13 //
   14 // You should have received a copy of the GNU General Public License along
   15 // with this program; if not, write to the Free Software Foundation, Inc.,
   16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   17 //--------------------------------------------------------------------------
   18 
   19 // domain_filter.cc author Russ Combs <rucombs@cisco.com>
   20 
   21 #ifdef HAVE_CONFIG_H
   22 #include "config.h"
   23 #endif
   24 
   25 #include <cassert>
   26 #include <cerrno>
   27 
   28 #include <fstream>
   29 #include <string>
   30 #include <unordered_set>
   31 #include <vector>
   32 
   33 #include "detection/detection_engine.h"
   34 #include "framework/inspector.h"
   35 #include "framework/module.h"
   36 #include "log/messages.h"
   37 #include "main/thread.h"
   38 #include "profiler/profiler.h"
   39 #include "pub_sub/http_events.h"
   40 #include "utils/util.h"
   41 
   42 #define DF_GID 175
   43 #define DF_SID   1
   44 
   45 static const char* s_name = "domain_filter";
   46 static const char* s_help = "alert on configured HTTP domains";
   47 
   48 using DomainList = std::vector<std::string>;
   49 using DomainSet = std::unordered_set<std::string>;
   50 using namespace snort;
   51 
   52 //--------------------------------------------------------------------------
   53 // attributes
   54 //--------------------------------------------------------------------------
   55 
   56 static const Parameter s_params[] =
   57 {
   58     { "file", Parameter::PT_STRING, nullptr, nullptr,
   59       "file with list of domains identifying hosts to be filtered" },
   60 
   61     { "hosts", Parameter::PT_STRING, nullptr, nullptr,
   62       "list of domains identifying hosts to be filtered" },
   63 
   64     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
   65 };
   66 
   67 static const RuleMap s_rules[] =
   68 {
   69     { DF_SID, "configured domain detected" },
   70 
   71     { 0, nullptr }
   72 };
   73 
   74 struct DomainFilterStats
   75 {
   76     PegCount checked;
   77     PegCount filtered;
   78 };
   79 
   80 static THREAD_LOCAL DomainFilterStats s_counts;
   81 
   82 const PegInfo s_pegs[] =
   83 {
   84     { CountType::SUM, "checked", "domains checked" },
   85     { CountType::SUM, "filtered", "domains filtered" },
   86 
   87     { CountType::END, nullptr, nullptr }
   88 };
   89 
   90 static THREAD_LOCAL ProfileStats s_prof;
   91 
   92 //--------------------------------------------------------------------------
   93 // module stuff
   94 //--------------------------------------------------------------------------
   95 
   96 class DomainFilterModule : public Module
   97 {
   98 public:
   99     DomainFilterModule() : Module(s_name, s_help, s_params) { }
  100 
  101     DomainList& get_hosts()
  102     { return hosts; }
  103 
  104     bool set(const char*, Value&, SnortConfig*) override;
  105 
  106     const PegInfo* get_pegs() const override
  107     { return s_pegs; }
  108 
  109     PegCount* get_counts() const override
  110     { return (PegCount*)&s_counts; }
  111 
  112     unsigned get_gid() const override
  113     { return DF_GID; }
  114 
  115     const RuleMap* get_rules() const override
  116     { return s_rules; }
  117 
  118     Usage get_usage() const override
  119     { return INSPECT; }
  120 
  121     ProfileStats* get_profile() const override
  122     { return &s_prof; }
  123 
  124 public:
  125     DomainList hosts;
  126 };
  127 
  128 bool DomainFilterModule::set(const char* fqn, Value& v, SnortConfig* sc)
  129 {
  130     if ( v.is("file") )
  131     {
  132         std::ifstream df(v.get_string());
  133 
  134         if ( !df.is_open() )
  135         {
  136             ParseError("can't open file %s: %s", v.get_string(), get_error(errno));
  137             return false;
  138         }
  139         std::string tok;
  140 
  141         while ( df >> tok )
  142             hosts.push_back(tok);
  143     }
  144     else if ( v.is("hosts") )
  145     {
  146         std::string tok;
  147         v.set_first_token();
  148 
  149         while ( v.get_next_token(tok) )
  150             hosts.push_back(tok);
  151     }
  152     else
  153         return Module::set(fqn, v, sc);
  154 
  155     return true;
  156 }
  157 
  158 //--------------------------------------------------------------------------
  159 // event stuff
  160 //--------------------------------------------------------------------------
  161 
  162 class HttpHandler : public DataHandler
  163 {
  164 public:
  165     HttpHandler(DomainSet& sv) : DataHandler(s_name), hosts(sv) { }
  166 
  167     void handle(DataEvent& e, Flow*) override;
  168 
  169 private:
  170     DomainSet& hosts;
  171 };
  172 
  173 void HttpHandler::handle(DataEvent& de, Flow*)
  174 {
  175     Profile profile(s_prof);
  176     HttpEvent* he = (HttpEvent*)&de;
  177 
  178     int32_t len;
  179     const char* s = (const char*)he->get_host(len);
  180 
  181     if ( !s or len < 1 )
  182         return;
  183 
  184     std::string h(s, len);
  185     transform(h.begin(), h.end(), h.begin(), ::tolower);
  186 
  187     DomainSet::const_iterator it = hosts.find(h);
  188 
  189     if ( it != hosts.end() )
  190     {
  191         DetectionEngine::queue_event(DF_GID, DF_SID);
  192         ++s_counts.filtered;
  193     }
  194     ++s_counts.checked;
  195 }
  196 
  197 //--------------------------------------------------------------------------
  198 // inspector stuff
  199 //--------------------------------------------------------------------------
  200 
  201 class DomainFilter : public Inspector
  202 {
  203 public:
  204     DomainFilter(DomainList&);
  205     void show(const SnortConfig*) const override;
  206     void eval(Packet*) override { }
  207 
  208 private:
  209     DomainSet hosts;
  210 };
  211 
  212 DomainFilter::DomainFilter(DomainList& sv)
  213 {
  214     hosts.insert(sv.begin(), sv.end());
  215     sv.clear();
  216 
  217     if ( !hosts.empty() )
  218         DataBus::subscribe(HTTP_REQUEST_HEADER_EVENT_KEY, new HttpHandler(hosts));
  219 }
  220 
  221 void DomainFilter::show(const SnortConfig*) const
  222 {
  223     DomainList domain_list;
  224 
  225     for (const auto& host : hosts)
  226         domain_list.push_back(host);
  227     std::sort(domain_list.begin(), domain_list.end());
  228 
  229     std::string sorted_hosts;
  230     for (const auto& host : domain_list)
  231     {
  232         if (!sorted_hosts.empty())
  233             sorted_hosts += " ";
  234         sorted_hosts += host;
  235     }
  236 
  237     if ( sorted_hosts.empty() )
  238         sorted_hosts = "none";
  239 
  240     ConfigLogger::log_list("hosts", sorted_hosts.c_str());
  241 }
  242 
  243 //--------------------------------------------------------------------------
  244 // api stuff
  245 //--------------------------------------------------------------------------
  246 
  247 static Module* mod_ctor()
  248 { return new DomainFilterModule; }
  249 
  250 static void mod_dtor(Module* pm)
  251 { delete pm; }
  252 
  253 static Inspector* df_ctor(Module* m)
  254 {
  255     DomainFilterModule* pm = (DomainFilterModule*)m;
  256     return new DomainFilter(pm->get_hosts());
  257 }
  258 
  259 static void df_dtor(Inspector* p)
  260 {
  261     assert(p);
  262     delete p;
  263 }
  264 
  265 static const InspectApi df_api =
  266 {
  267     {
  268         PT_INSPECTOR,
  269         sizeof(InspectApi),
  270         INSAPI_VERSION,
  271         0,
  272         API_RESERVED,
  273         API_OPTIONS,
  274         s_name,
  275         s_help,
  276         mod_ctor,
  277         mod_dtor
  278     },
  279     IT_PASSIVE,
  280 
  281     0,        // proto_bits;
  282     nullptr,  // buffers
  283     nullptr,  // service
  284     nullptr,  // pinit
  285     nullptr,  // pterm
  286     nullptr,  // tinit
  287     nullptr,  // tterm
  288 
  289     df_ctor,
  290     df_dtor,
  291 
  292     nullptr,  // ssn
  293     nullptr,  // reset
  294 };
  295 
  296 SO_PUBLIC const BaseApi* snort_plugins[] =
  297 {
  298     &df_api.base,
  299     nullptr
  300 };
  301