"Fossies" - the Fresh Open Source Software Archive

Member "snort3_extra-3.1.51.0/src/inspectors/domain_filter/domain_filter.cc" (20 Dec 2022, 7285 Bytes) of package /linux/misc/snort3_extra-3.1.51.0.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 last Fossies "Diffs" side-by-side code changes report: 3.1.48.0_vs_3.1.50.0.

    1 //--------------------------------------------------------------------------
    2 // Copyright (C) 2018-2022 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 #include <cassert>
   22 #include <cerrno>
   23 
   24 #include <fstream>
   25 #include <string>
   26 #include <unordered_set>
   27 #include <vector>
   28 
   29 #include "detection/detection_engine.h"
   30 #include "framework/inspector.h"
   31 #include "framework/module.h"
   32 #include "log/messages.h"
   33 #include "main/thread.h"
   34 #include "profiler/profiler.h"
   35 #include "pub_sub/http_events.h"
   36 #include "utils/util.h"
   37 
   38 #define DF_GID 175
   39 #define DF_SID   1
   40 
   41 static const char* s_name = "domain_filter";
   42 static const char* s_help = "alert on configured HTTP domains";
   43 
   44 using DomainList = std::vector<std::string>;
   45 using DomainSet = std::unordered_set<std::string>;
   46 using namespace snort;
   47 
   48 //--------------------------------------------------------------------------
   49 // attributes
   50 //--------------------------------------------------------------------------
   51 
   52 static const Parameter s_params[] =
   53 {
   54     { "file", Parameter::PT_STRING, nullptr, nullptr,
   55       "file with list of domains identifying hosts to be filtered" },
   56 
   57     { "hosts", Parameter::PT_STRING, nullptr, nullptr,
   58       "list of domains identifying hosts to be filtered" },
   59 
   60     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
   61 };
   62 
   63 static const RuleMap s_rules[] =
   64 {
   65     { DF_SID, "configured domain detected" },
   66 
   67     { 0, nullptr }
   68 };
   69 
   70 struct DomainFilterStats
   71 {
   72     PegCount checked;
   73     PegCount filtered;
   74 };
   75 
   76 static THREAD_LOCAL DomainFilterStats s_counts;
   77 
   78 const PegInfo s_pegs[] =
   79 {
   80     { CountType::SUM, "checked", "domains checked" },
   81     { CountType::SUM, "filtered", "domains filtered" },
   82 
   83     { CountType::END, nullptr, nullptr }
   84 };
   85 
   86 static THREAD_LOCAL ProfileStats s_prof;
   87 
   88 //--------------------------------------------------------------------------
   89 // module stuff
   90 //--------------------------------------------------------------------------
   91 
   92 class DomainFilterModule : public Module
   93 {
   94 public:
   95     DomainFilterModule() : Module(s_name, s_help, s_params) { }
   96 
   97     DomainList& get_hosts()
   98     { return hosts; }
   99 
  100     bool set(const char*, Value&, SnortConfig*) override;
  101 
  102     const PegInfo* get_pegs() const override
  103     { return s_pegs; }
  104 
  105     PegCount* get_counts() const override
  106     { return (PegCount*)&s_counts; }
  107 
  108     unsigned get_gid() const override
  109     { return DF_GID; }
  110 
  111     const RuleMap* get_rules() const override
  112     { return s_rules; }
  113 
  114     Usage get_usage() const override
  115     { return INSPECT; }
  116 
  117     ProfileStats* get_profile() const override
  118     { return &s_prof; }
  119 
  120 public:
  121     DomainList hosts;
  122 };
  123 
  124 bool DomainFilterModule::set(const char*, Value& v, SnortConfig*)
  125 {
  126     if ( v.is("file") )
  127     {
  128         std::ifstream df(v.get_string());
  129 
  130         if ( !df.is_open() )
  131         {
  132             ParseError("can't open file %s: %s", v.get_string(), get_error(errno));
  133             return false;
  134         }
  135         std::string tok;
  136 
  137         while ( df >> tok )
  138             hosts.push_back(tok);
  139     }
  140     else if ( v.is("hosts") )
  141     {
  142         std::string tok;
  143         v.set_first_token();
  144 
  145         while ( v.get_next_token(tok) )
  146             hosts.push_back(tok);
  147     }
  148     return true;
  149 }
  150 
  151 //--------------------------------------------------------------------------
  152 // event stuff
  153 //--------------------------------------------------------------------------
  154 
  155 class HttpHandler : public DataHandler
  156 {
  157 public:
  158     HttpHandler(DomainSet& sv) : DataHandler(s_name), hosts(sv) { }
  159 
  160     void handle(DataEvent& e, Flow*) override;
  161 
  162 private:
  163     DomainSet& hosts;
  164 };
  165 
  166 void HttpHandler::handle(DataEvent& de, Flow*)
  167 {
  168     Profile profile(s_prof);
  169     HttpEvent* he = (HttpEvent*)&de;
  170 
  171     int32_t len;
  172     const char* s = (const char*)he->get_uri_host(len);
  173 
  174     if ( !s or len < 1 )
  175         return;
  176 
  177     std::string h(s, len);
  178     transform(h.begin(), h.end(), h.begin(), ::tolower);
  179 
  180     DomainSet::const_iterator it = hosts.find(h);
  181 
  182     if ( it != hosts.end() )
  183     {
  184         DetectionEngine::queue_event(DF_GID, DF_SID);
  185         ++s_counts.filtered;
  186     }
  187     ++s_counts.checked;
  188 }
  189 
  190 //--------------------------------------------------------------------------
  191 // inspector stuff
  192 //--------------------------------------------------------------------------
  193 
  194 class DomainFilter : public Inspector
  195 {
  196 public:
  197     DomainFilter(DomainList&);
  198 
  199     bool configure(SnortConfig*) override;
  200     void show(const SnortConfig*) const override;
  201     void eval(Packet*) override { }
  202 
  203 private:
  204     DomainSet hosts;
  205 };
  206 
  207 DomainFilter::DomainFilter(DomainList& sv)
  208 {
  209     hosts.insert(sv.begin(), sv.end());
  210     sv.clear();
  211 }
  212 
  213 bool DomainFilter::configure(SnortConfig*)
  214 {
  215     if ( !hosts.empty() )
  216         DataBus::subscribe(http_pub_key, HttpEventIds::REQUEST_HEADER, new HttpHandler(hosts));
  217 
  218     return true;
  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