mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00

Add parsing of several more types to SAN extension. Make error messages of x509 file analyzer more useful. Fix file ID generation. You apparently have to be very careful which EndOfFile function of the file analysis framework you call... otherwhise it might try to close another file id. This took me quite a while to find. addresses BIT-953, BIT-760, BIT-1150
103 lines
2.7 KiB
Text
103 lines
2.7 KiB
Text
@load base/frameworks/files
|
|
@load base/files/hash
|
|
|
|
module X509;
|
|
|
|
export {
|
|
redef enum Log::ID += { LOG };
|
|
|
|
## Set that keeps track of the certificates which were logged recently.
|
|
global cert_hashes: set[string] &create_expire=1hrs &synchronized &redef;
|
|
|
|
type Info: record {
|
|
## current timestamp
|
|
ts: time &log;
|
|
|
|
## SHA-1 hash of this certificate
|
|
sha1: string &log &optional;
|
|
|
|
## Basic information about the certificate
|
|
certificate: X509::Certificate &log;
|
|
|
|
## The opaque wrapping the certificate. Mainly used
|
|
## for the verify operations
|
|
handle: opaque of x509;
|
|
|
|
## All extensions that were encountered in the certificate
|
|
extensions: vector of X509::Extension &default=vector();
|
|
|
|
## Subject alternative name extension of the certificate
|
|
san: X509::SubjectAlternativeName &optional &log;
|
|
|
|
## Basic constraints extension of the certificate
|
|
basic_constraints: X509::BasicConstraints &optional &log;
|
|
};
|
|
|
|
## Event for accessing logged records.
|
|
global log_x509: event(rec: Info);
|
|
}
|
|
|
|
event bro_init() &priority=5
|
|
{
|
|
Log::create_stream(X509::LOG, [$columns=Info, $ev=log_x509]);
|
|
}
|
|
|
|
redef record Files::Info += {
|
|
## Information about X509 certificates. This is used to keep
|
|
## certificate information until all events have been received.
|
|
x509: X509::Info &optional;
|
|
};
|
|
|
|
# Either, this event arrives first - then info$x509 does not exist
|
|
# yet and this is a no-op, and the sha1 value is set in x509_certificate.
|
|
# Or the x509_certificate event arrives first - then the hash is set here.
|
|
event file_hash(f: fa_file, kind: string, hash: string)
|
|
{
|
|
if ( f$info?$x509 && kind == "sha1" )
|
|
f$info$x509$sha1 = hash;
|
|
}
|
|
|
|
event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &priority=5
|
|
{
|
|
f$info$x509 = [$ts=f$info$ts, $certificate=cert, $handle=cert_ref];
|
|
if ( f$info?$sha1 )
|
|
f$info$x509$sha1 = f$info$sha1;
|
|
}
|
|
|
|
event x509_extension(f: fa_file, ext: X509::Extension) &priority=5
|
|
{
|
|
if ( f$info?$x509 )
|
|
f$info$x509$extensions[|f$info$x509$extensions|] = ext;
|
|
}
|
|
|
|
event x509_ext_basic_constraints(f: fa_file, ext: X509::BasicConstraints) &priority=5
|
|
{
|
|
if ( f$info?$x509 )
|
|
f$info$x509$basic_constraints = ext;
|
|
}
|
|
|
|
event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativeName) &priority=5
|
|
{
|
|
if ( f$info?$x509 )
|
|
f$info$x509$san = ext;
|
|
}
|
|
|
|
event file_state_remove(f: fa_file) &priority=5
|
|
{
|
|
if ( ! f$info?$x509 )
|
|
return;
|
|
|
|
if ( ! f$info$x509?$sha1 )
|
|
{
|
|
Reporter::error(fmt("Certificate without a hash value. Logging skipped. File-id: %s", f$id));
|
|
return;
|
|
}
|
|
|
|
if ( f$info$x509$sha1 in cert_hashes )
|
|
# we already have seen & logged this certificate
|
|
return;
|
|
|
|
add cert_hashes[f$info$x509$sha1];
|
|
|
|
Log::write(LOG, f$info$x509);
|
|
}
|