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