mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
SSL/TLS: Parse CertificateRequest message
This commit introduces parsing of the CertificateRequest message in the TLS handshake. It introduces a new event ssl_certificate_request, as well as a new function parse_distinguished_name, which can be used to parse part of the ssl_certificate_request event parameters. This commit also introduces a new policy script, which appends information about the CAs a TLS server requests in the CertificateRequest message, if it sends it.
This commit is contained in:
parent
b73dda5cff
commit
b56b856da9
17 changed files with 221 additions and 4 deletions
|
@ -657,7 +657,7 @@ event ssl_stapled_ocsp%(c: connection, is_client: bool, response: string%);
|
|||
##
|
||||
## .. zeek:see:: ssl_alert ssl_established ssl_extension ssl_server_hello
|
||||
## ssl_session_ticket_handshake x509_certificate ssl_client_hello
|
||||
## ssl_change_cipher_spec ssl_connection_flipped
|
||||
## ssl_change_cipher_spec ssl_connection_flipped ssl_certificate_request
|
||||
event ssl_handshake_message%(c: connection, is_client: bool, msg_type: count, length: count%);
|
||||
|
||||
## This event is raised when a SSL/TLS ChangeCipherSpec message is encountered
|
||||
|
@ -687,3 +687,26 @@ event ssl_change_cipher_spec%(c: connection, is_client: bool%);
|
|||
## ssl_session_ticket_handshake x509_certificate ssl_client_hello
|
||||
## ssl_handshake_message
|
||||
event ssl_connection_flipped%(c: connection%);
|
||||
|
||||
## This event is raised, when a Certificate Request handshake message is encountered. This
|
||||
## Message can be used by a TLS server to request a client certificate.
|
||||
##
|
||||
## c: The connection.
|
||||
##
|
||||
## is_client: True if event is raised for the client side of the connection
|
||||
## (the side that sends the client hello). This is typically equivalent
|
||||
## with the originator, but does not have to be in all circumstances.
|
||||
##
|
||||
## certificate_types: List of the types of certificates that the client may offer.
|
||||
##
|
||||
## supported_signature_algorithms: List of hash/sighature algorithm pairs that the server
|
||||
## supports, listed in descending order of preferences.
|
||||
##
|
||||
## certificate_authorities: List of distinguished names of certificate authorities that are
|
||||
## acceptable to the server. The individual entries are DER encoded.
|
||||
## :zeek:id:`parse_distinguished_name` can be used to decode the strings.
|
||||
##
|
||||
## .. zeek:see:: ssl_handshake_message x509_certificate ssl_server_hello ssl_client_hello
|
||||
## parse_distinguished_name
|
||||
event ssl_certificate_request%(c: connection, is_client: bool, certificate_types: index_vec, supported_signature_algorithms: SSL::SignatureAndHashAlgorithm, certificate_authorities: string_vec%);
|
||||
|
||||
|
|
|
@ -65,3 +65,35 @@ function set_keys%(c: connection, keys: string%): bool
|
|||
|
||||
return zeek::val_mgr->False();
|
||||
%}
|
||||
|
||||
## Decodes a DER-encoded distinguished name into an ASCII string,
|
||||
## using the RFC2253 representation
|
||||
##
|
||||
## dn: DER encoded distinguished name
|
||||
##
|
||||
## Returns: Ascii representation on success, empty string on failure
|
||||
##
|
||||
## .. zeek:see:: ssl_certificate_request
|
||||
function parse_distinguished_name%(dn: string%): string
|
||||
%{
|
||||
std::string out = "";
|
||||
const unsigned char* in = dn->Bytes();
|
||||
|
||||
X509_NAME* dn_x509 = d2i_X509_NAME(nullptr, &in, dn->Len());
|
||||
if ( ! dn_x509 )
|
||||
{
|
||||
// we were not able to parse. Let's return an empty string.
|
||||
return zeek::make_intrusive<zeek::StringVal>("");
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
|
||||
X509_NAME_print_ex(bio, dn_x509, 0, XN_FLAG_RFC2253);
|
||||
int len = BIO_gets(bio, buf, sizeof(buf));
|
||||
out.assign(buf, len);
|
||||
BIO_free(bio);
|
||||
X509_NAME_free(dn_x509);
|
||||
return zeek::make_intrusive<zeek::StringVal>(out);
|
||||
%}
|
||||
|
|
|
@ -626,6 +626,47 @@ refine connection Handshake_Conn += {
|
|||
return true;
|
||||
%}
|
||||
|
||||
function proc_certificate_request(rec: HandshakeRecord, req: CertificateRequest) : bool
|
||||
%{
|
||||
if ( ! ssl_certificate_request )
|
||||
return true;
|
||||
|
||||
auto ctlist = zeek::make_intrusive<zeek::VectorVal>(zeek::id::find_type<zeek::VectorType>("index_vec"));
|
||||
auto ctypes = ${req.certificate_types};
|
||||
|
||||
if ( ctypes )
|
||||
for ( unsigned int i = 0; i < ctypes->size(); ++i)
|
||||
ctlist->Assign(i, zeek::val_mgr->Count((*ctypes)[i]));
|
||||
|
||||
auto slist = zeek::make_intrusive<zeek::VectorVal>(zeek::id::find_type<zeek::VectorType>("signature_and_hashalgorithm_vec"));
|
||||
if ( ${req.uses_signature_and_hashalgorithm} )
|
||||
{
|
||||
auto sigalgs = ${req.supported_signature_algorithms.supported_signature_algorithms};
|
||||
|
||||
if ( sigalgs )
|
||||
{
|
||||
for ( unsigned int i = 0; i < sigalgs->size(); ++i )
|
||||
{
|
||||
auto el = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SSL::SignatureAndHashAlgorithm);
|
||||
el->Assign(0, (*sigalgs)[i]->HashAlgorithm());
|
||||
el->Assign(1, (*sigalgs)[i]->SignatureAlgorithm());
|
||||
slist->Assign(i, std::move(el));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto calist = zeek::make_intrusive<zeek::VectorVal>(zeek::id::find_type<zeek::VectorType>("string_vec"));
|
||||
auto certificate_authorities = ${req.certificate_authorities.certificate_authorities};
|
||||
if ( certificate_authorities )
|
||||
for ( unsigned int i = 0; i < certificate_authorities->size(); ++i )
|
||||
calist->Assign(i, zeek::make_intrusive<zeek::StringVal>((*certificate_authorities)[i]->certificate_authority().length(), (const char*) (*certificate_authorities)[i]->certificate_authority().data()));
|
||||
|
||||
zeek::BifEvent::enqueue_ssl_certificate_request(zeek_analyzer(), zeek_analyzer()->Conn(), ${rec.is_orig} ^ flipped_, ctlist, slist, calist);
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
};
|
||||
|
||||
refine typeattr ClientHello += &let {
|
||||
|
@ -754,3 +795,7 @@ refine typeattr Handshake += &let {
|
|||
refine typeattr SignedCertificateTimestamp += &let {
|
||||
proc : bool = $context.connection.proc_signedcertificatetimestamp(rec, version, logid, timestamp, digitally_signed_algorithms, digitally_signed_signature);
|
||||
};
|
||||
|
||||
refine typeattr CertificateRequest += &let {
|
||||
proc: bool = $context.connection.proc_certificate_request(rec, this);
|
||||
};
|
||||
|
|
|
@ -439,9 +439,30 @@ type DhAnonServerKeyExchange(rec: HandshakeRecord) = record {
|
|||
# V3 Certificate Request (7.4.4.)
|
||||
######################################################################
|
||||
|
||||
type CertificateAuthorities = record {
|
||||
certificate_authority_len: uint16;
|
||||
certificate_authority: bytestring &length=certificate_authority_len;
|
||||
};
|
||||
|
||||
type CertificateAuthoritiesContainer = record {
|
||||
certificate_authorities: CertificateAuthorities[] &until($input.length() == 0);
|
||||
};
|
||||
|
||||
# For now, ignore Certificate Request Details; just eat up message.
|
||||
type CertificateRequest(rec: HandshakeRecord) = record {
|
||||
certificate_types_len: uint8;
|
||||
certificate_types: uint8[certificate_types_len];
|
||||
alg: case uses_signature_and_hashalgorithm of {
|
||||
true -> supported_signature_algorithms: SignatureAlgorithm(rec);
|
||||
false -> nothing: bytestring &length=0;
|
||||
} &requires(uses_signature_and_hashalgorithm);
|
||||
certificate_authorities_len: uint16;
|
||||
certificate_authorities: CertificateAuthoritiesContainer &length=certificate_authorities_len;
|
||||
cont : bytestring &restofdata &transient;
|
||||
} &let {
|
||||
uses_signature_and_hashalgorithm : bool =
|
||||
($context.connection.chosen_version() > TLSv11) &&
|
||||
($context.connection.chosen_version() != DTLSv10);
|
||||
};
|
||||
|
||||
|
||||
|
@ -931,7 +952,7 @@ type PreSharedKey(rec: HandshakeRecord) = case rec.msg_type of {
|
|||
type SignatureAlgorithm(rec: HandshakeRecord) = record {
|
||||
length: uint16;
|
||||
supported_signature_algorithms: SignatureAndHashAlgorithm[] &until($input.length() == 0);
|
||||
}
|
||||
} &length=length+2;
|
||||
|
||||
type EllipticCurves(rec: HandshakeRecord) = record {
|
||||
length: uint16;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue