zeek/scripts/policy/protocols/ssl/log-hostcerts-only.zeek
SG 42bf41aca1 check for the existance of f?$conns in file_sniff event in policy/protocols/ssl/log-hostcerts-only.zeek
In using the corelight/bro-xor-exe-plugin (https://github.com/corelight/bro-xor-exe-plugin) I noticed this error when running the PCAP trace file in its tests directory:

1428602842.525435 expression error in /opt/zeek/share/zeek/policy/protocols/ssl/log-hostcerts-only.zeek, line 44: field value missing (X509::f$conns)

Examining log-hostcerts-only.zeek, I saw that although f$conns is being checked for length, it's not being checked to see if it exists first.

This commit changes "if ( |f$conns| != 1 )" to "if (( ! f?$conns ) || ( |f$conns| != 1 ))" so that the script returns if there is no f$conns field.

In my local testing, this seems to fix the error. My testing was being done with v3.0.5, but I think this patch can be applied to both the 3.0.x and 3.1.x branches.
2020-04-16 10:19:59 -06:00

83 lines
2.1 KiB
Text

##! When this script is loaded, only the host certificates (client and server)
##! will be logged to x509.log. Logging of all other certificates will be suppressed.
@load base/protocols/ssl
@load base/files/x509
module X509;
export {
redef record Info += {
## Logging of certificate is suppressed if set to F
logcert: bool &default=T;
};
}
# We need both the Info and the fa_file record modified.
# The only instant when we have both, the connection and the
# file available without having to loop is in the file_over_new_connection
# event.
# When that event is raised, the x509 record in f$info (which is the only
# record the logging framework gets) is not yet available. So - we
# have to do this two times, sorry.
# Alternatively, we could place it info Files::Info first - but we would
# still have to copy it.
redef record fa_file += {
logcert: bool &default=T;
};
function host_certs_only(rec: X509::Info): bool
{
return rec$logcert;
}
event zeek_init() &priority=2
{
local f = Log::get_filter(X509::LOG, "default");
Log::remove_filter(X509::LOG, "default"); # disable default logging
f$pred=host_certs_only; # and add our predicate
Log::add_filter(X509::LOG, f);
}
event file_sniff(f: fa_file, meta: fa_metadata) &priority=4
{
if (( ! f?$conns ) || ( |f$conns| != 1 ))
return;
if ( ! f?$info || ! f$info?$mime_type )
return;
if ( ! ( f$info$mime_type == "application/x-x509-ca-cert" || f$info$mime_type == "application/x-x509-user-cert"
|| f$info$mime_type == "application/pkix-cert" ) )
return;
local c: connection;
for ( cid, c in f$conns )
{
if ( ! c?$ssl )
return;
}
local chain: vector of string;
if ( f$is_orig )
chain = c$ssl$client_cert_chain_fuids;
else
chain = c$ssl$cert_chain_fuids;
if ( |chain| == 0 )
{
Reporter::warning(fmt("Certificate not in chain? (fuid %s)", f$id));
return;
}
# Check if this is the host certificate
if ( f$id != chain[0] )
f$logcert=F;
}
event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &priority=2
{
f$info$x509$logcert = f$logcert; # info record available, copy information.
}