]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3486: wizard: add proto option for wizard
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Mon, 27 Jun 2022 12:22:07 +0000 (12:22 +0000)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Mon, 27 Jun 2022 12:22:07 +0000 (12:22 +0000)
Merge in SNORT/snort3 from ~YVELYKOZ/snort3:wizard_proto to master

Squashed commit of the following:

commit 44c44188e18a24a6744a2b45c9791d8420e9223f
Author: Yehor Velykozhon <yvelykoz@cisco.com>
Date:   Thu Jun 16 17:22:30 2022 +0300

    wizard: update wizard's patterns to follow the proto option

    Updated framework to parse correctly the patterns in pair with proto
    option. For each proto type should be created seperated collection of
    patterns based on config file.

lua/snort_defaults.lua
src/service_inspectors/wizard/hexes.cc
src/service_inspectors/wizard/magic.cc
src/service_inspectors/wizard/magic.h
src/service_inspectors/wizard/spells.cc
src/service_inspectors/wizard/wiz_module.cc
src/service_inspectors/wizard/wiz_module.h
src/service_inspectors/wizard/wizard.cc

index 43c1037ec9a01fa6a3fc4e777fc51c0ca6e99371..4242f85dcb572358a2c6f449878f96cab87945c9 100644 (file)
@@ -392,7 +392,7 @@ default_wizard =
         { service = 'dnp3', proto = 'tcp', client_first = true,
           to_server = { '|05 64|' }, to_client = { '|05 64|' } },
 
-        { service = 'netflow', proto = 'udp',  client_first = true,
+        { service = 'netflow', proto = 'udp', client_first = true,
           to_server = netflow_versions },
 
         { service = 'http2', proto = 'tcp', client_first = true,
index 8b73db1dfc15f8983e588e27af04ec72e438c10e..9d8b7dcc5a2df8b3689f7188df02c8369beb20c0 100644 (file)
@@ -100,8 +100,20 @@ void HexBook::add_spell(
     p->value = SnortConfig::get_static_name(val);
 }
 
-bool HexBook::add_spell(const char* key, const char*& val)
+bool HexBook::add_spell(const char* key, const char*& val, ArcaneType proto)
 {
+    // In case of 'ANY' as proto, pattern should be added
+    // to both UDP and TCP collections
+    if ( proto == ArcaneType::ANY )
+    {
+        auto val_local = val;
+
+        bool ret1 = add_spell(key, val_local, ArcaneType::UDP);
+        bool ret2 = add_spell(key, val, ArcaneType::TCP);
+
+        return ret1 || ret2;
+    }
+
     HexVector hv;
 
     if ( !translate(key, hv) )
@@ -112,7 +124,7 @@ bool HexBook::add_spell(const char* key, const char*& val)
     }
 
     unsigned i = 0;
-    MagicPage* p = root;
+    MagicPage* p = get_root(proto);
 
     while ( i < hv.size() )
     {
index 41ddd964121df40455f1b89278a5af68dabcab6f..bea294702e26cd731bc37cb264daf3ceceefa299 100644 (file)
@@ -54,8 +54,8 @@ const char* MagicBook::find_spell(const uint8_t* data, unsigned len,
 }
 
 MagicBook::MagicBook()
-{ root = new MagicPage(*this); }
+{ root = new MagicPage[(int)ArcaneType::MAX] { *this, *this }; }
 
 MagicBook::~MagicBook()
-{ delete root; }
+{ delete[] root; }
 
index bc848d296bddd49dacb995ac9992797e879c9542..ba90ec81a0967b27f94534b631ad4b4246883d9c 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef MAGIC_H
 #define MAGIC_H
 
+#include <cassert>
 #include <string>
 #include <vector>
 
@@ -50,17 +51,34 @@ public:
     MagicBook(const MagicBook&) = delete;
     MagicBook& operator=(const MagicBook&) = delete;
 
-    virtual bool add_spell(const char* key, const char*& val) = 0;
+    enum class ArcaneType
+    {
+        TCP,
+        UDP,
+        ANY,
+        MAX = ANY
+    };
+
+    virtual bool add_spell(const char* key, const char*& val, ArcaneType proto) = 0;
     virtual const char* find_spell(const uint8_t* data, unsigned len, const MagicPage*& p,
         const MagicPage*& bookmark) const;
 
-    const MagicPage* page1() const
-    { return root; }
+    const MagicPage* page1(ArcaneType proto) const
+    {
+        assert(proto < ArcaneType::MAX);
+        return &root[(int)proto];
+    }
 
 protected:
     MagicBook();
     MagicPage* root;
 
+    MagicPage* get_root(ArcaneType proto) const
+    {
+        assert(proto < ArcaneType::MAX);
+        return &root[(int)proto];
+    }
+
     virtual const MagicPage* find_spell(const uint8_t*, unsigned,
         const MagicPage*, unsigned, const MagicPage*&) const = 0;
 };
@@ -75,7 +93,7 @@ class SpellBook : public MagicBook
 public:
     SpellBook();
 
-    bool add_spell(const char*, const char*&) override;
+    bool add_spell(const char*, const char*&, ArcaneType) override;
 
 private:
     bool translate(const char*, HexVector&);
@@ -94,7 +112,7 @@ class HexBook : public MagicBook
 public:
     HexBook() = default;
 
-    bool add_spell(const char*, const char*&) override;
+    bool add_spell(const char*, const char*&, ArcaneType) override;
 
 private:
     bool translate(const char*, HexVector&);
index 9b8b51ebcdc9345c2b2f28b915b8e3798b5c5ad9..a04101be33fbd4320e19809b7bf11118905a8648 100644 (file)
@@ -31,13 +31,19 @@ using namespace std;
 
 #define WILD 0x100
 
-SpellBook::SpellBook()
+SpellBook::SpellBook() : MagicBook()
 {
-    // allows skipping leading whitespace only
-    root->next[(int)' '] = root;
-    root->next[(int)'\t'] = root;
-    root->next[(int)'\r'] = root;
-    root->next[(int)'\n'] = root;
+    // applying for both TCP and UDP arrays
+    for (size_t idx = 0; idx < (int)ArcaneType::MAX; ++idx)
+    {
+        MagicPage* r = &root[idx];
+
+        // allows skipping leading whitespace only
+        root[idx].next[(int)' '] = r;
+        root[idx].next[(int)'\t'] = r;
+        root[idx].next[(int)'\r'] = r;
+        root[idx].next[(int)'\n'] = r;
+    }
 }
 
 bool SpellBook::translate(const char* in, HexVector& out)
@@ -91,8 +97,20 @@ void SpellBook::add_spell(
     p->value = snort::SnortConfig::get_static_name(val);
 }
 
-bool SpellBook::add_spell(const char* key, const char*& val)
+bool SpellBook::add_spell(const char* key, const char*& val, ArcaneType proto)
 {
+    // In case of 'ANY' as proto, pattern should be added
+    // to both UDP and TCP collections
+    if ( proto == ArcaneType::ANY )
+    {
+        auto val_local = val;
+
+        bool ret1 = add_spell(key, val_local, ArcaneType::UDP);
+        bool ret2 = add_spell(key, val, ArcaneType::TCP);
+
+        return ret1 || ret2;
+    }
+
     HexVector hv;
 
     if ( !translate(key, hv) )
@@ -103,7 +121,7 @@ bool SpellBook::add_spell(const char* key, const char*& val)
     }
 
     unsigned i = 0;
-    MagicPage* p = root;
+    MagicPage* p = get_root(proto);
 
     // Perform a longest prefix match before inserting the pattern.
     while ( i < hv.size() )
index 1f49d65c4e9708dc48c90201149f4379518378f9..4d725f3f7bc38f73fb9a76ad9fe6acfc894423f4 100644 (file)
@@ -28,7 +28,6 @@
 #include "trace/trace.h"
 
 #include "curses.h"
-#include "magic.h"
 
 using namespace snort;
 using namespace std;
@@ -52,7 +51,7 @@ static const Parameter wizard_hexes_params[] =
     { "service", Parameter::PT_STRING, nullptr, nullptr,
       "name of service" },
 
-    { "proto", Parameter::PT_SELECT, "tcp | udp", "tcp",
+    { "proto", Parameter::PT_SELECT, "tcp | udp | any", "any",
       "protocol to scan" },
 
     { "client_first", Parameter::PT_BOOL, nullptr, "true",
@@ -80,7 +79,7 @@ static const Parameter wizard_spells_params[] =
     { "service", Parameter::PT_STRING, nullptr, nullptr,
       "name of service" },
 
-    { "proto", Parameter::PT_SELECT, "tcp | udp", "tcp",
+    { "proto", Parameter::PT_SELECT, "tcp | udp | any", "any",
       "protocol to scan" },
 
     { "client_first", Parameter::PT_BOOL, nullptr, "true",
@@ -143,10 +142,17 @@ bool WizardModule::set(const char*, Value& v, SnortConfig*)
     if ( v.is("service") )
         service = v.get_string();
 
-    // FIXIT-L implement proto and client_first
     else if ( v.is("proto") )
-        return true;
+    {
+        if ( !strcmp(v.get_string(), "tcp") )
+            proto = MagicBook::ArcaneType::TCP;
+        else if ( !strcmp(v.get_string(), "udp") )
+            proto = MagicBook::ArcaneType::UDP;
+        else 
+            proto = MagicBook::ArcaneType::ANY;
+    }
 
+    // FIXIT-H implement client_first
     else if ( v.is("client_first") )
         return true;
 
@@ -196,12 +202,14 @@ bool WizardModule::begin(const char* fqn, int idx, SnortConfig*)
     return true;
 }
 
-static bool add_spells(MagicBook* b, const string& service, const vector<string>& patterns, bool hex)
+static bool add_spells(MagicBook* b, const string& service, const vector<string>& patterns,
+    bool hex, MagicBook::ArcaneType proto)
 {
     for ( const auto& p : patterns )
     {
         const char* val = service.c_str();
-        if ( !b->add_spell(p.c_str(), val) )
+
+        if ( !b->add_spell(p.c_str(), val, proto) )
         {
             if ( !val )
             {
@@ -231,6 +239,7 @@ bool WizardModule::end(const char* fqn, int idx, SnortConfig*)
     {
         service.clear();
         c2s_patterns.clear();
+        s2c_patterns.clear();
     }
     else if ( !strcmp(fqn, "wizard.hexes") )
     {
@@ -249,9 +258,9 @@ bool WizardModule::end(const char* fqn, int idx, SnortConfig*)
 
                 return false;
             }
-            if ( !add_spells(c2s_hexes, service, c2s_patterns, true) )
+            if ( !add_spells(c2s_hexes, service, c2s_patterns, true, proto) )
                 return false;
-            if ( !add_spells(s2c_hexes, service, s2c_patterns, true) )
+            if ( !add_spells(s2c_hexes, service, s2c_patterns, true, proto) )
                 return false;
         }
     }
@@ -272,9 +281,9 @@ bool WizardModule::end(const char* fqn, int idx, SnortConfig*)
 
                 return false;
             }
-            if ( !add_spells(c2s_spells, service, c2s_patterns, false) )
+            if ( !add_spells(c2s_spells, service, c2s_patterns, false, proto) )
                 return false;
-            if ( !add_spells(s2c_spells, service, s2c_patterns, false) )
+            if ( !add_spells(s2c_spells, service, s2c_patterns, false, proto) )
                 return false;
         }
     }
index 2dce2b36d6a9872c93b10d54f17cbc08940a5fb2..4cd46bc9e3f88183e6ac9b677692896604ea8da4 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "framework/module.h"
 
+#include "magic.h"
+
 #define WIZ_NAME "wizard"
 #define WIZ_HELP "inspector that implements port-independent protocol identification"
 
@@ -84,6 +86,8 @@ private:
 
     CurseBook* curses = nullptr;
     uint16_t max_search_depth = 0;
+
+    MagicBook::ArcaneType proto;
 };
 
 #endif
index 12dc1f5c514eec2c2c9a95a084ee19e909c12019..4407d2afe0d3779264b973bcd4552a33d6756999 100644 (file)
@@ -141,7 +141,7 @@ public:
     inline bool finished(Wand& w)
     { return !w.hex and !w.spell and w.curse_tracker.empty(); }
 
-    void reset(Wand&, bool, bool);
+    void reset(Wand&, bool, MagicBook::MagicBook::ArcaneType);
 
     bool cast_spell(Wand&, Flow*, const uint8_t*, unsigned, uint16_t&);
     bool spellbind(const MagicPage*&, Flow*, const uint8_t*, unsigned, const MagicPage*&);
@@ -170,7 +170,8 @@ MagicSplitter::MagicSplitter(bool c2s, class Wizard* w) :
 {
     wizard = w;
     w->add_ref();
-    w->reset(wand, true, c2s);
+    // Used only in case of TCP traffic
+    w->reset(wand, c2s, MagicBook::ArcaneType::TCP);
 }
 
 MagicSplitter::~MagicSplitter()
@@ -259,21 +260,23 @@ Wizard::~Wizard()
     delete curses;
 }
 
-void Wizard::reset(Wand& w, bool tcp, bool c2s)
+void Wizard::reset(Wand& w, bool c2s, MagicBook::ArcaneType proto)
 {
     w.bookmark = nullptr;
 
     if ( c2s )
     {
-        w.hex = c2s_hexes->page1();
-        w.spell = c2s_spells->page1();
+        w.hex = c2s_hexes->page1(proto);
+        w.spell = c2s_spells->page1(proto);
     }
     else
     {
-        w.hex = s2c_hexes->page1();
-        w.spell = s2c_spells->page1();
+        w.hex = s2c_hexes->page1(proto);
+        w.spell = s2c_spells->page1(proto);
     }
 
+    bool tcp = MagicBook::ArcaneType::TCP == proto;
+
     if ( w.curse_tracker.empty() )
     {
         for ( const CurseDetails* curse : curses->get_curses(tcp) )
@@ -298,7 +301,7 @@ void Wizard::eval(Packet* p)
 
     bool c2s = p->is_from_client();
     Wand wand;
-    reset(wand, false, c2s);
+    reset(wand, c2s, MagicBook::ArcaneType::UDP);
     uint16_t udp_processed_bytes = 0;
 
     ++tstats.udp_scans;