zeek/scripts/base/frameworks/analyzer/dpd.zeek
Johanna Amann af77a7a83b Analyzer failure logging: tweaks and test fixes
The main part of this commit are changes in tests. A lot of the tests
that previously relied on analyzer.log or dpd.log now use the new
analyzer-failed.log.

I verified all the changes and, as far as I can tell, everything
behaves as it should. This includes the external test baselines.

This change also enables logging of file and packet analyzer to
analyzer_failed.log and fixes some small behavior issues.

The analyzer_failed event is no longer raised when the removal of an
analyzer is vetoed.

If an analyzer is no longer active when an analyzer violation is raised,
currently the analyzer_failed event is raised. This can, e.g., happen
when an analyzer error happens at the very end of the connection. This
makes the behavior more similar to what happened in the past, and also
intuitively seems to make sense.

A bug introduced in the failed service logging was fixed.
2025-06-03 15:56:42 +01:00

113 lines
3.5 KiB
Text

##! 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 remove on violations.
option ignore_violations: set[Analyzer::Tag] = set();
## Ignore violations which go this many bytes into the connection.
## Set to 0 to never ignore protocol violations.
option ignore_violations_after = 10 * 1024;
## Change behavior of service field in conn.log:
## Failed services are no longer removed. Instead, for a failed
## service, a second entry with a "-" in front of it is added.
## E.g. a http connection with a violation would be logged as
## "http,-http".
option track_removed_services_in_connection = F;
}
redef record connection += {
## The set of services (analyzers) for which Zeek has observed a
## violation after the same service had previously been confirmed.
service_violation: set[string] &default=set() &ordered;
};
# Add confirmed protocol analyzers to conn.log service field
event analyzer_confirmation_info(atype: AllAnalyzers::Tag, info: AnalyzerConfirmationInfo) &priority=10
{
if ( ! is_protocol_analyzer(atype) && ! is_packet_analyzer(atype) )
return;
if ( ! info?$c )
return;
local c = info$c;
local analyzer = Analyzer::name(atype);
add c$service[analyzer];
}
# Remove failed analyzers from service field and add them to c$service_violation
# Low priority to allow other handlers to check if the analyzer was confirmed
event analyzer_failed(ts: time, atype: AllAnalyzers::Tag, info: AnalyzerViolationInfo) &priority=-5
{
if ( ! is_protocol_analyzer(atype) )
return;
if ( ! info?$c )
return;
local c = info$c;
local analyzer = Analyzer::name(atype);
# If the service hasn't been confirmed yet, or already failed,
# don't generate a log message for the protocol violation.
if ( analyzer !in c$service )
return;
# If removed service tracking is active, don't delete the service here.
if ( ! track_removed_services_in_connection )
delete c$service[analyzer];
# 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 )
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) )
return;
if ( ! info?$c || ! info?$aid )
return;
if ( atype in ignore_violations )
return;
local c = info$c;
local aid = info$aid;
local size = c$orig$size + c$resp$size;
if ( ignore_violations_after > 0 && size > ignore_violations_after )
return;
# analyzer already was removed or connection finished
# let's still log this.
if ( lookup_connection_analyzer_id(c$id, atype) == 0 )
{
event analyzer_failed(network_time(), atype, info);
return;
}
local disabled = disable_analyzer(c$id, aid, F);
# If analyzer was disabled, send failed event
if ( disabled )
event analyzer_failed(network_time(), atype, info);
}