diff --git a/scripts/base/frameworks/analyzer/__load__.zeek b/scripts/base/frameworks/analyzer/__load__.zeek index e2c42c7a8e..ab0b2416e4 100644 --- a/scripts/base/frameworks/analyzer/__load__.zeek +++ b/scripts/base/frameworks/analyzer/__load__.zeek @@ -1,2 +1,3 @@ @load ./main @load ./dpd +@load ./analyzer-failed-log diff --git a/scripts/base/frameworks/analyzer/analyzer-failed-log.zeek b/scripts/base/frameworks/analyzer/analyzer-failed-log.zeek new file mode 100644 index 0000000000..07550b861c --- /dev/null +++ b/scripts/base/frameworks/analyzer/analyzer-failed-log.zeek @@ -0,0 +1,88 @@ +##! Logging analyzer violations into analyzer-failed.log + +@load base/frameworks/logging +@load ./main + +module Analyzer::Logging; + +export { + ## Add the analyzer logging stream identifier. + redef enum Log::ID += { LOG }; + + ## The record type defining the columns to log in the analyzer-failed logging stream. + type Info: record { + ## Timestamp of the violation. + ts: time &log; + ## The kind of analyzer involved. Currently "packet", "file" + ## or "protocol". + analyzer_kind: string &log; + ## The name of the analyzer as produced by :zeek:see:`Analyzer::name` + ## for the analyzer's tag. + analyzer_name: string &log; + ## Connection UID if available. + uid: string &log &optional; + ## File UID if available. + fuid: string &log &optional; + ## Connection identifier if available + id: conn_id &log &optional; + + ## Failure or violation reason, if available. + failure_reason: string &log; + + ## Data causing failure or violation if available. Truncated + ## to :zeek:see:`Analyzer::Logging::failure_data_max_size`. + failure_data: string &log &optional; + }; + + ## If a violation contains information about the data causing it, + ## include at most this many bytes of it in the log. + option failure_data_max_size = 40; + + ## An event that can be handled to access the :zeek:type:`Analyzer::Logging::Info` + ## record as it is sent on to the logging framework. + global log_analyzer_failed: event(rec: Info); + + ## A default logging policy hook for the stream. + global log_policy: Log::PolicyHook; +} + +event zeek_init() &priority=5 + { + Log::create_stream(LOG, [$columns=Info, $path="analyzer-failed", $ev=log_analyzer_failed, $policy=log_policy]); + } + +event analyzer_failed(ts: time, atype: AllAnalyzers::Tag, info: AnalyzerViolationInfo) + { + local rec = Info( + $ts=ts, + $analyzer_kind=Analyzer::kind(atype), + $analyzer_name=Analyzer::name(atype), + $failure_reason=info$reason + ); + + if ( info?$c ) + { + rec$id = info$c$id; + rec$uid = info$c$uid; + } + + if ( info?$f ) + { + rec$fuid = info$f$id; + # If the confirmation didn't have a connection, but the + # fa_file object has exactly one, use it. + if ( ! rec?$uid && info$f?$conns && |info$f$conns| == 1 ) + { + for ( _, c in info$f$conns ) + { + rec$id = c$id; + rec$uid = c$uid; + } + } + } + + if ( info?$data ) + rec$failure_data = info$data; + + Log::write(LOG, rec); + } diff --git a/scripts/base/frameworks/analyzer/dpd.zeek b/scripts/base/frameworks/analyzer/dpd.zeek index 0f810b6151..36cba619fa 100644 --- a/scripts/base/frameworks/analyzer/dpd.zeek +++ b/scripts/base/frameworks/analyzer/dpd.zeek @@ -1,13 +1,15 @@ ##! Disables analyzers if protocol violations occur, and add service information ##! to connection log. +@load ./main + module DPD; export { ## Deprecated, please see https://github.com/zeek/zeek/pull/4200 for details option max_violations: table[Analyzer::Tag] of count = table() &deprecated="Remove in v8.1: This has become non-functional in Zeek 7.2, see PR #4200" &default = 5; - ## Analyzers which you don't want to throw + ## Analyzers which you don't want to remove on violations. option ignore_violations: set[Analyzer::Tag] = set(); ## Ignore violations which go this many bytes into the connection. @@ -43,7 +45,7 @@ event analyzer_confirmation_info(atype: AllAnalyzers::Tag, info: AnalyzerConfirm } ## Remove failed analyzers from service field and add them to c$service_violation -event analyzer_violation_info(atype: AllAnalyzers::Tag, info: AnalyzerViolationInfo) &priority=10 +event analyzer_failed(ts: time, atype: AllAnalyzers::Tag, info: AnalyzerViolationInfo) { if ( ! is_protocol_analyzer(atype) && ! is_packet_analyzer(atype) ) return; @@ -64,13 +66,18 @@ event analyzer_violation_info(atype: AllAnalyzers::Tag, info: AnalyzerViolationI # if statement is separate, to allow repeated removal of service, in case there are several # confirmation and violation events - if ( analyzer in c$service_violation ) - return; + if ( analyzer !in c$service_violation ) + add c$service_violation[analyzer]; - add c$service_violation[analyzer]; + # add "-service" to the list of services on removal due to violation, if analyzer was confirmed before + if ( track_removed_services_in_connection && Analyzer::name(atype) in c$service ) + { + local rname = cat("-", Analyzer::name(atype)); + if ( rname !in c$service ) + add c$service[rname]; + } } - event analyzer_violation_info(atype: AllAnalyzers::Tag, info: AnalyzerViolationInfo ) &priority=5 { if ( ! is_protocol_analyzer(atype) && ! is_packet_analyzer(atype) ) @@ -90,13 +97,7 @@ event analyzer_violation_info(atype: AllAnalyzers::Tag, info: AnalyzerViolationI local disabled = disable_analyzer(c$id, aid, F); - # add "-service" to the list of services on removal due to violation, if analyzer was confirmed before - if ( track_removed_services_in_connection && disabled && Analyzer::name(atype) in c$service ) - { - local rname = cat("-", Analyzer::name(atype)); - if ( rname !in c$service ) - add c$service[rname]; - } - + # If no one objected to the removal, send failed event + event analyzer_failed(network_time(), atype, info); } diff --git a/scripts/base/frameworks/analyzer/main.zeek b/scripts/base/frameworks/analyzer/main.zeek index dd911c2d3c..e32c7e040c 100644 --- a/scripts/base/frameworks/analyzer/main.zeek +++ b/scripts/base/frameworks/analyzer/main.zeek @@ -88,6 +88,15 @@ export { ## Returns: The analyzer name corresponding to the tag. global name: function(tag: Analyzer::Tag) : string; + ## Translates an analyzer type to a string with the analyzer's type. + ## + ## Possible values are "protocol", "packet", "file", or "unknown". + ## + ## tag: The analyzer tag. + ## + ## Returns: The analyzer kind corresponding to the tag. + global kind: function(tag: Analyzer::Tag) : string; + ## Check whether the given analyzer name exists. ## ## This can be used before calling :zeek:see:`Analyzer::get_tag` to @@ -246,6 +255,19 @@ function name(atype: AllAnalyzers::Tag) : string return __name(atype); } +function kind(atype: AllAnalyzers::Tag): string + { + if ( is_protocol_analyzer(atype) ) + return "protocol"; + else if ( is_packet_analyzer(atype) ) + return "packet"; + else if ( is_file_analyzer(atype) ) + return "file"; + + Reporter::warning(fmt("Unknown kind of analyzer %s", atype)); + return "unknown"; + } + function has_tag(name: string): bool { return __has_tag(name); diff --git a/scripts/policy/frameworks/analyzer/analyzer-debug-log.zeek b/scripts/policy/frameworks/analyzer/analyzer-debug-log.zeek index e0af2dc65e..153086def8 100644 --- a/scripts/policy/frameworks/analyzer/analyzer-debug-log.zeek +++ b/scripts/policy/frameworks/analyzer/analyzer-debug-log.zeek @@ -1,4 +1,4 @@ -##! Logging analyzer confirmations and violations into analyzer-debug.log +#! Logging analyzer confirmations and violations into analyzer-debug.log @load base/frameworks/config @load base/frameworks/logging @@ -117,19 +117,6 @@ event zeek_init() &priority=5 } -function analyzer_kind(atype: AllAnalyzers::Tag): string - { - if ( is_protocol_analyzer(atype) ) - return "protocol"; - else if ( is_packet_analyzer(atype) ) - return "packet"; - else if ( is_file_analyzer(atype) ) - return "file"; - - Reporter::warning(fmt("Unknown kind of analyzer %s", atype)); - return "unknown"; - } - function populate_from_conn(rec: Info, c: connection) { rec$id = c$id; @@ -159,7 +146,7 @@ event analyzer_confirmation_info(atype: AllAnalyzers::Tag, info: AnalyzerConfirm local rec = Info( $ts=network_time(), $cause="confirmation", - $analyzer_kind=analyzer_kind(atype), + $analyzer_kind=Analyzer::kind(atype), $analyzer_name=Analyzer::name(atype), ); @@ -180,7 +167,7 @@ event analyzer_violation_info(atype: AllAnalyzers::Tag, info: AnalyzerViolationI local rec = Info( $ts=network_time(), $cause="violation", - $analyzer_kind=analyzer_kind(atype), + $analyzer_kind=Analyzer::kind(atype), $analyzer_name=Analyzer::name(atype), $failure_reason=info$reason, ); @@ -210,7 +197,7 @@ hook Analyzer::disabling_analyzer(c: connection, atype: AllAnalyzers::Tag, aid: local rec = Info( $ts=network_time(), $cause="disabled", - $analyzer_kind=analyzer_kind(atype), + $analyzer_kind=Analyzer::kind(atype), $analyzer_name=Analyzer::name(atype), );