Merge remote-tracking branch 'origin/topic/johanna/certificate-req'

* origin/topic/johanna/certificate-req:
  SSL/TLS CertificateRequest message: Address review feedback
  SSL/TLS: Parse CertificateRequest message
This commit is contained in:
Johanna Amann 2023-03-15 10:02:52 +01:00
commit dcbc809189
19 changed files with 237 additions and 5 deletions

View file

@ -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%);

View file

@ -65,3 +65,34 @@ 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
%{
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));
auto out = zeek::make_intrusive<zeek::StringVal>(len, buf);
BIO_free(bio);
X509_NAME_free(dn_x509);
return out;
%}

View file

@ -626,6 +626,50 @@ 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::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::string_vec);
auto certificate_authorities = ${req.certificate_authorities.certificate_authorities};
if ( certificate_authorities )
for ( unsigned int i = 0; i < certificate_authorities->size(); ++i )
{
auto ca = (*certificate_authorities)[i]->certificate_authority();
calist->Assign(i, zeek::make_intrusive<zeek::StringVal>(ca.length(), (const char*) ca.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 +798,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);
};

View file

@ -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;