From: Mike Stepanek (mstepane) Date: Mon, 27 Jun 2022 12:22:07 +0000 (+0000) Subject: Pull request #3486: wizard: add proto option for wizard X-Git-Tag: 3.1.33.0~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c29e929f849fc01697c85e8acef986416f6d338;p=thirdparty%2Fsnort3.git Pull request #3486: wizard: add proto option for wizard Merge in SNORT/snort3 from ~YVELYKOZ/snort3:wizard_proto to master Squashed commit of the following: commit 44c44188e18a24a6744a2b45c9791d8420e9223f Author: Yehor Velykozhon 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. --- diff --git a/lua/snort_defaults.lua b/lua/snort_defaults.lua index 43c1037ec..4242f85dc 100644 --- a/lua/snort_defaults.lua +++ b/lua/snort_defaults.lua @@ -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, diff --git a/src/service_inspectors/wizard/hexes.cc b/src/service_inspectors/wizard/hexes.cc index 8b73db1df..9d8b7dcc5 100644 --- a/src/service_inspectors/wizard/hexes.cc +++ b/src/service_inspectors/wizard/hexes.cc @@ -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() ) { diff --git a/src/service_inspectors/wizard/magic.cc b/src/service_inspectors/wizard/magic.cc index 41ddd9641..bea294702 100644 --- a/src/service_inspectors/wizard/magic.cc +++ b/src/service_inspectors/wizard/magic.cc @@ -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; } diff --git a/src/service_inspectors/wizard/magic.h b/src/service_inspectors/wizard/magic.h index bc848d296..ba90ec81a 100644 --- a/src/service_inspectors/wizard/magic.h +++ b/src/service_inspectors/wizard/magic.h @@ -20,6 +20,7 @@ #ifndef MAGIC_H #define MAGIC_H +#include #include #include @@ -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&); diff --git a/src/service_inspectors/wizard/spells.cc b/src/service_inspectors/wizard/spells.cc index 9b8b51ebc..a04101be3 100644 --- a/src/service_inspectors/wizard/spells.cc +++ b/src/service_inspectors/wizard/spells.cc @@ -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() ) diff --git a/src/service_inspectors/wizard/wiz_module.cc b/src/service_inspectors/wizard/wiz_module.cc index 1f49d65c4..4d725f3f7 100644 --- a/src/service_inspectors/wizard/wiz_module.cc +++ b/src/service_inspectors/wizard/wiz_module.cc @@ -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& patterns, bool hex) +static bool add_spells(MagicBook* b, const string& service, const vector& 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; } } diff --git a/src/service_inspectors/wizard/wiz_module.h b/src/service_inspectors/wizard/wiz_module.h index 2dce2b36d..4cd46bc9e 100644 --- a/src/service_inspectors/wizard/wiz_module.h +++ b/src/service_inspectors/wizard/wiz_module.h @@ -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 diff --git a/src/service_inspectors/wizard/wizard.cc b/src/service_inspectors/wizard/wizard.cc index 12dc1f5c5..4407d2afe 100644 --- a/src/service_inspectors/wizard/wizard.cc +++ b/src/service_inspectors/wizard/wizard.cc @@ -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;