eve/tls: implement client cert logging

Enable client logging in extended mode.

Add "client", "client_certificate" and "client_chain", where the latter two
depend on "client".
pull/7896/head
Victor Julien 3 years ago
parent e817a8f968
commit 4a283d480d

@ -73,28 +73,24 @@ SC_ATOMIC_EXTERN(unsigned int, cert_id);
#define LOG_TLS_FIELD_SESSION_RESUMED (1 << 10)
#define LOG_TLS_FIELD_JA3 (1 << 11)
#define LOG_TLS_FIELD_JA3S (1 << 12)
#define LOG_TLS_FIELD_CLIENT (1 << 13) /**< client fields (issuer, subject, etc) */
#define LOG_TLS_FIELD_CLIENT_CERT (1 << 14)
#define LOG_TLS_FIELD_CLIENT_CHAIN (1 << 15)
typedef struct {
const char *name;
uint64_t flag;
} TlsFields;
TlsFields tls_fields[] = {
{ "version", LOG_TLS_FIELD_VERSION },
{ "subject", LOG_TLS_FIELD_SUBJECT },
{ "issuer", LOG_TLS_FIELD_ISSUER },
{ "serial", LOG_TLS_FIELD_SERIAL },
{ "fingerprint", LOG_TLS_FIELD_FINGERPRINT },
{ "not_before", LOG_TLS_FIELD_NOTBEFORE },
{ "not_after", LOG_TLS_FIELD_NOTAFTER },
{ "sni", LOG_TLS_FIELD_SNI },
{ "certificate", LOG_TLS_FIELD_CERTIFICATE },
{ "chain", LOG_TLS_FIELD_CHAIN },
{ "session_resumed", LOG_TLS_FIELD_SESSION_RESUMED },
{ "ja3", LOG_TLS_FIELD_JA3 },
{ "ja3s", LOG_TLS_FIELD_JA3S },
{ NULL, -1 }
};
TlsFields tls_fields[] = { { "version", LOG_TLS_FIELD_VERSION },
{ "subject", LOG_TLS_FIELD_SUBJECT }, { "issuer", LOG_TLS_FIELD_ISSUER },
{ "serial", LOG_TLS_FIELD_SERIAL }, { "fingerprint", LOG_TLS_FIELD_FINGERPRINT },
{ "not_before", LOG_TLS_FIELD_NOTBEFORE }, { "not_after", LOG_TLS_FIELD_NOTAFTER },
{ "sni", LOG_TLS_FIELD_SNI }, { "certificate", LOG_TLS_FIELD_CERTIFICATE },
{ "chain", LOG_TLS_FIELD_CHAIN }, { "session_resumed", LOG_TLS_FIELD_SESSION_RESUMED },
{ "ja3", LOG_TLS_FIELD_JA3 }, { "ja3s", LOG_TLS_FIELD_JA3S },
{ "client", LOG_TLS_FIELD_CLIENT }, { "client_certificate", LOG_TLS_FIELD_CLIENT_CERT },
{ "client_chain", LOG_TLS_FIELD_CLIENT_CHAIN }, { NULL, -1 } };
typedef struct OutputTlsCtx_ {
uint32_t flags; /** Store mode */
@ -285,6 +281,53 @@ static void JsonTlsLogChain(JsonBuilder *js, SSLStateConnp *connp)
jb_close(js);
}
static bool HasClientCert(SSLStateConnp *connp)
{
if (connp->cert0_subject || connp->cert0_issuerdn)
return true;
return false;
}
static void JsonTlsLogClientCert(
JsonBuilder *js, SSLStateConnp *connp, const bool log_cert, const bool log_chain)
{
if (connp->cert0_subject != NULL) {
jb_set_string(js, "subject", connp->cert0_subject);
}
if (connp->cert0_issuerdn != NULL) {
jb_set_string(js, "issuerdn", connp->cert0_issuerdn);
}
if (connp->cert0_fingerprint) {
jb_set_string(js, "fingerprint", connp->cert0_fingerprint);
}
if (connp->cert0_serial) {
jb_set_string(js, "serial", connp->cert0_serial);
}
if (connp->cert0_not_before != 0) {
char timebuf[64];
struct timeval tv;
tv.tv_sec = connp->cert0_not_before;
tv.tv_usec = 0;
CreateUtcIsoTimeString(&tv, timebuf, sizeof(timebuf));
jb_set_string(js, "notbefore", timebuf);
}
if (connp->cert0_not_after != 0) {
char timebuf[64];
struct timeval tv;
tv.tv_sec = connp->cert0_not_after;
tv.tv_usec = 0;
CreateUtcIsoTimeString(&tv, timebuf, sizeof(timebuf));
jb_set_string(js, "notafter", timebuf);
}
if (log_cert) {
JsonTlsLogCertificate(js, connp);
}
if (log_chain) {
JsonTlsLogChain(js, connp);
}
}
void JsonTlsLogJSONBasic(JsonBuilder *js, SSLState *ssl_state)
{
/* tls subject */
@ -351,6 +394,16 @@ static void JsonTlsLogJSONCustom(OutputTlsCtx *tls_ctx, JsonBuilder *js,
/* tls ja3s */
if (tls_ctx->fields & LOG_TLS_FIELD_JA3S)
JsonTlsLogJa3S(js, ssl_state);
if (tls_ctx->fields & LOG_TLS_FIELD_CLIENT) {
const bool log_cert = (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CERT) != 0;
const bool log_chain = (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CHAIN) != 0;
if (HasClientCert(&ssl_state->client_connp)) {
jb_open_object(js, "client");
JsonTlsLogClientCert(js, &ssl_state->client_connp, log_cert, log_chain);
jb_close(js);
}
}
}
void JsonTlsLogJSONExtended(JsonBuilder *tjs, SSLState * state)
@ -380,6 +433,12 @@ void JsonTlsLogJSONExtended(JsonBuilder *tjs, SSLState * state)
/* tls ja3s */
JsonTlsLogJa3S(tjs, state);
if (HasClientCert(&state->client_connp)) {
jb_open_object(tjs, "client");
JsonTlsLogClientCert(tjs, &state->client_connp, false, false);
jb_close(tjs);
}
}
static int JsonTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p,
@ -540,6 +599,24 @@ static OutputTlsCtx *OutputTlsInitCtx(ConfNode *conf)
"certificate, so only one of them should be enabled "
"at a time");
}
if ((tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CERT) &&
(tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CHAIN)) {
SCLogWarning(SC_WARN_DUPLICATE_OUTPUT,
"Both 'client_certificate' and 'client_chain' contains the top "
"certificate, so only one of them should be enabled "
"at a time");
}
if ((tls_ctx->fields & LOG_TLS_FIELD_CLIENT) == 0) {
if (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CERT) {
SCLogConfig("enabling \"client\" as a dependency of \"client_certificate\"");
tls_ctx->fields |= LOG_TLS_FIELD_CLIENT;
}
if (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CHAIN) {
SCLogConfig("enabling \"client\" as a dependency of \"client_chain\"");
tls_ctx->fields |= LOG_TLS_FIELD_CLIENT;
}
}
return tls_ctx;
}

Loading…
Cancel
Save