Support for log filter policy hooks

This adds a "policy" hook into the logging framework's streams and
filters to replace the existing log filter predicates. The hook
signature is as follows:

    hook(rec: any, id: Log::ID, filter: Log::Filter);

The logging manager invokes hooks on each log record. Hooks can veto
log records via a break, and modify them if necessary. Log filters
inherit the stream-level hook, but can override or remove the hook as
needed.

The distribution's existing log streams now come with pre-defined
hooks that users can add handlers to. Their name is standardized as
"log_policy" by convention, with additional suffixes when a module
provides multiple streams. The following adds a handler to the Conn
module's default log policy hook:

    hook Conn::log_policy(rec: Conn::Info, id: Log::ID, filter: Log::Filter)
            {
            if ( some_veto_reason(rec) )
                break;
            }

By default, this handler will get invoked for any log filter
associated with the Conn::LOG stream.

The existing predicates are deprecated for removal in 4.1 but continue
to work.
This commit is contained in:
Christian Kreibich 2020-09-21 16:09:36 -07:00
parent c8545c85d8
commit 1bd658da8f
61 changed files with 289 additions and 85 deletions

View file

@ -13,6 +13,9 @@ export {
## The connection logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type which contains column fields of the connection log.
type Info: record {
## This is the time of the first packet.
@ -158,7 +161,7 @@ redef record connection += {
event zeek_init() &priority=5
{
Log::create_stream(Conn::LOG, [$columns=Info, $ev=log_conn, $path="conn"]);
Log::create_stream(Conn::LOG, [$columns=Info, $ev=log_conn, $path="conn", $policy=log_policy]);
}
function conn_state(c: connection, trans: transport_proto): string

View file

@ -7,6 +7,8 @@ module DCE_RPC;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts : time &log;
@ -65,7 +67,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(DCE_RPC::LOG, [$columns=Info, $path="dce_rpc"]);
Log::create_stream(DCE_RPC::LOG, [$columns=Info, $path="dce_rpc", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DCE_RPC, ports);
}

View file

@ -12,6 +12,8 @@ module DHCP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the column fields of the DHCP log.
type Info: record {
## The earliest time at which a DHCP message over the
@ -122,7 +124,7 @@ redef likely_server_ports += { 67/udp };
event zeek_init() &priority=5
{
Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp, $path="dhcp"]);
Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp, $path="dhcp", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DHCP, ports);
}

View file

@ -8,6 +8,8 @@ module DNP3;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Time of the request.
ts: time &log;
@ -40,7 +42,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(DNP3::LOG, [$columns=Info, $ev=log_dnp3, $path="dnp3"]);
Log::create_stream(DNP3::LOG, [$columns=Info, $ev=log_dnp3, $path="dnp3", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DNP3_TCP, ports);
}

View file

@ -11,6 +11,9 @@ export {
## The DNS logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type which contains the column fields of the DNS log.
type Info: record {
## The earliest time at which a DNS protocol message over the
@ -160,7 +163,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns, $path="dns"]);
Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns, $path="dns", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DNS, ports);
}

View file

@ -18,6 +18,9 @@ export {
## The FTP protocol logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## List of commands that should have their command/response pairs logged.
option logged_commands = {
"APPE", "DELE", "RETR", "STOR", "STOU", "ACCT", "PORT", "PASV", "EPRT",
@ -61,7 +64,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp, $path="ftp"]);
Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp, $path="ftp", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_FTP, ports);
}

View file

@ -12,6 +12,8 @@ module HTTP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## Indicate a type of attack or compromise in the record to be logged.
type Tags: enum {
## Placeholder.
@ -145,7 +147,7 @@ redef likely_server_ports += { ports };
# Initialize the HTTP logging stream and ports.
event zeek_init() &priority=5
{
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http, $path="http"]);
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http, $path="http", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_HTTP, ports);
}

View file

@ -8,6 +8,8 @@ export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp when the command was seen.
ts: time &log;
@ -43,7 +45,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log, $path="irc"]);
Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log, $path="irc", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_IRC, ports);
}

View file

@ -9,6 +9,8 @@ module KRB;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
@ -81,7 +83,7 @@ event zeek_init() &priority=5
{
Analyzer::register_for_ports(Analyzer::ANALYZER_KRB, udp_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_KRB_TCP, tcp_ports);
Log::create_stream(KRB::LOG, [$columns=Info, $ev=log_krb, $path="kerberos"]);
Log::create_stream(KRB::LOG, [$columns=Info, $ev=log_krb, $path="kerberos", $policy=log_policy]);
}
function set_session(c: connection): bool

View file

@ -7,6 +7,8 @@ module Modbus;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Time of the request.
ts: time &log;
@ -34,7 +36,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(Modbus::LOG, [$columns=Info, $ev=log_modbus, $path="modbus"]);
Log::create_stream(Modbus::LOG, [$columns=Info, $ev=log_modbus, $path="modbus", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_MODBUS, ports);
}

View file

@ -8,6 +8,8 @@ module MySQL;
export {
redef enum Log::ID += { mysql::LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
@ -43,7 +45,7 @@ const ports = { 1434/tcp, 3306/tcp };
event zeek_init() &priority=5
{
Log::create_stream(mysql::LOG, [$columns=Info, $ev=log_mysql, $path="mysql"]);
Log::create_stream(mysql::LOG, [$columns=Info, $ev=log_mysql, $path="mysql", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_MYSQL, ports);
}

View file

@ -6,6 +6,8 @@ module NTLM;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts : time &log;
@ -48,7 +50,7 @@ redef record connection += {
event zeek_init() &priority=5
{
Log::create_stream(NTLM::LOG, [$columns=Info, $path="ntlm"]);
Log::create_stream(NTLM::LOG, [$columns=Info, $path="ntlm", $policy=log_policy]);
}
function set_session(c: connection)

View file

@ -3,6 +3,8 @@ module NTP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
@ -59,7 +61,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Analyzer::register_for_ports(Analyzer::ANALYZER_NTP, ports);
Log::create_stream(NTP::LOG, [$columns = Info, $ev = log_ntp, $path="ntp"]);
Log::create_stream(NTP::LOG, [$columns = Info, $ev = log_ntp, $path="ntp", $policy=log_policy]);
}
event ntp_message(c: connection, is_orig: bool, msg: NTP::Message) &priority=5

View file

@ -9,6 +9,8 @@ module RADIUS;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts : time &log;
@ -63,7 +65,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius, $path="radius"]);
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius, $path="radius", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_RADIUS, ports);
}

View file

@ -8,6 +8,8 @@ module RDP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
@ -95,7 +97,7 @@ redef likely_server_ports += { rdp_ports, rdpeudp_ports };
event zeek_init() &priority=5
{
Log::create_stream(RDP::LOG, [$columns=RDP::Info, $ev=log_rdp, $path="rdp"]);
Log::create_stream(RDP::LOG, [$columns=RDP::Info, $ev=log_rdp, $path="rdp", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_RDP, rdp_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_RDPEUDP, rdpeudp_ports);
}

View file

@ -5,6 +5,8 @@ module RFB;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the RFB log.
type Info: record {
## Timestamp for when the event happened.
@ -83,7 +85,7 @@ redef record connection += {
event zeek_init() &priority=5
{
Log::create_stream(RFB::LOG, [$columns=Info, $ev=log_rfb, $path="rfb"]);
Log::create_stream(RFB::LOG, [$columns=Info, $ev=log_rfb, $path="rfb", $policy=log_policy]);
}
function write_log(c:connection)

View file

@ -11,6 +11,8 @@ module SIP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the SIP log.
type Info: record {
## Timestamp for when the request happened.
@ -104,7 +106,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(SIP::LOG, [$columns=Info, $ev=log_sip, $path="sip"]);
Log::create_stream(SIP::LOG, [$columns=Info, $ev=log_sip, $path="sip", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SIP, ports);
}

View file

@ -10,6 +10,9 @@ export {
MAPPING_LOG,
FILES_LOG
};
global log_policy_files: Log::PolicyHook;
global log_policy_mapping: Log::PolicyHook;
## Abstracted actions for SMB file actions.
type Action: enum {
@ -179,8 +182,8 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(SMB::FILES_LOG, [$columns=SMB::FileInfo, $path="smb_files"]);
Log::create_stream(SMB::MAPPING_LOG, [$columns=SMB::TreeInfo, $path="smb_mapping"]);
Log::create_stream(SMB::FILES_LOG, [$columns=SMB::FileInfo, $path="smb_files", $policy=log_policy_files]);
Log::create_stream(SMB::MAPPING_LOG, [$columns=SMB::TreeInfo, $path="smb_mapping", $policy=log_policy_mapping]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SMB, ports);
}

View file

@ -8,6 +8,8 @@ module SMTP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Time when the message was first seen.
ts: time &log;
@ -98,7 +100,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp, $path="smtp"]);
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp, $path="smtp", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SMTP, ports);
}

View file

@ -7,6 +7,8 @@ module SNMP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## Information tracked per SNMP session.
type Info: record {
## Timestamp of first packet belonging to the SNMP session.
@ -71,7 +73,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Analyzer::register_for_ports(Analyzer::ANALYZER_SNMP, ports);
Log::create_stream(SNMP::LOG, [$columns=SNMP::Info, $ev=log_snmp, $path="snmp"]);
Log::create_stream(SNMP::LOG, [$columns=SNMP::Info, $ev=log_snmp, $path="snmp", $policy=log_policy]);
}
function init_state(c: connection, h: SNMP::Header): Info

View file

@ -7,6 +7,8 @@ module SOCKS;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## Whether passwords are captured or not.
option default_capture_password = F;
@ -53,7 +55,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks, $path="socks"]);
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks, $path="socks", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SOCKS, ports);
}

View file

@ -9,6 +9,9 @@ export {
## The SSH protocol logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the SSH log.
type Info: record {
## Time when the SSH connection began.
@ -143,7 +146,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Analyzer::register_for_ports(Analyzer::ANALYZER_SSH, ports);
Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh, $path="ssh"]);
Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh, $path="ssh", $policy=log_policy]);
}
function set_session(c: connection)

View file

@ -10,6 +10,8 @@ module SSL;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the SSL log.
type Info: record {
## Time when the SSL connection was first detected.
@ -147,7 +149,7 @@ redef likely_server_ports += { ssl_ports, dtls_ports };
event zeek_init() &priority=5
{
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl"]);
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ssl_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_DTLS, dtls_ports);
}

View file

@ -8,6 +8,8 @@ module Syslog;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the syslog log.
type Info: record {
## Timestamp when the syslog message was seen.
@ -36,7 +38,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(Syslog::LOG, [$columns=Info, $path="syslog"]);
Log::create_stream(Syslog::LOG, [$columns=Info, $path="syslog", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SYSLOG, ports);
}