output/tls: Allow logging of sv-handshake params

Ticket: 6695

"server_handshake" which logs the following:
1. TLS version used during handshake
2. The chosen cipher suite, excluding GREASE
3. TLS extensions, excluding GREASE
pull/13251/head
Richard McConnell 7 months ago committed by Victor Julien
parent 94c8be22d4
commit d81b76d852

@ -1056,6 +1056,8 @@ In addition to this, custom logging also allows the following fields:
* "client_handshake": structure containing "version", "ciphers" ([u16]), "exts" ([u16]), "sig_algs" ([u16]),
for client hello supported cipher suites, extensions, and signature algorithms,
respectively, in the order that they're mentioned (ie. unsorted)
* "server_handshake": structure containing "version", "chosen cipher", "exts" ([u16]), for server hello
in the order that they're mentioned (ie. unsorted)
Examples
~~~~~~~~

@ -7102,6 +7102,27 @@
}
}
},
"server_handshake": {
"type": "object",
"properties": {
"version": {
"description": "TLS version in server hello",
"type": "string"
},
"cipher": {
"description": "TLS server's chosen cipher",
"type": "integer"
},
"exts": {
"description": "TLS server extension(s)",
"type": "array",
"minItems": 1,
"items": {
"type": "integer"
}
}
}
},
"server_alpns": {
"description": "TLS server ALPN field(s)",
"type": "array",

@ -146,6 +146,12 @@ impl HandshakeParams {
Ok(())
}
fn log_first_cipher(&self, js: &mut JsonBuilder) -> Result<(), JsonError> {
let chosen = self.ciphersuites.first().map(|&v| *v).unwrap_or(0);
js.set_uint("cipher", chosen)?;
Ok(())
}
fn log_ciphers(&self, js: &mut JsonBuilder) -> Result<(), JsonError> {
if self.ciphersuites.is_empty() {
return Ok(());
@ -242,6 +248,14 @@ pub unsafe extern "C" fn SCTLSHandshakeLogCiphers(hs: &HandshakeParams, js: *mut
return hs.log_ciphers(js.as_mut().unwrap()).is_ok()
}
#[no_mangle]
pub unsafe extern "C" fn SCTLSHandshakeLogFirstCipher(hs: &HandshakeParams, js: *mut JsonBuilder) -> bool {
if js.is_null() {
return false;
}
return hs.log_first_cipher(js.as_mut().unwrap()).is_ok()
}
#[no_mangle]
pub unsafe extern "C" fn SCTLSHandshakeLogExtensions(hs: &HandshakeParams, js: *mut JsonBuilder) -> bool {
if js.is_null() {

@ -664,7 +664,8 @@ static inline int TLSDecodeHSHelloVersion(SSLState *ssl_state,
uint16_t version = (uint16_t)(*input << 8) | *(input + 1);
ssl_state->curr_connp->version = version;
if (ssl_state->current_flags & SSL_AL_FLAG_STATE_CLIENT_HELLO) {
if (ssl_state->current_flags &
(SSL_AL_FLAG_STATE_CLIENT_HELLO | SSL_AL_FLAG_STATE_SERVER_HELLO)) {
SCTLSHandshakeSetTLSVersion(ssl_state->curr_connp->hs, version);
}
@ -836,7 +837,8 @@ static inline int TLSDecodeHSHelloCipherSuites(SSLState *ssl_state,
input += 2;
if (TLSDecodeValueIsGREASE(cipher_suite) != 1) {
if (ssl_state->current_flags & SSL_AL_FLAG_STATE_CLIENT_HELLO) {
if (ssl_state->current_flags &
(SSL_AL_FLAG_STATE_CLIENT_HELLO | SSL_AL_FLAG_STATE_SERVER_HELLO)) {
SCTLSHandshakeAddCipher(ssl_state->curr_connp->hs, cipher_suite);
}
if (enable_ja3) {
@ -1428,7 +1430,8 @@ static inline int TLSDecodeHSHelloExtensions(SSLState *ssl_state,
}
}
if (ssl_state->current_flags & SSL_AL_FLAG_STATE_CLIENT_HELLO) {
if (ssl_state->current_flags &
(SSL_AL_FLAG_STATE_CLIENT_HELLO | SSL_AL_FLAG_STATE_SERVER_HELLO)) {
if (TLSDecodeValueIsGREASE(ext_type) != 1) {
SCTLSHandshakeAddExtension(ssl_state->curr_connp->hs, ext_type);
}

@ -58,6 +58,7 @@
#define LOG_TLS_FIELD_CLIENT_ALPNS BIT_U64(18)
#define LOG_TLS_FIELD_SERVER_ALPNS BIT_U64(19)
#define LOG_TLS_FIELD_CLIENT_HANDSHAKE BIT_U64(20)
#define LOG_TLS_FIELD_SERVER_HANDSHAKE BIT_U64(21)
typedef struct {
const char *name;
@ -87,6 +88,7 @@ TlsFields tls_fields[] = {
{ "client_alpns", LOG_TLS_FIELD_CLIENT_ALPNS },
{ "server_alpns", LOG_TLS_FIELD_SERVER_ALPNS },
{ "client_handshake", LOG_TLS_FIELD_CLIENT_HANDSHAKE },
{ "server_handshake", LOG_TLS_FIELD_SERVER_HANDSHAKE },
{ NULL, -1 },
// clang-format on
};
@ -383,6 +385,25 @@ static void JsonTlsLogClientHandshake(SCJsonBuilder *js, SSLState *ssl_state)
SCJbClose(js);
}
static void JsonTlsLogServerHandshake(SCJsonBuilder *js, SSLState *ssl_state)
{
if (ssl_state->server_connp.hs == NULL) {
return;
}
if (SCTLSHandshakeIsEmpty(ssl_state->server_connp.hs)) {
return;
}
SCJbOpenObject(js, "server_handshake");
SCTLSHandshakeLogVersion(ssl_state->server_connp.hs, js);
SCTLSHandshakeLogFirstCipher(ssl_state->server_connp.hs, js);
SCTLSHandshakeLogExtensions(ssl_state->server_connp.hs, js);
SCJbClose(js);
}
static void JsonTlsLogFields(SCJsonBuilder *js, SSLState *ssl_state, uint64_t fields)
{
/* tls subject */
@ -458,6 +479,10 @@ static void JsonTlsLogFields(SCJsonBuilder *js, SSLState *ssl_state, uint64_t fi
if (fields & LOG_TLS_FIELD_CLIENT_HANDSHAKE)
JsonTlsLogClientHandshake(js, ssl_state);
/* tls server handshake parameters */
if (fields & LOG_TLS_FIELD_SERVER_HANDSHAKE)
JsonTlsLogServerHandshake(js, ssl_state);
if (fields & LOG_TLS_FIELD_CLIENT) {
const bool log_cert = (fields & LOG_TLS_FIELD_CLIENT_CERT) != 0;
const bool log_chain = (fields & LOG_TLS_FIELD_CLIENT_CHAIN) != 0;

@ -288,7 +288,7 @@ outputs:
#session-resumption: no
# custom controls which TLS fields that are included in eve-log
# WARNING: enabling custom disables extended logging.
#custom: [subject, issuer, session_resumed, serial, fingerprint, sni, version, not_before, not_after, certificate, chain, ja3, ja3s, ja4, subjectaltname, client, client_certificate, client_chain, client_alpns, server_alpns, client_handshake]
#custom: [subject, issuer, session_resumed, serial, fingerprint, sni, version, not_before, not_after, certificate, chain, ja3, ja3s, ja4, subjectaltname, client, client_certificate, client_chain, client_alpns, server_alpns, client_handshake, server_handshake]
- files:
force-magic: no # force logging magic on all logged files
# force logging of checksums, available hash functions are md5,

Loading…
Cancel
Save