From 1efaf8d7a4321ba06e967142d71dd398ccc7e01a Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 7 Oct 2021 09:59:15 +0200 Subject: [PATCH] Move logic to execute `HookLoadFile` for signatures into rule matcher code. This (1) fixes an issue where signature files supplied on the command line wouldn't pass through the hooks, and (2) prepares for allowing hooks to supply the content of a signature file directly. --- src/RuleMatcher.cc | 47 +++++++++++++++++-- src/RuleMatcher.h | 3 +- src/ScannedFile.cc | 12 ++++- src/ScannedFile.h | 13 ++++- src/scan.l | 28 +---------- src/zeek-setup.cc | 10 ++-- testing/btest/Baseline/plugins.hooks/output | 6 +++ .../Baseline/signatures.udp-state/reject | 2 +- testing/btest/plugins/hooks.zeek | 13 ++++- 9 files changed, 94 insertions(+), 40 deletions(-) diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index 4cf0c15214..cd2455c074 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -24,6 +24,7 @@ #include "zeek/ZeekString.h" #include "zeek/analyzer/Analyzer.h" #include "zeek/module_util.h" +#include "zeek/plugin/Manager.h" using namespace std; @@ -248,7 +249,7 @@ void RuleMatcher::Delete(RuleHdrTest* node) delete node; } -bool RuleMatcher::ReadFiles(const std::vector& files) +bool RuleMatcher::ReadFiles(const std::vector& files) { #ifdef USE_PERFTOOLS_DEBUG HeapLeakChecker::Disabler disabler; @@ -256,18 +257,54 @@ bool RuleMatcher::ReadFiles(const std::vector& files) parse_error = false; - for ( const auto& f : files ) + for ( auto f : files ) { - rules_in = util::open_file(util::find_file(f, util::zeek_path(), ".sig")); + if ( ! f.full_path ) + f.full_path = util::find_file(f.file, util::zeek_path(), ".sig"); + + int rc = PLUGIN_HOOK_WITH_RESULT( + HOOK_LOAD_FILE, HookLoadFile(zeek::plugin::Plugin::SIGNATURES, f.file, *f.full_path), + -1); + + switch ( rc ) + { + case -1: + // No plugin in charge of this file. + if ( f.full_path->empty() ) + { + zeek::reporter->Error("failed to find file associated with @load-sigs %s", + f.file.c_str()); + continue; + } + break; + + case 0: + if ( ! zeek::reporter->Errors() ) + zeek::reporter->Error("Plugin reported error loading signatures %s", + f.file.c_str()); + + exit(1); + break; + + case 1: + // A plugin took care of it, just skip. + continue; + + default: + assert(false); + break; + } + + rules_in = util::open_file(*f.full_path); if ( ! rules_in ) { - reporter->Error("Can't open signature file %s", f.data()); + reporter->Error("Can't open signature file %s", f.file.c_str()); return false; } rules_line_number = 0; - current_rule_file = f.data(); + current_rule_file = f.full_path->c_str(); rules_parse(); fclose(rules_in); } diff --git a/src/RuleMatcher.h b/src/RuleMatcher.h index 9a89d39efd..f64a7bc97e 100644 --- a/src/RuleMatcher.h +++ b/src/RuleMatcher.h @@ -11,6 +11,7 @@ #include "zeek/CCL.h" #include "zeek/RE.h" #include "zeek/Rule.h" +#include "zeek/ScannedFile.h" //#define MATCHER_PRINT_STATS @@ -259,7 +260,7 @@ public: ~RuleMatcher(); // Parse the given files and built up data structures. - bool ReadFiles(const std::vector& files); + bool ReadFiles(const std::vector& files); /** * Inititialize a state object for matching file magic signatures. diff --git a/src/ScannedFile.cc b/src/ScannedFile.cc index c5367748e4..8050f0fc12 100644 --- a/src/ScannedFile.cc +++ b/src/ScannedFile.cc @@ -10,7 +10,7 @@ namespace zeek::detail { std::list files_scanned; -std::vector sig_files; +std::vector sig_files; ScannedFile::ScannedFile(int arg_include_level, std::string arg_name, bool arg_skipped, bool arg_prefixes_checked) @@ -47,4 +47,14 @@ bool ScannedFile::AlreadyScanned() const return rval; } +SignatureFile::SignatureFile(std::string file) + : file(std::move(file)) + { + } + +SignatureFile::SignatureFile(std::string file, std::string full_path) + : file(std::move(file)), full_path(std::move(full_path)) + { + } + } // namespace zeek::detail diff --git a/src/ScannedFile.h b/src/ScannedFile.h index 902d627f7d..9829b2c1d2 100644 --- a/src/ScannedFile.h +++ b/src/ScannedFile.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include #include @@ -34,6 +35,16 @@ public: }; extern std::list files_scanned; -extern std::vector sig_files; + +struct SignatureFile + { + std::string file; + std::optional full_path; + + SignatureFile(std::string file); + SignatureFile(std::string file, std::string full_path); + }; + +extern std::vector sig_files; } // namespace zeek::detail diff --git a/src/scan.l b/src/scan.l index e6af14cd89..dbcb3fcfd3 100644 --- a/src/scan.l +++ b/src/scan.l @@ -348,33 +348,7 @@ when return TOK_WHEN; @load-sigs{WS}{FILE} { const char* file = zeek::util::skip_whitespace(yytext + 10); std::string path = find_relative_file(file, ".sig"); - int rc = PLUGIN_HOOK_WITH_RESULT(HOOK_LOAD_FILE, HookLoadFile(zeek::plugin::Plugin::SIGNATURES, file, path), -1); - - switch ( rc ) { - case -1: - // No plugin in charge of this file. - if ( path.empty() ) - zeek::reporter->Error("failed to find file associated with @load-sigs %s", - file); - else - zeek::detail::sig_files.push_back(std::move(path)); - break; - - case 0: - if ( ! zeek::reporter->Errors() ) - zeek::reporter->Error("Plugin reported error loading signatures %s", file); - - exit(1); - break; - - case 1: - // A plugin took care of it, just skip. - break; - - default: - assert(false); - break; - } + sig_files.emplace_back(file, path); } @load-plugin{WS}{ID} { diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index dad543c282..b2e77df628 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -737,15 +737,19 @@ SetupResult setup(int argc, char** argv, Options* zopts) id->SetVal(make_intrusive(*options.pcap_filter)); } - auto all_signature_files = options.signature_files; + std::vector all_signature_files; + + // Append signature files given on the command line + for ( const auto& sf : options.signature_files ) + all_signature_files.push_back(sf); // Append signature files defined in "signature_files" script option for ( auto&& sf : get_script_signature_files() ) - all_signature_files.emplace_back(std::move(sf)); + all_signature_files.push_back(std::move(sf)); // Append signature files defined in @load-sigs for ( const auto& sf : zeek::detail::sig_files ) - all_signature_files.emplace_back(sf); + all_signature_files.push_back(sf); if ( ! all_signature_files.empty() ) { diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index e16e7c63b6..e340ed914b 100644 --- a/testing/btest/Baseline/plugins.hooks/output +++ b/testing/btest/Baseline/plugins.hooks/output @@ -1034,6 +1034,7 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/zeek.bif, <...>/zeek.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, builtin-plugins/__load__.zeek, <...>/__load__.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, builtin-plugins/__preload__.zeek, <...>/__preload__.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, s1.sig, ./s1.sig) -> -1 0.000000 MetaHookPost LoadFile(1, ./archive, <...>/archive.sig) -> -1 0.000000 MetaHookPost LoadFile(1, ./audio, <...>/audio.sig) -> -1 0.000000 MetaHookPost LoadFile(1, ./dpd.sig, <...>/dpd.sig) -> -1 @@ -1046,6 +1047,7 @@ 0.000000 MetaHookPost LoadFile(1, ./office, <...>/office.sig) -> -1 0.000000 MetaHookPost LoadFile(1, ./programming, <...>/programming.sig) -> -1 0.000000 MetaHookPost LoadFile(1, ./video, <...>/video.sig) -> -1 +0.000000 MetaHookPost LoadFile(1, s2, ./s2.sig) -> -1 0.000000 MetaHookPost LogInit(Log::WRITER_ASCII, default, true, true, packet_filter(0.0,0.0,0.0), 5, {ts (time), node (string), filter (string), init (bool), success (bool)}) -> 0.000000 MetaHookPost LogWrite(Log::WRITER_ASCII, default, packet_filter(0.0,0.0,0.0), 5, {ts (time), node (string), filter (string), init (bool), success (bool)}, ) -> true 0.000000 MetaHookPost QueueEvent(NetControl::init()) -> false @@ -2086,6 +2088,7 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/zeek.bif, <...>/zeek.bif.zeek) 0.000000 MetaHookPre LoadFile(0, builtin-plugins/__load__.zeek, <...>/__load__.zeek) 0.000000 MetaHookPre LoadFile(0, builtin-plugins/__preload__.zeek, <...>/__preload__.zeek) +0.000000 MetaHookPre LoadFile(0, s1.sig, ./s1.sig) 0.000000 MetaHookPre LoadFile(1, ./archive, <...>/archive.sig) 0.000000 MetaHookPre LoadFile(1, ./audio, <...>/audio.sig) 0.000000 MetaHookPre LoadFile(1, ./dpd.sig, <...>/dpd.sig) @@ -2098,6 +2101,7 @@ 0.000000 MetaHookPre LoadFile(1, ./office, <...>/office.sig) 0.000000 MetaHookPre LoadFile(1, ./programming, <...>/programming.sig) 0.000000 MetaHookPre LoadFile(1, ./video, <...>/video.sig) +0.000000 MetaHookPre LoadFile(1, s2, ./s2.sig) 0.000000 MetaHookPre LogInit(Log::WRITER_ASCII, default, true, true, packet_filter(0.0,0.0,0.0), 5, {ts (time), node (string), filter (string), init (bool), success (bool)}) 0.000000 MetaHookPre LogWrite(Log::WRITER_ASCII, default, packet_filter(0.0,0.0,0.0), 5, {ts (time), node (string), filter (string), init (bool), success (bool)}, ) 0.000000 MetaHookPre QueueEvent(NetControl::init()) @@ -3149,6 +3153,8 @@ 0.000000 | HookLoadFile base<...>/zeek.bif <...>/zeek.bif.zeek 0.000000 | HookLoadFile builtin-plugins/__load__.zeek <...>/__load__.zeek 0.000000 | HookLoadFile builtin-plugins/__preload__.zeek <...>/__preload__.zeek +0.000000 | HookLoadFile s1.sig ./s1.sig +0.000000 | HookLoadFile s2 ./s2.sig 0.000000 | HookLogInit packet_filter 1/1 {ts (time), node (string), filter (string), init (bool), success (bool)} 0.000000 | HookLogWrite packet_filter [ts=XXXXXXXXXX.XXXXXX, node=zeek, filter=ip or not ip, init=T, success=T] 0.000000 | HookQueueEvent NetControl::init() diff --git a/testing/btest/Baseline/signatures.udp-state/reject b/testing/btest/Baseline/signatures.udp-state/reject index aaeba4be58..9d97a9ac45 100644 --- a/testing/btest/Baseline/signatures.udp-state/reject +++ b/testing/btest/Baseline/signatures.udp-state/reject @@ -1,3 +1,3 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -error: Error in signature (udp-established.sig:5): 'established' is not a valid 'udp-state' +error: Error in signature (./udp-established.sig:5): 'established' is not a valid 'udp-state' diff --git a/testing/btest/plugins/hooks.zeek b/testing/btest/plugins/hooks.zeek index cfff751eca..992d305f14 100644 --- a/testing/btest/plugins/hooks.zeek +++ b/testing/btest/plugins/hooks.zeek @@ -1,8 +1,19 @@ # @TEST-EXEC: ${DIST}/auxil/zeek-aux/plugin-support/init-plugin -u . Demo Hooks # @TEST-EXEC: cp -r %DIR/hooks-plugin/* . # @TEST-EXEC: ./configure --zeek-dist=${DIST} && make -# @TEST-EXEC: ZEEK_PLUGIN_ACTIVATE="Demo::Hooks" ZEEK_PLUGIN_PATH=`pwd` zeek -b -r $TRACES/http/get.trace %INPUT 2>&1 | $SCRIPTS/diff-remove-abspath | sort | uniq >output +# @TEST-EXEC: ZEEK_PLUGIN_ACTIVATE="Demo::Hooks" ZEEK_PLUGIN_PATH=`pwd` zeek -b -r $TRACES/http/get.trace %INPUT s1.sig 2>&1 | $SCRIPTS/diff-remove-abspath | sort | uniq >output # @TEST-EXEC: btest-diff output @unload base/misc/version @load base/init-default + +@load-sigs s2 + +@TEST-START-FILE s1.sig +# Just empty. +@TEST-END-FILE + +@TEST-START-FILE s2.sig +# Just empty. +@TEST-END-FILE +