diff options
Diffstat (limited to 'framework/src/suricata/src/log-tlsstore.c')
-rw-r--r-- | framework/src/suricata/src/log-tlsstore.c | 439 |
1 files changed, 0 insertions, 439 deletions
diff --git a/framework/src/suricata/src/log-tlsstore.c b/framework/src/suricata/src/log-tlsstore.c deleted file mode 100644 index da23908e..00000000 --- a/framework/src/suricata/src/log-tlsstore.c +++ /dev/null @@ -1,439 +0,0 @@ -/* Copyright (C) 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 - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Roliers Jean-Paul <popof.fpn@gmail.co> - * \author Eric Leblond <eric@regit.org> - * \author Victor Julien <victor@inliniac.net> - * - * Implements TLS store portion of the engine. - * - */ - -#include "suricata-common.h" -#include "debug.h" -#include "detect.h" -#include "pkt-var.h" -#include "conf.h" - -#include "threads.h" -#include "threadvars.h" -#include "tm-threads.h" - -#include "util-print.h" -#include "util-unittest.h" - -#include "util-debug.h" - -#include "output.h" -#include "log-tlslog.h" -#include "app-layer-ssl.h" -#include "app-layer.h" -#include "app-layer-parser.h" -#include "util-privs.h" -#include "util-buffer.h" - -#include "util-logopenfile.h" -#include "util-crypt.h" -#include "util-time.h" - -#define MODULE_NAME "LogTlsStoreLog" - -static char tls_logfile_base_dir[PATH_MAX] = "/tmp"; -SC_ATOMIC_DECLARE(unsigned int, cert_id); -static char logging_dir_not_writable; - -#define LOGGING_WRITE_ISSUE_LIMIT 6 - -typedef struct LogTlsStoreLogThread_ { - uint32_t tls_cnt; - - uint8_t* enc_buf; - size_t enc_buf_len; -} LogTlsStoreLogThread; - -static int CreateFileName(const Packet *p, SSLState *state, char *filename) -{ -#define FILELEN 64 //filename len + extention + ending path / + some space - - int filenamelen = FILELEN + strlen(tls_logfile_base_dir); - int file_id = SC_ATOMIC_ADD(cert_id, 1); - - if (filenamelen + 1 > PATH_MAX) { - return 0; - } - - /* 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 */ - snprintf(filename, filenamelen, "%s/%ld.%ld-%d.pem", - tls_logfile_base_dir, - (long int)p->ts.tv_sec, - (long int)p->ts.tv_usec, - file_id); - return 1; -} - -static void LogTlsLogPem(LogTlsStoreLogThread *aft, const Packet *p, SSLState *state, int ipproto) -{ -#define PEMHEADER "-----BEGIN CERTIFICATE-----\n" -#define PEMFOOTER "-----END CERTIFICATE-----\n" - //Logging pem certificate - char filename[PATH_MAX] = ""; - FILE* fp = NULL; - FILE* fpmeta = NULL; - unsigned long pemlen; - unsigned char* pembase64ptr = NULL; - int ret; - uint8_t *ptmp; - SSLCertsChain *cert; - - if ((state->server_connp.cert_input == NULL) || (state->server_connp.cert_input_len == 0)) - SCReturn; - - CreateFileName(p, state, filename); - if (strlen(filename) == 0) { - SCLogWarning(SC_ERR_FOPEN, "Can't create PEM filename"); - SCReturn; - } - - fp = fopen(filename, "w"); - if (fp == NULL) { - if (logging_dir_not_writable < LOGGING_WRITE_ISSUE_LIMIT) { - SCLogWarning(SC_ERR_FOPEN, - "Can't create PEM file '%s' in '%s' directory", - filename, tls_logfile_base_dir); - logging_dir_not_writable++; - } - SCReturn; - } - - TAILQ_FOREACH(cert, &state->server_connp.certs, next) { - pemlen = (4 * (cert->cert_len + 2) / 3) +1; - if (pemlen > aft->enc_buf_len) { - ptmp = (uint8_t*) SCRealloc(aft->enc_buf, sizeof(uint8_t) * pemlen); - if (ptmp == NULL) { - SCFree(aft->enc_buf); - aft->enc_buf = NULL; - SCLogWarning(SC_ERR_MEM_ALLOC, "Can't allocate data for base64 encoding"); - goto end_fp; - } - aft->enc_buf = ptmp; - aft->enc_buf_len = pemlen; - } - - memset(aft->enc_buf, 0, aft->enc_buf_len); - - ret = Base64Encode((unsigned char*) cert->cert_data, cert->cert_len, aft->enc_buf, &pemlen); - if (ret != SC_BASE64_OK) { - SCLogWarning(SC_ERR_INVALID_ARGUMENTS, "Invalid return of Base64Encode function"); - goto end_fwrite_fp; - } - - if (fprintf(fp, PEMHEADER) < 0) - goto end_fwrite_fp; - - pembase64ptr = aft->enc_buf; - while (pemlen > 0) { - size_t loffset = pemlen >= 64 ? 64 : pemlen; - if (fwrite(pembase64ptr, 1, loffset, fp) != loffset) - goto end_fwrite_fp; - if (fwrite("\n", 1, 1, fp) != 1) - goto end_fwrite_fp; - pembase64ptr += 64; - if (pemlen < 64) - break; - pemlen -= 64; - } - - if (fprintf(fp, PEMFOOTER) < 0) - goto end_fwrite_fp; - } - fclose(fp); - - //Logging certificate informations - memcpy(filename + (strlen(filename) - 3), "meta", 4); - fpmeta = fopen(filename, "w"); - if (fpmeta != NULL) { - #define PRINT_BUF_LEN 46 - char srcip[PRINT_BUF_LEN], dstip[PRINT_BUF_LEN]; - char timebuf[64]; - Port sp, dp; - CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); - if (!TLSGetIPInformations(p, srcip, PRINT_BUF_LEN, &sp, dstip, PRINT_BUF_LEN, &dp, ipproto)) - goto end_fwrite_fpmeta; - if (fprintf(fpmeta, "TIME: %s\n", timebuf) < 0) - goto end_fwrite_fpmeta; - if (p->pcap_cnt > 0) { - if (fprintf(fpmeta, "PCAP PKT NUM: %"PRIu64"\n", p->pcap_cnt) < 0) - goto end_fwrite_fpmeta; - } - if (fprintf(fpmeta, "SRC IP: %s\n", srcip) < 0) - goto end_fwrite_fpmeta; - if (fprintf(fpmeta, "DST IP: %s\n", dstip) < 0) - goto end_fwrite_fpmeta; - if (fprintf(fpmeta, "PROTO: %" PRIu32 "\n", p->proto) < 0) - goto end_fwrite_fpmeta; - if (PKT_IS_TCP(p) || PKT_IS_UDP(p)) { - if (fprintf(fpmeta, "SRC PORT: %" PRIu16 "\n", sp) < 0) - goto end_fwrite_fpmeta; - if (fprintf(fpmeta, "DST PORT: %" PRIu16 "\n", dp) < 0) - goto end_fwrite_fpmeta; - } - - 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) - goto end_fwrite_fpmeta; - - fclose(fpmeta); - } else { - if (logging_dir_not_writable < LOGGING_WRITE_ISSUE_LIMIT) { - SCLogWarning(SC_ERR_FOPEN, - "Can't create meta file '%s' in '%s' directory", - filename, tls_logfile_base_dir); - logging_dir_not_writable++; - } - SCReturn; - } - - /* Reset the store flag */ - state->server_connp.cert_log_flag &= ~SSL_TLS_LOG_PEM; - SCReturn; - -end_fwrite_fp: - fclose(fp); - if (logging_dir_not_writable < LOGGING_WRITE_ISSUE_LIMIT) { - SCLogWarning(SC_ERR_FWRITE, "Unable to write certificate"); - logging_dir_not_writable++; - } -end_fwrite_fpmeta: - if (fpmeta) { - fclose(fpmeta); - if (logging_dir_not_writable < LOGGING_WRITE_ISSUE_LIMIT) { - SCLogWarning(SC_ERR_FWRITE, "Unable to write certificate metafile"); - logging_dir_not_writable++; - } - } - SCReturn; -end_fp: - fclose(fp); - SCReturn; -} - -/** \internal - * \brief Condition function for TLS logger - * \retval bool true or false -- log now? - */ -static int LogTlsStoreCondition(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 we don't have to write - * the cert due to tls.store keyword. */ - if (!(ssl_state->server_connp.cert_log_flag & SSL_TLS_LOG_PEM) && - (ssl_state->flags & SSL_AL_FLAG_STATE_STORED)) - goto dontlog; - - if (ssl_state->server_connp.cert0_issuerdn == NULL || - ssl_state->server_connp.cert0_subject == NULL) - goto dontlog; - - FLOWLOCK_UNLOCK(p->flow); - return TRUE; -dontlog: - FLOWLOCK_UNLOCK(p->flow); - return FALSE; -} - -static int LogTlsStoreLogger(ThreadVars *tv, void *thread_data, const Packet *p) -{ - LogTlsStoreLogThread *aft = (LogTlsStoreLogThread *)thread_data; - int ipproto = (PKT_IS_IPV4(p)) ? AF_INET : AF_INET6; - /* 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.cert_log_flag & SSL_TLS_LOG_PEM) { - LogTlsLogPem(aft, p, ssl_state, ipproto); - } - - /* we only store the state once */ - ssl_state->flags |= SSL_AL_FLAG_STATE_STORED; -end: - FLOWLOCK_UNLOCK(p->flow); - return 0; -} - -static TmEcode LogTlsStoreLogThreadInit(ThreadVars *t, void *initdata, void **data) -{ - LogTlsStoreLogThread *aft = SCMalloc(sizeof(LogTlsStoreLogThread)); - if (unlikely(aft == NULL)) - return TM_ECODE_FAILED; - memset(aft, 0, sizeof(LogTlsStoreLogThread)); - - if (initdata == NULL) { - SCLogDebug("Error getting context for LogTlsStore. \"initdata\" argument NULL"); - SCFree(aft); - return TM_ECODE_FAILED; - } - - struct stat stat_buf; - if (stat(tls_logfile_base_dir, &stat_buf) != 0) { - int ret; - ret = mkdir(tls_logfile_base_dir, S_IRWXU|S_IXGRP|S_IRGRP); - if (ret != 0) { - int err = errno; - if (err != EEXIST) { - SCLogError(SC_ERR_LOGDIR_CONFIG, - "Cannot create certs drop directory %s: %s", - tls_logfile_base_dir, strerror(err)); - exit(EXIT_FAILURE); - } - } else { - SCLogInfo("Created certs drop directory %s", - tls_logfile_base_dir); - } - - } - - *data = (void *)aft; - return TM_ECODE_OK; -} - -static TmEcode LogTlsStoreLogThreadDeinit(ThreadVars *t, void *data) -{ - LogTlsStoreLogThread *aft = (LogTlsStoreLogThread *)data; - if (aft == NULL) { - return TM_ECODE_OK; - } - - /* clear memory */ - memset(aft, 0, sizeof(LogTlsStoreLogThread)); - - SCFree(aft); - return TM_ECODE_OK; -} - -static void LogTlsStoreLogExitPrintStats(ThreadVars *tv, void *data) -{ - LogTlsStoreLogThread *aft = (LogTlsStoreLogThread *)data; - if (aft == NULL) { - return; - } - - SCLogInfo("(%s) certificates extracted %" PRIu32 "", tv->name, aft->tls_cnt); -} - -/** - * \internal - * - * \brief deinit the log ctx and write out the waldo - * - * \param output_ctx output context to deinit - */ -static void LogTlsStoreLogDeInitCtx(OutputCtx *output_ctx) -{ - SCFree(output_ctx); -} - -/** \brief Create a new http log LogFilestoreCtx. - * \param conf Pointer to ConfNode containing this loggers configuration. - * \return NULL if failure, LogFilestoreCtx* to the file_ctx if succesful - * */ -static OutputCtx *LogTlsStoreLogInitCtx(ConfNode *conf) -{ - - OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); - if (unlikely(output_ctx == NULL)) - return NULL; - - output_ctx->data = NULL; - output_ctx->DeInit = LogTlsStoreLogDeInitCtx; - - /* FIXME we need to implement backward compability here */ - char *s_default_log_dir = NULL; - s_default_log_dir = ConfigGetLogDirectory(); - - const char *s_base_dir = NULL; - s_base_dir = ConfNodeLookupChildValue(conf, "certs-log-dir"); - if (s_base_dir == NULL || strlen(s_base_dir) == 0) { - strlcpy(tls_logfile_base_dir, - s_default_log_dir, sizeof(tls_logfile_base_dir)); - } else { - if (PathIsAbsolute(s_base_dir)) { - strlcpy(tls_logfile_base_dir, - s_base_dir, sizeof(tls_logfile_base_dir)); - } else { - snprintf(tls_logfile_base_dir, sizeof(tls_logfile_base_dir), - "%s/%s", s_default_log_dir, s_base_dir); - } - } - - SCLogInfo("storing certs in %s", tls_logfile_base_dir); - - SCReturnPtr(output_ctx, "OutputCtx"); -} - -void TmModuleLogTlsStoreRegister (void) -{ - tmm_modules[TMM_TLSSTORE].name = MODULE_NAME; - tmm_modules[TMM_TLSSTORE].ThreadInit = LogTlsStoreLogThreadInit; - tmm_modules[TMM_TLSSTORE].Func = NULL; - tmm_modules[TMM_TLSSTORE].ThreadExitPrintStats = LogTlsStoreLogExitPrintStats; - tmm_modules[TMM_TLSSTORE].ThreadDeinit = LogTlsStoreLogThreadDeinit; - tmm_modules[TMM_TLSSTORE].RegisterTests = NULL; - tmm_modules[TMM_TLSSTORE].cap_flags = 0; - tmm_modules[TMM_TLSSTORE].flags = TM_FLAG_LOGAPI_TM; - tmm_modules[TMM_TLSSTORE].priority = 10; - - OutputRegisterPacketModule(MODULE_NAME, "tls-store", LogTlsStoreLogInitCtx, - LogTlsStoreLogger, LogTlsStoreCondition); - - SC_ATOMIC_INIT(cert_id); - - SCLogDebug("registered"); -} |