From: Victor Julien Date: Sat, 25 May 2024 15:35:26 +0000 (+0200) Subject: tls-store: support client logging X-Git-Tag: suricata-8.0.0-beta1~1244 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=121955d5c173cd96b4e5e45cad8d6447854d6d74;p=thirdparty%2Fsuricata.git tls-store: support client logging Adds a `client-` prefix to the logged certs and meta files. Ticket: #7045. --- diff --git a/src/log-tlsstore.c b/src/log-tlsstore.c index a11f20d2b9..e6c89559ed 100644 --- a/src/log-tlsstore.c +++ b/src/log-tlsstore.c @@ -56,15 +56,18 @@ typedef struct LogTlsStoreLogThread_ { size_t enc_buf_len; } LogTlsStoreLogThread; -static int CreateFileName(const Packet *p, SSLState *state, char *filename, size_t filename_size) +static int CreateFileName( + const Packet *p, SSLState *state, char *filename, size_t filename_size, const bool client) { char path[PATH_MAX]; int file_id = SC_ATOMIC_ADD(cert_id, 1); + const char *dir = client ? "client-" : ""; + /* Use format : packet time + incremental ID * When running on same pcap it will overwrite * On a live device, we will not be able to overwrite */ - if (snprintf(path, sizeof(path), "%s/%ld.%ld-%d.pem", tls_logfile_base_dir, + if (snprintf(path, sizeof(path), "%s/%s%ld.%ld-%d.pem", tls_logfile_base_dir, dir, (long int)SCTIME_SECS(p->ts), (long int)SCTIME_USECS(p->ts), file_id) == sizeof(path)) return 0; @@ -73,7 +76,8 @@ static int CreateFileName(const Packet *p, SSLState *state, char *filename, size return 1; } -static void LogTlsLogPem(LogTlsStoreLogThread *aft, const Packet *p, SSLState *state, int ipproto) +static void LogTlsLogPem(LogTlsStoreLogThread *aft, const Packet *p, SSLState *state, + SSLStateConnp *connp, int ipproto) { #define PEMHEADER "-----BEGIN CERTIFICATE-----\n" #define PEMFOOTER "-----END CERTIFICATE-----\n" @@ -87,10 +91,12 @@ static void LogTlsLogPem(LogTlsStoreLogThread *aft, const Packet *p, SSLState *s uint8_t *ptmp; SSLCertsChain *cert; - if (TAILQ_EMPTY(&state->server_connp.certs)) + if (TAILQ_EMPTY(&connp->certs)) { SCReturn; + } - CreateFileName(p, state, filename, sizeof(filename)); + const bool client = connp == &state->client_connp; + CreateFileName(p, state, filename, sizeof(filename), client); if (strlen(filename) == 0) { SCLogWarning("Can't create PEM filename"); SCReturn; @@ -106,7 +112,7 @@ static void LogTlsLogPem(LogTlsStoreLogThread *aft, const Packet *p, SSLState *s SCReturn; } - TAILQ_FOREACH(cert, &state->server_connp.certs, next) { + TAILQ_FOREACH (cert, &connp->certs, next) { pemlen = Base64EncodeBufferSize(cert->cert_len); if (pemlen > aft->enc_buf_len) { ptmp = (uint8_t*) SCRealloc(aft->enc_buf, sizeof(uint8_t) * pemlen); @@ -180,12 +186,11 @@ static void LogTlsLogPem(LogTlsStoreLogThread *aft, const Packet *p, SSLState *s goto end_fwrite_fpmeta; } - if (fprintf(fpmeta, "TLS SUBJECT: %s\n" + if (fprintf(fpmeta, + "TLS SUBJECT: %s\n" "TLS ISSUERDN: %s\n" "TLS FINGERPRINT: %s\n", - state->server_connp.cert0_subject, - state->server_connp.cert0_issuerdn, - state->server_connp.cert0_fingerprint) < 0) + connp->cert0_subject, connp->cert0_issuerdn, connp->cert0_fingerprint) < 0) goto end_fwrite_fpmeta; fclose(fpmeta); @@ -199,7 +204,7 @@ static void LogTlsLogPem(LogTlsStoreLogThread *aft, const Packet *p, SSLState *s } /* Reset the store flag */ - state->server_connp.cert_log_flag &= ~SSL_TLS_LOG_PEM; + connp->cert_log_flag &= ~SSL_TLS_LOG_PEM; SCReturn; end_fwrite_fp: @@ -243,20 +248,53 @@ static bool LogTlsStoreCondition( goto dontlog; } - if ((ssl_state->server_connp.cert_log_flag & SSL_TLS_LOG_PEM) == 0) + if ((ssl_state->server_connp.cert_log_flag & SSL_TLS_LOG_PEM) == 0) { goto dontlog; + } if (ssl_state->server_connp.cert0_issuerdn == NULL || - ssl_state->server_connp.cert0_subject == NULL) + ssl_state->server_connp.cert0_subject == NULL) { + goto dontlog; + } + + return true; +dontlog: + return false; +} + +static bool LogTlsStoreConditionClient( + ThreadVars *tv, const Packet *p, void *state, void *tx, uint64_t tx_id) +{ + if (p->flow == NULL) { + return false; + } + + if (!(PacketIsTCP(p))) { + return false; + } + + SSLState *ssl_state = (SSLState *)state; + if (ssl_state == NULL) { + SCLogDebug("no tls state, so no request logging"); + goto dontlog; + } + + if ((ssl_state->client_connp.cert_log_flag & SSL_TLS_LOG_PEM) == 0) { goto dontlog; + } + + if ((ssl_state->client_connp.cert0_issuerdn == NULL || + ssl_state->client_connp.cert0_subject == NULL)) { + goto dontlog; + } return true; dontlog: return false; } -static int LogTlsStoreLogger(ThreadVars *tv, void *thread_data, const Packet *p, - Flow *f, void *state, void *tx, uint64_t tx_id) +static int LogTlsStoreLoggerClient(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, + void *state, void *tx, uint64_t tx_id) { LogTlsStoreLogThread *aft = (LogTlsStoreLogThread *)thread_data; int ipproto = (PacketIsIPv4(p)) ? AF_INET : AF_INET6; @@ -265,9 +303,29 @@ static int LogTlsStoreLogger(ThreadVars *tv, void *thread_data, const Packet *p, if (unlikely(ssl_state == NULL)) { return 0; } + /* client cert */ + SSLStateConnp *connp = &ssl_state->client_connp; + if (connp->cert_log_flag & SSL_TLS_LOG_PEM) { + LogTlsLogPem(aft, p, ssl_state, connp, ipproto); + } + + return 0; +} + +static int LogTlsStoreLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, + void *state, void *tx, uint64_t tx_id) +{ + LogTlsStoreLogThread *aft = (LogTlsStoreLogThread *)thread_data; + int ipproto = (PacketIsIPv4(p)) ? AF_INET : AF_INET6; - if (ssl_state->server_connp.cert_log_flag & SSL_TLS_LOG_PEM) { - LogTlsLogPem(aft, p, ssl_state, ipproto); + SSLState *ssl_state = (SSLState *)state; + if (unlikely(ssl_state == NULL)) { + return 0; + } + /* server cert */ + SSLStateConnp *connp = &ssl_state->server_connp; + if (connp->cert_log_flag & SSL_TLS_LOG_PEM) { + LogTlsLogPem(aft, p, ssl_state, connp, ipproto); } return 0; @@ -394,6 +452,10 @@ void LogTlsStoreRegister (void) LogTlsStoreCondition, LogTlsStoreLogThreadInit, LogTlsStoreLogThreadDeinit, LogTlsStoreLogExitPrintStats); + OutputRegisterTxModuleWithCondition(LOGGER_TLS_STORE_CLIENT, MODULE_NAME, "tls-store", + LogTlsStoreLogInitCtx, ALPROTO_TLS, LogTlsStoreLoggerClient, LogTlsStoreConditionClient, + LogTlsStoreLogThreadInit, LogTlsStoreLogThreadDeinit, LogTlsStoreLogExitPrintStats); + SC_ATOMIC_INIT(cert_id); SC_ATOMIC_SET(cert_id, 1); diff --git a/src/suricata-common.h b/src/suricata-common.h index 1f3c6341e5..cb95d17e97 100644 --- a/src/suricata-common.h +++ b/src/suricata-common.h @@ -463,6 +463,7 @@ typedef enum { /* TX loggers first for low logger IDs */ LOGGER_HTTP, LOGGER_TLS_STORE, + LOGGER_TLS_STORE_CLIENT, LOGGER_TLS, LOGGER_JSON_TX, LOGGER_FILE, diff --git a/src/util-profiling.c b/src/util-profiling.c index 46c587d011..70b187e97a 100644 --- a/src/util-profiling.c +++ b/src/util-profiling.c @@ -1266,6 +1266,7 @@ const char *PacketProfileLoggerIdToString(LoggerId id) CASE_CODE(LOGGER_UNDEFINED); CASE_CODE(LOGGER_HTTP); CASE_CODE(LOGGER_TLS_STORE); + CASE_CODE(LOGGER_TLS_STORE_CLIENT); CASE_CODE(LOGGER_TLS); CASE_CODE(LOGGER_JSON_TX); CASE_CODE(LOGGER_FILE);