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

This commit adds two new bifs, x509_check_hostname and x509_check_cert_hostname. These bifs can be used to check if a given hostname which can, e.g., be sent in a SNI is valid for a specific certificate. This PR furthermore modifies the ssl logs again, and adds information about this to the log-file. Furthermore we now by default remove the server certificate information from ssl.log - I doubt that this is often looked at, it is not present in TLS 1.3, we do still have the SNI, and if you need it you have the information in x509.log. This also fixes a small potential problem in X509.cc assuming there might be SAN-entries that contain null-bytes. Baseline update will follow in another commit.
194 lines
5.8 KiB
Text
194 lines
5.8 KiB
Text
@load ./main
|
|
@load base/utils/conn-ids
|
|
@load base/frameworks/files
|
|
@load base/files/x509
|
|
|
|
module SSL;
|
|
|
|
export {
|
|
## Set this to true to includd the server certificate subject and
|
|
## issuer from the SSL log file. This information is still available
|
|
## in x509.log.
|
|
const log_include_server_certificate_subject_issuer = F &redef;
|
|
|
|
## Set this to true to include the client certificate subject
|
|
## and issuer in the SSL logfile. This information is rarely present
|
|
## and probably only interesting in very specific circumstances
|
|
const log_include_client_certificate_subject_issuer = F &redef;
|
|
|
|
redef record Info += {
|
|
## Chain of certificates offered by the server to validate its
|
|
## complete signing chain.
|
|
cert_chain: vector of Files::Info &optional;
|
|
|
|
## An ordered vector of all certificate fingerprints for the
|
|
## certificates offered by the server.
|
|
cert_chain_fps: vector of string &optional &log;
|
|
|
|
## Chain of certificates offered by the client to validate its
|
|
## complete signing chain.
|
|
client_cert_chain: vector of Files::Info &optional;
|
|
|
|
## An ordered vector of all certificate fingerprints for the
|
|
## certificates offered by the client.
|
|
client_cert_chain_fps: vector of string &optional &log;
|
|
|
|
## Subject of the X.509 certificate offered by the server.
|
|
subject: string &log &optional;
|
|
|
|
## Issuer of the signer of the X.509 certificate offered by the
|
|
## server.
|
|
issuer: string &log &optional;
|
|
|
|
## Subject of the X.509 certificate offered by the client.
|
|
client_subject: string &log &optional;
|
|
|
|
## Subject of the signer of the X.509 certificate offered by the
|
|
## client.
|
|
client_issuer: string &log &optional;
|
|
|
|
## Set to true if the hostname sent in the SNI matches the certificate.
|
|
## Set to false if they do not match. Unset if the client did not send
|
|
## an SNI.
|
|
sni_matches_cert: bool &log &optional;
|
|
|
|
## Current number of certificates seen from either side. Used
|
|
## to create file handles.
|
|
server_depth: count &default=0;
|
|
client_depth: count &default=0;
|
|
};
|
|
|
|
## Default file handle provider for SSL.
|
|
global get_file_handle: function(c: connection, is_orig: bool): string;
|
|
|
|
## Default file describer for SSL.
|
|
global describe_file: function(f: fa_file): string;
|
|
}
|
|
|
|
function get_file_handle(c: connection, is_orig: bool): string
|
|
{
|
|
# Unused. File handles are generated in the analyzer.
|
|
return "";
|
|
}
|
|
|
|
function describe_file(f: fa_file): string
|
|
{
|
|
if ( f$source != "SSL" || ! f?$info || ! f$info?$x509 || ! f$info$x509?$certificate )
|
|
return "";
|
|
|
|
# It is difficult to reliably describe a certificate - especially since
|
|
# we do not know when this function is called (hence, if the data structures
|
|
# are already populated).
|
|
#
|
|
# Just return a bit of our connection information and hope that that is good enough.
|
|
for ( cid, c in f$conns )
|
|
{
|
|
if ( c?$ssl )
|
|
{
|
|
return cat(c$id$resp_h, ":", c$id$resp_p);
|
|
}
|
|
}
|
|
|
|
return cat("Serial: ", f$info$x509$certificate$serial, " Subject: ",
|
|
f$info$x509$certificate$subject, " Issuer: ",
|
|
f$info$x509$certificate$issuer);
|
|
}
|
|
|
|
event zeek_init() &priority=5
|
|
{
|
|
Files::register_protocol(Analyzer::ANALYZER_SSL,
|
|
[$get_file_handle = SSL::get_file_handle,
|
|
$describe = SSL::describe_file]);
|
|
|
|
Files::register_protocol(Analyzer::ANALYZER_DTLS,
|
|
[$get_file_handle = SSL::get_file_handle,
|
|
$describe = SSL::describe_file]);
|
|
|
|
|
|
local ssl_filter = Log::get_filter(SSL::LOG, "default");
|
|
if ( ssl_filter$name != "<not found>" )
|
|
{
|
|
if ( ! ssl_filter?$exclude )
|
|
ssl_filter$exclude = set();
|
|
if ( ! log_include_server_certificate_subject_issuer )
|
|
{
|
|
add ssl_filter$exclude["subject"];
|
|
add ssl_filter$exclude["issuer"];
|
|
}
|
|
if ( ! log_include_client_certificate_subject_issuer )
|
|
{
|
|
add ssl_filter$exclude["client_subject"];
|
|
add ssl_filter$exclude["client_issuer"];
|
|
}
|
|
Log::add_filter(SSL::LOG, ssl_filter);
|
|
}
|
|
}
|
|
|
|
event file_sniff(f: fa_file, meta: fa_metadata) &priority=5
|
|
{
|
|
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 &is_assigned; # to help static analysis
|
|
|
|
for ( cid, c in f$conns )
|
|
{
|
|
if ( ! c?$ssl )
|
|
return;
|
|
}
|
|
|
|
if ( ! c$ssl?$cert_chain )
|
|
{
|
|
c$ssl$cert_chain = vector();
|
|
c$ssl$client_cert_chain = vector();
|
|
c$ssl$cert_chain_fps = string_vec();
|
|
c$ssl$client_cert_chain_fps = string_vec();
|
|
}
|
|
|
|
if ( f$is_orig )
|
|
c$ssl$client_cert_chain += f$info;
|
|
else
|
|
c$ssl$cert_chain += f$info;
|
|
}
|
|
|
|
hook ssl_finishing(c: connection) &priority=20
|
|
{
|
|
if ( c$ssl?$cert_chain)
|
|
for ( i in c$ssl$cert_chain )
|
|
if ( c$ssl$cert_chain[i]?$x509 && c$ssl$cert_chain[i]$x509?$fp )
|
|
c$ssl$cert_chain_fps += c$ssl$cert_chain[i]$x509$fp;
|
|
|
|
if ( c$ssl?$client_cert_chain )
|
|
for ( i in c$ssl$client_cert_chain )
|
|
if ( c$ssl$client_cert_chain[i]?$x509 && c$ssl$client_cert_chain[i]$x509?$fp )
|
|
c$ssl$client_cert_chain_fps += c$ssl$client_cert_chain[i]$x509$fp;
|
|
|
|
if ( c$ssl?$cert_chain && |c$ssl$cert_chain| > 0 &&
|
|
c$ssl$cert_chain[0]?$x509 )
|
|
{
|
|
if ( c$ssl?$server_name )
|
|
{
|
|
if ( x509_check_cert_hostname(c$ssl$cert_chain[0]$x509$handle, c$ssl$server_name) != "" )
|
|
c$ssl$sni_matches_cert = T;
|
|
else
|
|
c$ssl$sni_matches_cert = F;
|
|
}
|
|
|
|
c$ssl$subject = c$ssl$cert_chain[0]$x509$certificate$subject;
|
|
c$ssl$issuer = c$ssl$cert_chain[0]$x509$certificate$issuer;
|
|
}
|
|
|
|
if ( c$ssl?$client_cert_chain && |c$ssl$client_cert_chain| > 0 &&
|
|
c$ssl$client_cert_chain[0]?$x509 )
|
|
{
|
|
c$ssl$client_subject = c$ssl$client_cert_chain[0]$x509$certificate$subject;
|
|
c$ssl$client_issuer = c$ssl$client_cert_chain[0]$x509$certificate$issuer;
|
|
}
|
|
}
|