From 504f39adefa97bf79d9aff9d2f8bb54c608ef33d Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Mon, 13 Jan 2014 16:13:27 +0100 Subject: [PATCH] log-tls: convert to packet logger API This patch converts log-tls to use the packet logger API. The packet logger API was choosen as the TLS parser is not transaction aware. To make sure the state is only logged once, the flag SSL_AL_FLAG_STATE_LOGGED was added to the parser. This flag is checked by the condition function, and set at the end of the Logger function. --- src/app-layer-ssl.h | 3 + src/log-tlslog.c | 232 ++++++++++++++++++++++---------------------- 2 files changed, 119 insertions(+), 116 deletions(-) diff --git a/src/app-layer-ssl.h b/src/app-layer-ssl.h index 55a85ae4d7..d138200d05 100644 --- a/src/app-layer-ssl.h +++ b/src/app-layer-ssl.h @@ -66,6 +66,9 @@ enum { #define SSL_AL_FLAG_STATE_SERVER_KEYX 0x1000 #define SSL_AL_FLAG_STATE_UNKNOWN 0x2000 +#define SSL_AL_FLAG_STATE_LOGGED 0x4000 + +/* config flags */ #define SSL_TLS_LOG_PEM (1 << 0) diff --git a/src/log-tlslog.c b/src/log-tlslog.c index 67fd96a377..fa90a14a9c 100644 --- a/src/log-tlslog.c +++ b/src/log-tlslog.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2013 Open Information Security Foundation +/* Copyright (C) 2007-2014 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -20,8 +20,11 @@ * * \author Roliers Jean-Paul * \author Eric Leblond + * \author Victor Julien * - * Implements tls logging portion of the engine. + * Implements TLS logging portion of the engine. The TLS logger is + * implemented as a packet logger, as the TLS parser is not transaction + * aware. */ #include "suricata-common.h" @@ -112,7 +115,7 @@ static void LogTlsLogExtended(LogTlsLogThread *aft, SSLState * state) MemBufferWriteString(aft->buffer, "\n"); } -static int GetIPInformations(Packet *p, char* srcip, size_t srcip_len, +static int GetIPInformations(const Packet *p, char* srcip, size_t srcip_len, Port* sp, char* dstip, size_t dstip_len, Port* dp, int ipproto) { @@ -150,7 +153,7 @@ static int GetIPInformations(Packet *p, char* srcip, size_t srcip_len, return 1; } -static int CreateFileName(LogTlsFileCtx *log, Packet *p, SSLState *state, char *filename) +static int CreateFileName(LogTlsFileCtx *log, const Packet *p, SSLState *state, char *filename) { #define FILELEN 64 //filename len + extention + ending path / + some space @@ -172,8 +175,7 @@ static int CreateFileName(LogTlsFileCtx *log, Packet *p, SSLState *state, char * return 1; } - -static void LogTlsLogPem(LogTlsLogThread *aft, Packet *p, SSLState *state, LogTlsFileCtx *log, int ipproto) +static void LogTlsLogPem(LogTlsLogThread *aft, const Packet *p, SSLState *state, LogTlsFileCtx *log, int ipproto) { #define PEMHEADER "-----BEGIN CERTIFICATE-----\n" #define PEMFOOTER "-----END CERTIFICATE-----\n" @@ -307,114 +309,6 @@ end_fp: fclose(fp); } - -static TmEcode LogTlsLogIPWrapper(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq, int ipproto) -{ - - SCEnter(); - LogTlsLogThread *aft = (LogTlsLogThread *) data; - LogTlsFileCtx *hlog = aft->tlslog_ctx; - - char timebuf[64]; - - /* no flow, no tls state */ - if (p->flow == NULL) { - SCReturnInt(TM_ECODE_OK); - } - - /* check if we have TLS state or not */ - FLOWLOCK_WRLOCK(p->flow); - uint16_t proto = FlowGetAppProtocol(p->flow); - if (proto != ALPROTO_TLS) - goto end; - - SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow); - if (ssl_state == NULL) { - SCLogDebug("no tls state, so no request logging"); - goto end; - } - - if (ssl_state->server_connp.cert0_issuerdn == NULL || ssl_state->server_connp.cert0_subject == NULL) - goto end; - - if (ssl_state->server_connp.cert_log_flag & SSL_TLS_LOG_PEM) { - LogTlsLogPem(aft, p, ssl_state, hlog, ipproto); - } - - if (AppLayerParserGetTransactionLogId(p->flow->alparser) != 0) { - goto end; - } - - CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); - #define PRINT_BUF_LEN 46 - char srcip[PRINT_BUF_LEN], dstip[PRINT_BUF_LEN]; - Port sp, dp; - if (!GetIPInformations(p, srcip, PRINT_BUF_LEN, - &sp, dstip, PRINT_BUF_LEN, &dp, ipproto)) { - goto end; - } - - /* reset */ - MemBufferReset(aft->buffer); - - MemBufferWriteString(aft->buffer, - "%s %s:%d -> %s:%d TLS: Subject='%s' Issuerdn='%s'", - timebuf, srcip, sp, dstip, dp, - ssl_state->server_connp.cert0_subject, ssl_state->server_connp.cert0_issuerdn); - - AppLayerParserSetTransactionLogId(p->flow->alparser); - - if (hlog->flags & LOG_TLS_EXTENDED) { - LogTlsLogExtended(aft, ssl_state); - } else { - MemBufferWriteString(aft->buffer, "\n"); - } - - aft->tls_cnt ++; - - SCMutexLock(&hlog->file_ctx->fp_mutex); - MemBufferPrintToFPAsString(aft->buffer, hlog->file_ctx->fp); - fflush(hlog->file_ctx->fp); - SCMutexUnlock(&hlog->file_ctx->fp_mutex); - -end: - FLOWLOCK_UNLOCK(p->flow); - SCReturnInt(TM_ECODE_OK); - -} - -static TmEcode LogTlsLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) -{ - return LogTlsLogIPWrapper(tv, p, data, pq, postpq, AF_INET); -} - -static TmEcode LogTlsLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) -{ - return LogTlsLogIPWrapper(tv, p, data, pq, postpq, AF_INET6); -} - -static TmEcode LogTlsLog(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) -{ - SCEnter(); - - /* no flow, no htp state */ - if (p->flow == NULL) { - SCReturnInt(TM_ECODE_OK); - } - - if (!(PKT_IS_TCP(p))) { - SCReturnInt(TM_ECODE_OK); - } - - if (PKT_IS_IPV4(p)) { - SCReturnInt(LogTlsLogIPv4(tv, p, data, pq, postpq)); - } else if (PKT_IS_IPV6(p)) { - SCReturnInt(LogTlsLogIPv6(tv, p, data, pq, postpq)); - } - - SCReturnInt(TM_ECODE_OK); -} - static TmEcode LogTlsLogThreadInit(ThreadVars *t, void *initdata, void **data) { LogTlsLogThread *aft = SCMalloc(sizeof(LogTlsLogThread)); @@ -571,17 +465,123 @@ filectx_error: return NULL; } +/** \internal + * \brief Condition function for TLS logger + * \retval bool true or false -- log now? + */ +static int LogTlsCondition(ThreadVars *tv, const Packet *p) { + if (p->flow == NULL) { + return FALSE; + } + + if (!(PKT_IS_TCP(p))) { + return FALSE; + } + + FLOWLOCK_RDLOCK(p->flow); + uint16_t proto = FlowGetAppProtocol(p->flow); + if (proto != ALPROTO_TLS) + goto dontlog; + + SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow); + if (ssl_state == NULL) { + SCLogDebug("no tls state, so no request logging"); + goto dontlog; + } + + /* we only log the state once */ + if (ssl_state->flags & SSL_AL_FLAG_STATE_LOGGED) + goto dontlog; + + if (ssl_state->server_connp.cert0_issuerdn == NULL || + ssl_state->server_connp.cert0_subject == NULL) + goto dontlog; + + /* todo: logic to log once */ + + FLOWLOCK_UNLOCK(p->flow); + return TRUE; +dontlog: + FLOWLOCK_UNLOCK(p->flow); + return FALSE; +} + +static int LogTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p) { + LogTlsLogThread *aft = (LogTlsLogThread *)thread_data; + LogTlsFileCtx *hlog = aft->tlslog_ctx; + char timebuf[64]; + int ipproto = (PKT_IS_IPV4(p)) ? AF_INET : AF_INET6; + + if (unlikely(p->flow == NULL)) { + return 0; + } + + /* check if we have TLS state or not */ + FLOWLOCK_WRLOCK(p->flow); + uint16_t proto = FlowGetAppProtocol(p->flow); + if (proto != ALPROTO_TLS) + goto end; + + SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow); + if (unlikely(ssl_state == NULL)) { + goto end; + } + + if (ssl_state->server_connp.cert0_issuerdn == NULL || ssl_state->server_connp.cert0_subject == NULL) + goto end; + + if (ssl_state->server_connp.cert_log_flag & SSL_TLS_LOG_PEM) { + LogTlsLogPem(aft, p, ssl_state, hlog, ipproto); + } + + CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); +#define PRINT_BUF_LEN 46 + char srcip[PRINT_BUF_LEN], dstip[PRINT_BUF_LEN]; + Port sp, dp; + if (!GetIPInformations(p, srcip, PRINT_BUF_LEN, + &sp, dstip, PRINT_BUF_LEN, &dp, ipproto)) { + goto end; + } + + MemBufferReset(aft->buffer); + MemBufferWriteString(aft->buffer, + "%s %s:%d -> %s:%d TLS: Subject='%s' Issuerdn='%s'", + timebuf, srcip, sp, dstip, dp, + ssl_state->server_connp.cert0_subject, + ssl_state->server_connp.cert0_issuerdn); + + if (hlog->flags & LOG_TLS_EXTENDED) { + LogTlsLogExtended(aft, ssl_state); + } else { + MemBufferWriteString(aft->buffer, "\n"); + } + + aft->tls_cnt++; + + SCMutexLock(&hlog->file_ctx->fp_mutex); + MemBufferPrintToFPAsString(aft->buffer, hlog->file_ctx->fp); + fflush(hlog->file_ctx->fp); + SCMutexUnlock(&hlog->file_ctx->fp_mutex); + + /* we only log the state once */ + ssl_state->flags |= SSL_AL_FLAG_STATE_LOGGED; +end: + FLOWLOCK_UNLOCK(p->flow); + return 0; +} + void TmModuleLogTlsLogRegister(void) { tmm_modules[TMM_LOGTLSLOG].name = MODULE_NAME; tmm_modules[TMM_LOGTLSLOG].ThreadInit = LogTlsLogThreadInit; - tmm_modules[TMM_LOGTLSLOG].Func = LogTlsLog; + tmm_modules[TMM_LOGTLSLOG].Func = NULL; tmm_modules[TMM_LOGTLSLOG].ThreadExitPrintStats = LogTlsLogExitPrintStats; tmm_modules[TMM_LOGTLSLOG].ThreadDeinit = LogTlsLogThreadDeinit; tmm_modules[TMM_LOGTLSLOG].RegisterTests = NULL; tmm_modules[TMM_LOGTLSLOG].cap_flags = 0; - OutputRegisterModule(MODULE_NAME, "tls-log", LogTlsLogInitCtx); + OutputRegisterPacketModule(MODULE_NAME, "tls-log", LogTlsLogInitCtx, + LogTlsLogger, LogTlsCondition); SC_ATOMIC_INIT(cert_id); }