mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 23:28:20 +00:00
Change x509 log - now certificates are only logged once per hour.
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
This commit is contained in:
parent
7eb6b5133e
commit
0d50b8b04f
10 changed files with 242 additions and 55 deletions
|
@ -6,12 +6,15 @@ module X509;
|
||||||
export {
|
export {
|
||||||
redef enum Log::ID += { LOG };
|
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 {
|
type Info: record {
|
||||||
## current timestamp
|
## current timestamp
|
||||||
ts: time &log &default=network_time();
|
ts: time &log;
|
||||||
|
|
||||||
## file id of this certificate
|
## SHA-1 hash of this certificate
|
||||||
id: string &log;
|
sha1: string &log &optional;
|
||||||
|
|
||||||
## Basic information about the certificate
|
## Basic information about the certificate
|
||||||
certificate: X509::Certificate &log;
|
certificate: X509::Certificate &log;
|
||||||
|
@ -24,7 +27,7 @@ export {
|
||||||
extensions: vector of X509::Extension &default=vector();
|
extensions: vector of X509::Extension &default=vector();
|
||||||
|
|
||||||
## Subject alternative name extension of the certificate
|
## Subject alternative name extension of the certificate
|
||||||
san: string_vec &optional &log;
|
san: X509::SubjectAlternativeName &optional &log;
|
||||||
|
|
||||||
## Basic constraints extension of the certificate
|
## Basic constraints extension of the certificate
|
||||||
basic_constraints: X509::BasicConstraints &optional &log;
|
basic_constraints: X509::BasicConstraints &optional &log;
|
||||||
|
@ -45,9 +48,20 @@ redef record Files::Info += {
|
||||||
x509: X509::Info &optional;
|
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
|
event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &priority=5
|
||||||
{
|
{
|
||||||
f$info$x509 = [$id=f$id, $certificate=cert, $handle=cert_ref];
|
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
|
event x509_extension(f: fa_file, ext: X509::Extension) &priority=5
|
||||||
|
@ -62,10 +76,10 @@ event x509_ext_basic_constraints(f: fa_file, ext: X509::BasicConstraints) &prior
|
||||||
f$info$x509$basic_constraints = ext;
|
f$info$x509$basic_constraints = ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
event x509_ext_subject_alternative_name(f: fa_file, names: string_vec) &priority=5
|
event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativeName) &priority=5
|
||||||
{
|
{
|
||||||
if ( f$info?$x509 )
|
if ( f$info?$x509 )
|
||||||
f$info$x509$san = names;
|
f$info$x509$san = ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
event file_state_remove(f: fa_file) &priority=5
|
event file_state_remove(f: fa_file) &priority=5
|
||||||
|
@ -73,5 +87,17 @@ event file_state_remove(f: fa_file) &priority=5
|
||||||
if ( ! f$info?$x509 )
|
if ( ! f$info?$x509 )
|
||||||
return;
|
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);
|
Log::write(LOG, f$info$x509);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2750,7 +2750,7 @@ export {
|
||||||
|
|
||||||
module X509;
|
module X509;
|
||||||
export {
|
export {
|
||||||
type X509::Certificate: record {
|
type Certificate: record {
|
||||||
version: count; ##< Version number.
|
version: count; ##< Version number.
|
||||||
serial: string; ##< Serial number.
|
serial: string; ##< Serial number.
|
||||||
subject: string; ##< Subject.
|
subject: string; ##< Subject.
|
||||||
|
@ -2767,7 +2767,7 @@ export {
|
||||||
#path_len: count &optional; ##< indicates the path_length value in the X509v3 BasicConstraints extension
|
#path_len: count &optional; ##< indicates the path_length value in the X509v3 BasicConstraints extension
|
||||||
} &log;
|
} &log;
|
||||||
|
|
||||||
type X509::Extension: record {
|
type Extension: record {
|
||||||
name: string; ##< long name of extension. oid if name not known
|
name: string; ##< long name of extension. oid if name not known
|
||||||
short_name: string &optional; ##< short name of extension if known.
|
short_name: string &optional; ##< short name of extension if known.
|
||||||
oid: string; ##< oid of extension
|
oid: string; ##< oid of extension
|
||||||
|
@ -2775,13 +2775,21 @@ export {
|
||||||
value: string; ##< extension content parsed to string for known extensions. Raw data otherwise.
|
value: string; ##< extension content parsed to string for known extensions. Raw data otherwise.
|
||||||
};
|
};
|
||||||
|
|
||||||
type X509::BasicConstraints: record {
|
type BasicConstraints: record {
|
||||||
ca: bool; ##< CA flag set?
|
ca: bool; ##< CA flag set?
|
||||||
path_len: count &optional;
|
path_len: count &optional; ##< maximum path length
|
||||||
} &log;
|
} &log;
|
||||||
|
|
||||||
|
type SubjectAlternativeName: record {
|
||||||
|
dns: string_vec &optional &log; ##< list of DNS entries in SAN
|
||||||
|
uri: string_vec &optional &log; ##< list of URI entries in SAN
|
||||||
|
email: string_vec &optional &log; ##< list of email entries in SAN
|
||||||
|
ip: addr_vec &optional &log; ##< list of IP entries in SAN
|
||||||
|
other_fields: bool; ##< true if the certificate contained other, not recognized or parsed name fields
|
||||||
|
};
|
||||||
|
|
||||||
## Result of an X509 certificate chain verification
|
## Result of an X509 certificate chain verification
|
||||||
type X509::Result: record {
|
type Result: record {
|
||||||
## OpenSSL result code
|
## OpenSSL result code
|
||||||
result: count;
|
result: count;
|
||||||
## Result as string
|
## Result as string
|
||||||
|
|
|
@ -11,17 +11,17 @@ export {
|
||||||
## complete signing chain.
|
## complete signing chain.
|
||||||
cert_chain: vector of Files::Info &optional;
|
cert_chain: vector of Files::Info &optional;
|
||||||
|
|
||||||
## An ordered vector of all certicate file unique IDs for the
|
## An ordered vector of all certicate sha1 hashes for the
|
||||||
## certificates offered by the server.
|
## certificates offered by the server.
|
||||||
cert_chain_fuids: vector of string &optional &log;
|
cert_chain_sha1s: vector of string &optional &log;
|
||||||
|
|
||||||
## Chain of certificates offered by the client to validate its
|
## Chain of certificates offered by the client to validate its
|
||||||
## complete signing chain.
|
## complete signing chain.
|
||||||
client_cert_chain: vector of Files::Info &optional;
|
client_cert_chain: vector of Files::Info &optional;
|
||||||
|
|
||||||
## An ordered vector of all certicate file unique IDs for the
|
## An ordered vector of all certicate sha1 hashes for the
|
||||||
## certificates offered by the client.
|
## certificates offered by the client.
|
||||||
client_cert_chain_fuids: vector of string &optional &log;
|
client_cert_chain_sha1s: vector of string &optional &log;
|
||||||
|
|
||||||
## Subject of the X.509 certificate offered by the server.
|
## Subject of the X.509 certificate offered by the server.
|
||||||
subject: string &log &optional;
|
subject: string &log &optional;
|
||||||
|
@ -34,6 +34,11 @@ export {
|
||||||
## Subject of the signer of the X.509 certificate offered by the
|
## Subject of the signer of the X.509 certificate offered by the
|
||||||
## client.
|
## client.
|
||||||
client_issuer: string &log &optional;
|
client_issuer: string &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.
|
## Default file handle provider for SSL.
|
||||||
|
@ -45,7 +50,22 @@ export {
|
||||||
|
|
||||||
function get_file_handle(c: connection, is_orig: bool): string
|
function get_file_handle(c: connection, is_orig: bool): string
|
||||||
{
|
{
|
||||||
return cat(Analyzer::ANALYZER_SSL, c$start_time);
|
set_session(c);
|
||||||
|
|
||||||
|
local depth: count;
|
||||||
|
|
||||||
|
if ( is_orig )
|
||||||
|
{
|
||||||
|
depth = c$ssl$client_depth;
|
||||||
|
++c$ssl$client_depth;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
depth = c$ssl$server_depth;
|
||||||
|
++c$ssl$server_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cat(Analyzer::ANALYZER_SSL, c$start_time, is_orig, id_string(c$id), depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
function describe_file(f: fa_file): string
|
function describe_file(f: fa_file): string
|
||||||
|
@ -54,7 +74,19 @@ function describe_file(f: fa_file): string
|
||||||
if ( f$source != "SSL" )
|
if ( f$source != "SSL" )
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
# Fixme!
|
# 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 in f$conns )
|
||||||
|
{
|
||||||
|
if ( f$conns[cid]?$ssl )
|
||||||
|
{
|
||||||
|
local c = f$conns[cid];
|
||||||
|
return cat(c$id$resp_h, ":", c$id$resp_p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -75,30 +107,22 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
|
||||||
{
|
{
|
||||||
c$ssl$cert_chain = vector();
|
c$ssl$cert_chain = vector();
|
||||||
c$ssl$client_cert_chain = vector();
|
c$ssl$client_cert_chain = vector();
|
||||||
c$ssl$cert_chain_fuids = string_vec();
|
|
||||||
c$ssl$client_cert_chain_fuids = string_vec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( is_orig )
|
if ( is_orig )
|
||||||
{
|
|
||||||
c$ssl$client_cert_chain[|c$ssl$client_cert_chain|] = f$info;
|
c$ssl$client_cert_chain[|c$ssl$client_cert_chain|] = f$info;
|
||||||
c$ssl$client_cert_chain_fuids[|c$ssl$client_cert_chain_fuids|] = f$id;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
c$ssl$cert_chain[|c$ssl$cert_chain|] = f$info;
|
c$ssl$cert_chain[|c$ssl$cert_chain|] = f$info;
|
||||||
c$ssl$cert_chain_fuids[|c$ssl$cert_chain_fuids|] = f$id;
|
|
||||||
}
|
|
||||||
|
|
||||||
Files::add_analyzer(f, Files::ANALYZER_X509);
|
Files::add_analyzer(f, Files::ANALYZER_X509);
|
||||||
# always calculate hashes for certificates
|
# always calculate hashes. SHA1 is always required for certificates.
|
||||||
Files::add_analyzer(f, Files::ANALYZER_MD5);
|
Files::add_analyzer(f, Files::ANALYZER_MD5);
|
||||||
Files::add_analyzer(f, Files::ANALYZER_SHA1);
|
Files::add_analyzer(f, Files::ANALYZER_SHA1);
|
||||||
}
|
}
|
||||||
|
|
||||||
event ssl_established(c: connection) &priority=6
|
event ssl_established(c: connection) &priority=6
|
||||||
{
|
{
|
||||||
# update subject and issuer information
|
# update subject and issuer information as well as sha1 hashes
|
||||||
if ( c$ssl?$cert_chain && |c$ssl$cert_chain| > 0 )
|
if ( c$ssl?$cert_chain && |c$ssl$cert_chain| > 0 )
|
||||||
{
|
{
|
||||||
c$ssl$subject = c$ssl$cert_chain[0]$x509$certificate$subject;
|
c$ssl$subject = c$ssl$cert_chain[0]$x509$certificate$subject;
|
||||||
|
@ -110,4 +134,19 @@ event ssl_established(c: connection) &priority=6
|
||||||
c$ssl$client_subject = c$ssl$client_cert_chain[0]$x509$certificate$subject;
|
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;
|
c$ssl$client_issuer = c$ssl$client_cert_chain[0]$x509$certificate$issuer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( c$ssl?$cert_chain )
|
||||||
|
{
|
||||||
|
c$ssl$cert_chain_sha1s = string_vec();
|
||||||
|
for ( i in c$ssl$cert_chain )
|
||||||
|
c$ssl$cert_chain_sha1s[i] = c$ssl$cert_chain[i]$x509$sha1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( c$ssl?$client_cert_chain )
|
||||||
|
{
|
||||||
|
c$ssl$client_cert_chain_sha1s = string_vec();
|
||||||
|
for ( i in c$ssl$client_cert_chain )
|
||||||
|
c$ssl$client_cert_chain_sha1s[i] = c$ssl$client_cert_chain[i]$x509$sha1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
## :bro:id:`SSL::cipher_desc` table maps them to descriptive names.
|
## :bro:id:`SSL::cipher_desc` table maps them to descriptive names.
|
||||||
##
|
##
|
||||||
## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello
|
## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello
|
||||||
## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
|
## ssl_session_ticket_handshake x509_certificate
|
||||||
event ssl_client_hello%(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: index_vec%);
|
event ssl_client_hello%(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: index_vec%);
|
||||||
|
|
||||||
## Generated for an SSL/TLS server's initial *hello* message. SSL/TLS sessions
|
## Generated for an SSL/TLS server's initial *hello* message. SSL/TLS sessions
|
||||||
|
@ -58,7 +58,7 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, client
|
||||||
## standardized as part of the SSL/TLS protocol.
|
## standardized as part of the SSL/TLS protocol.
|
||||||
##
|
##
|
||||||
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension
|
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension
|
||||||
## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
|
## ssl_session_ticket_handshake x509_certificate
|
||||||
event ssl_server_hello%(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count%);
|
event ssl_server_hello%(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count%);
|
||||||
|
|
||||||
## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS
|
## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS
|
||||||
|
@ -92,7 +92,7 @@ event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
|
||||||
## c: The connection.
|
## c: The connection.
|
||||||
##
|
##
|
||||||
## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello
|
## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello
|
||||||
## ssl_session_ticket_handshake
|
## ssl_session_ticket_handshake x509_certificate
|
||||||
event ssl_established%(c: connection%);
|
event ssl_established%(c: connection%);
|
||||||
|
|
||||||
## Generated for SSL/TLS alert records. SSL/TLS sessions start with an
|
## Generated for SSL/TLS alert records. SSL/TLS sessions start with an
|
||||||
|
|
|
@ -235,9 +235,9 @@ refine connection SSL_Conn += {
|
||||||
{
|
{
|
||||||
const bytestring& cert = (*certificates)[i];
|
const bytestring& cert = (*certificates)[i];
|
||||||
|
|
||||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()), cert.length(),
|
string fid = file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()), cert.length(),
|
||||||
bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn(), ${rec.is_orig});
|
bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn(), ${rec.is_orig});
|
||||||
file_mgr->EndOfFile(bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn());
|
file_mgr->EndOfFile(fid);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -108,7 +108,7 @@ public:
|
||||||
* cached and passed back in to a subsequent function call in order
|
* cached and passed back in to a subsequent function call in order
|
||||||
* to avoid costly file handle lookups (which have to go through
|
* to avoid costly file handle lookups (which have to go through
|
||||||
* the \c get_file_handle script-layer event). An empty string
|
* the \c get_file_handle script-layer event). An empty string
|
||||||
* indicates the associate file is not going to be analyzed further.
|
* indicates the associated file is not going to be analyzed further.
|
||||||
*/
|
*/
|
||||||
std::string DataIn(const u_char* data, uint64 len, analyzer::Tag tag,
|
std::string DataIn(const u_char* data, uint64 len, analyzer::Tag tag,
|
||||||
Connection* conn, bool is_orig,
|
Connection* conn, bool is_orig,
|
||||||
|
|
|
@ -45,7 +45,7 @@ bool file_analysis::X509::EndOfFile()
|
||||||
::X509* ssl_cert = d2i_X509(NULL, &cert_char, cert_data.size());
|
::X509* ssl_cert = d2i_X509(NULL, &cert_char, cert_data.size());
|
||||||
if ( !ssl_cert )
|
if ( !ssl_cert )
|
||||||
{
|
{
|
||||||
reporter->Error("Could not parse X509 certificate");
|
reporter->Error("Could not parse X509 certificate. fuid %s", GetFile()->GetID().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ void file_analysis::X509::ParseBasicConstraints(X509_EXTENSION* ex)
|
||||||
BASIC_CONSTRAINTS *constr = (BASIC_CONSTRAINTS *) X509V3_EXT_d2i(ex);
|
BASIC_CONSTRAINTS *constr = (BASIC_CONSTRAINTS *) X509V3_EXT_d2i(ex);
|
||||||
if ( !constr )
|
if ( !constr )
|
||||||
{
|
{
|
||||||
reporter->Error("Certificate with invalid BasicConstraint");
|
reporter->Error("Certificate with invalid BasicConstraint. fuid %s", GetFile()->GetID().c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -246,41 +246,96 @@ void file_analysis::X509::ParseSAN(X509_EXTENSION* ext)
|
||||||
GENERAL_NAMES *altname = (GENERAL_NAMES*)X509V3_EXT_d2i(ext);
|
GENERAL_NAMES *altname = (GENERAL_NAMES*)X509V3_EXT_d2i(ext);
|
||||||
if ( !altname )
|
if ( !altname )
|
||||||
{
|
{
|
||||||
reporter->Error("could not parse subject alternative names");
|
reporter->Error("Could not parse subject alternative names. fuid %s", GetFile()->GetID().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorVal* names = new VectorVal(internal_type("string_vec")->AsVectorType());
|
VectorVal* names = 0;
|
||||||
|
VectorVal* emails = 0;
|
||||||
|
VectorVal* uris = 0;
|
||||||
|
VectorVal* ips = 0;
|
||||||
|
|
||||||
|
unsigned int otherfields = 0;
|
||||||
|
|
||||||
int j = 0;
|
|
||||||
for ( int i = 0; i < sk_GENERAL_NAME_num(altname); i++ )
|
for ( int i = 0; i < sk_GENERAL_NAME_num(altname); i++ )
|
||||||
{
|
{
|
||||||
GENERAL_NAME *gen = sk_GENERAL_NAME_value(altname, i);
|
GENERAL_NAME *gen = sk_GENERAL_NAME_value(altname, i);
|
||||||
assert(gen);
|
assert(gen);
|
||||||
|
|
||||||
if ( gen->type == GEN_DNS )
|
if ( gen->type == GEN_DNS || gen->type == GEN_URI || gen->type == GEN_EMAIL )
|
||||||
{
|
{
|
||||||
if (ASN1_STRING_type(gen->d.ia5) != V_ASN1_IA5STRING)
|
if (ASN1_STRING_type(gen->d.ia5) != V_ASN1_IA5STRING)
|
||||||
{
|
{
|
||||||
reporter->Error("DNS-field does not contain an IA5String");
|
reporter->Error("DNS-field does not contain an IA5String. fuid %s", GetFile()->GetID().c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const char* name = (const char*) ASN1_STRING_data(gen->d.ia5);
|
const char* name = (const char*) ASN1_STRING_data(gen->d.ia5);
|
||||||
StringVal* bs = new StringVal(name);
|
StringVal* bs = new StringVal(name);
|
||||||
names->Assign(j, bs);
|
|
||||||
j++;
|
switch ( gen->type )
|
||||||
|
{
|
||||||
|
case GEN_DNS:
|
||||||
|
if ( names == 0 )
|
||||||
|
names = new VectorVal(internal_type("string_vec")->AsVectorType());
|
||||||
|
names->Assign(names->Size(), bs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GEN_URI:
|
||||||
|
if ( uris == 0 )
|
||||||
|
uris = new VectorVal(internal_type("string_vec")->AsVectorType());
|
||||||
|
uris->Assign(uris->Size(), bs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GEN_EMAIL:
|
||||||
|
if ( emails == 0 )
|
||||||
|
emails = new VectorVal(internal_type("string_vec")->AsVectorType());
|
||||||
|
emails->Assign(emails->Size(), bs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( gen->type == GEN_IPADD )
|
||||||
|
{
|
||||||
|
if ( ips == 0 )
|
||||||
|
ips = new VectorVal(internal_type("addr_vec")->AsVectorType());
|
||||||
|
|
||||||
|
uint32* addr = (uint32*) gen->d.ip->data;
|
||||||
|
if(gen->d.ip->length == 4 )
|
||||||
|
{
|
||||||
|
ips->Assign(ips->Size(), new AddrVal(*addr));
|
||||||
|
}
|
||||||
|
else if ( gen->d.ip->length == 16 )
|
||||||
|
{
|
||||||
|
ips->Assign(ips->Size(), new AddrVal(addr));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we should perhaps sometime parse out ip-addresses
|
reporter->Error("Weird IP address length %d in subject alternative name. fuid %s", gen->d.ip->length, GetFile()->GetID().c_str());
|
||||||
reporter->Error("Subject alternative name contained non-dns fields");
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//reporter->Error("Subject alternative name contained unsupported fields. fuid %s", GetFile()->GetID().c_str());
|
||||||
|
// This happens quite often - just mark it
|
||||||
|
otherfields = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecordVal* sanExt = new RecordVal(BifType::Record::X509::SubjectAlternativeName);
|
||||||
|
if ( names != 0 )
|
||||||
|
sanExt->Assign(0, names);
|
||||||
|
if ( uris != 0 )
|
||||||
|
sanExt->Assign(1, uris);
|
||||||
|
if ( emails != 0 )
|
||||||
|
sanExt->Assign(2, emails);
|
||||||
|
if ( ips != 0 )
|
||||||
|
sanExt->Assign(3, ips);
|
||||||
|
sanExt->Assign(4, new Val(otherfields, TYPE_BOOL));
|
||||||
|
|
||||||
val_list* vl = new val_list();
|
val_list* vl = new val_list();
|
||||||
vl->append(GetFile()->GetVal()->Ref());
|
vl->append(GetFile()->GetVal()->Ref());
|
||||||
vl->append(names);
|
vl->append(sanExt);
|
||||||
|
|
||||||
mgr.QueueEvent(x509_ext_subject_alternative_name, vl);
|
mgr.QueueEvent(x509_ext_subject_alternative_name, vl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,57 @@
|
||||||
|
## Generated for encountered X509 certificates, e.g., in the clear SSL/TLS
|
||||||
|
## connection handshake.
|
||||||
|
##
|
||||||
|
## See `Wikipedia <http://en.wikipedia.org/wiki/X.509>`__ for more information
|
||||||
|
## about the X.509 format.
|
||||||
|
##
|
||||||
|
## f: The file.
|
||||||
|
##
|
||||||
|
## cert_ref: An opaque pointer to the underlying OpenSSL data structure of the
|
||||||
|
## certificate.
|
||||||
|
##
|
||||||
|
## cert: The parsed certificate information.
|
||||||
|
##
|
||||||
|
## .. bro:see:: x509_extension x509_ext_basic_constraints
|
||||||
|
## x509_ext_subject_alternative_name x509_parse x509_verify
|
||||||
|
## x509_get_certificate_string
|
||||||
event x509_certificate%(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate%);
|
event x509_certificate%(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate%);
|
||||||
|
|
||||||
|
## Generated for X509 extensions seen in a certificate.
|
||||||
|
##
|
||||||
|
## See `Wikipedia <http://en.wikipedia.org/wiki/X.509>`__ for more information
|
||||||
|
## about the X.509 format.
|
||||||
|
##
|
||||||
|
## f: The file.
|
||||||
|
##
|
||||||
|
## ext: The parsed extension.
|
||||||
|
##
|
||||||
|
## .. bro:see:: x509_certificate x509_ext_basic_constraints
|
||||||
|
## x509_ext_subject_alternative_name x509_parse x509_verify
|
||||||
|
## x509_get_certificate_string
|
||||||
event x509_extension%(f: fa_file, ext: X509::Extension%);
|
event x509_extension%(f: fa_file, ext: X509::Extension%);
|
||||||
|
|
||||||
|
## Generated for the X509 basic constraints extension seen in a certificate.
|
||||||
|
## This extension can be used to identify the subject of a certificate as a CA.
|
||||||
|
##
|
||||||
|
## f: The file.
|
||||||
|
##
|
||||||
|
## ext: The parsed basic constraints extension.
|
||||||
|
##
|
||||||
|
## .. bro:see:: x509_certificate x509_extension
|
||||||
|
## x509_ext_subject_alternative_name x509_parse x509_verify
|
||||||
|
## x509_get_certificate_string
|
||||||
event x509_ext_basic_constraints%(f: fa_file, ext: X509::BasicConstraints%);
|
event x509_ext_basic_constraints%(f: fa_file, ext: X509::BasicConstraints%);
|
||||||
event x509_ext_subject_alternative_name%(f: fa_file, names: string_vec%);
|
|
||||||
|
## Generated for the X509 subject alternative name extension seen in a certificate.
|
||||||
|
## This extension can be used to allow additional entities to be bound to the subject
|
||||||
|
## of the certificate. Usually it is used to specify one or multiple DNS names for
|
||||||
|
## which a certificate is valid.
|
||||||
|
##
|
||||||
|
## f: The file.
|
||||||
|
##
|
||||||
|
## ext: The parsed subject alternative name extension.
|
||||||
|
##
|
||||||
|
## .. bro:see:: x509_certificate x509_extension x509_ext_basic_constraints
|
||||||
|
## x509_parse x509_verify
|
||||||
|
## x509_get_certificate_string
|
||||||
|
event x509_ext_subject_alternative_name%(f: fa_file, ext: X509::SubjectAlternativeName%);
|
||||||
|
|
|
@ -42,7 +42,9 @@ RecordVal* x509_error_record(uint64_t num, const char* reason)
|
||||||
##
|
##
|
||||||
## Returns: A X509::Certificate structure
|
## Returns: A X509::Certificate structure
|
||||||
##
|
##
|
||||||
## .. bro:see:: x509_verify
|
## .. bro:see:: x509_certificate x509_extension x509_ext_basic_constraints
|
||||||
|
## x509_ext_subject_alternative_name x509_verify
|
||||||
|
## x509_get_certificate_string
|
||||||
function x509_parse%(cert: opaque of x509%): X509::Certificate
|
function x509_parse%(cert: opaque of x509%): X509::Certificate
|
||||||
%{
|
%{
|
||||||
assert(cert);
|
assert(cert);
|
||||||
|
@ -60,7 +62,9 @@ function x509_parse%(cert: opaque of x509%): X509::Certificate
|
||||||
## (false).
|
## (false).
|
||||||
##
|
##
|
||||||
## Returns: X509 certificate as a string
|
## Returns: X509 certificate as a string
|
||||||
|
##
|
||||||
|
## .. bro:see:: x509_certificate x509_extension x509_ext_basic_constraints
|
||||||
|
## x509_ext_subject_alternative_name x509_parse x509_verify
|
||||||
function x509_get_certificate_string%(cert: opaque of x509, pem: bool &default=F%): string
|
function x509_get_certificate_string%(cert: opaque of x509, pem: bool &default=F%): string
|
||||||
%{
|
%{
|
||||||
assert(cert);
|
assert(cert);
|
||||||
|
@ -101,7 +105,9 @@ function x509_get_certificate_string%(cert: opaque of x509, pem: bool &default=F
|
||||||
## Returns: A record of type X509::Result containing the result code of the verify
|
## Returns: A record of type X509::Result containing the result code of the verify
|
||||||
## operation. In case of success also returns the full certificate chain.
|
## operation. In case of success also returns the full certificate chain.
|
||||||
##
|
##
|
||||||
## .. bro:see:: x509_parse
|
## .. bro:see:: x509_certificate x509_extension x509_ext_basic_constraints
|
||||||
|
## x509_ext_subject_alternative_name x509_parse
|
||||||
|
## x509_get_certificate_string
|
||||||
function x509_verify%(certs: x509_opaque_vector, root_certs: table_string_of_string%): X509::Result
|
function x509_verify%(certs: x509_opaque_vector, root_certs: table_string_of_string%): X509::Result
|
||||||
%{
|
%{
|
||||||
X509_STORE* ctx = 0;
|
X509_STORE* ctx = 0;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
type X509::Certificate: record;
|
type X509::Certificate: record;
|
||||||
type X509::Extension: record;
|
type X509::Extension: record;
|
||||||
type X509::BasicConstraints: record;
|
type X509::BasicConstraints: record;
|
||||||
|
type X509::SubjectAlternativeName: record;
|
||||||
type X509::Result: record;
|
type X509::Result: record;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue