diff --git a/src/Makefile.am b/src/Makefile.am index 59522c0feb..1145471b79 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -228,6 +228,7 @@ alert-unified-log.c alert-unified-log.h \ alert-unified-alert.c alert-unified-alert.h \ alert-unified2-alert.c alert-unified2-alert.h \ alert-syslog.c alert-syslog.h \ +alert-pcapinfo.c alert-pcapinfo.h \ log-droplog.c log-droplog.h \ log-httplog.c log-httplog.h \ log-pcap.c log-pcap.h \ diff --git a/src/alert-pcapinfo.c b/src/alert-pcapinfo.c new file mode 100644 index 0000000000..e487ccfc83 --- /dev/null +++ b/src/alert-pcapinfo.c @@ -0,0 +1,237 @@ +/* Copyright (C) 2011 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 Eric Leblond + * + * Logs alerts in a line based text format suitable for interaction + * with wireshark or an other pcap file analysis tools. + * + * The format of the logging is: + * Packet number:GID of matching signature:SID of signature:REV of signature:Flow:To Server:To Client:0:0:Signature Message + * The two zeros are reserved for upcoming usage (probably byte start + * and byte end of payload) + */ + +#include "suricata-common.h" +#include "debug.h" +#include "detect.h" +#include "flow.h" +#include "conf.h" + +#include "threads.h" +#include "tm-threads.h" +#include "threadvars.h" +#include "util-debug.h" + +#include "util-unittest.h" +#include "util-unittest-helper.h" + +#include "detect.h" +#include "detect-parse.h" +#include "detect-engine.h" +#include "detect-engine-mpm.h" +#include "detect-reference.h" +#include "util-classification-config.h" + +#include "output.h" +#include "alert-pcapinfo.h" + +#include "util-mpm-b2g-cuda.h" +#include "util-cuda-handlers.h" +#include "util-privs.h" +#include "util-print.h" +#include "util-proto-name.h" +#include "util-optimize.h" + +#define DEFAULT_LOG_FILENAME "alert-pcapinfo.log" +/* We need a new file for each pcap */ +#define DEFAULT_PCAPINFO_MODE_APPEND "no" + +#define MODULE_NAME "AlertPcapInfo" + +TmEcode AlertPcapInfo (ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *); +TmEcode AlertPcapInfoThreadInit(ThreadVars *, void *, void **); +TmEcode AlertPcapInfoThreadDeinit(ThreadVars *, void *); +void AlertPcapInfoExitPrintStats(ThreadVars *, void *); +static int AlertPcapInfoOpenFileCtx(LogFileCtx *, const char *, const char *); +static void AlertPcapInfoDeInitCtx(OutputCtx *); + +void TmModuleAlertPcapInfoRegister (void) { + tmm_modules[TMM_ALERTPCAPINFO].name = MODULE_NAME; + tmm_modules[TMM_ALERTPCAPINFO].ThreadInit = AlertPcapInfoThreadInit; + tmm_modules[TMM_ALERTPCAPINFO].Func = AlertPcapInfo; + tmm_modules[TMM_ALERTPCAPINFO].ThreadExitPrintStats = AlertPcapInfoExitPrintStats; + tmm_modules[TMM_ALERTPCAPINFO].ThreadDeinit = AlertPcapInfoThreadDeinit; + tmm_modules[TMM_ALERTPCAPINFO].RegisterTests = NULL; + tmm_modules[TMM_ALERTPCAPINFO].cap_flags = 0; + + OutputRegisterModule(MODULE_NAME, "pcap-info", AlertPcapInfoInitCtx); +} + +typedef struct AlertPcapInfoThread_ { + /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ + LogFileCtx* file_ctx; +} AlertPcapInfoThread; + + +TmEcode AlertPcapInfo (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) +{ + AlertPcapInfoThread *aft = (AlertPcapInfoThread *)data; + int i; + + + /* logging is useless if we don't have pcap number */ + if ((p->pcap_cnt != 0) && (p->alerts.cnt > 0)) { + SCMutexLock(&aft->file_ctx->fp_mutex); + /* only count logged alert */ + aft->file_ctx->alerts += p->alerts.cnt; + for (i = 0; i < p->alerts.cnt; i++) { + PacketAlert *pa = &p->alerts.alerts[i]; + + fprintf(aft->file_ctx->fp, "%ld:%d:%d:%d:%d:%d:%d:0:0:%s\n", + p->pcap_cnt, pa->s->gid, pa->s->id, + pa->s->rev, pa->alert_msg ? 1 : 0, + p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0, + p->flowflags & FLOW_PKT_TOCLIENT ? 1 : 0, + pa->s->msg); + } + SCMutexUnlock(&aft->file_ctx->fp_mutex); + } + + return TM_ECODE_OK; +} + +TmEcode AlertPcapInfoThreadInit(ThreadVars *t, void *initdata, void **data) +{ + AlertPcapInfoThread *aft = SCMalloc(sizeof(AlertPcapInfoThread)); + if (aft == NULL) + return TM_ECODE_FAILED; + memset(aft, 0, sizeof(AlertPcapInfoThread)); + if(initdata == NULL) + { + SCLogDebug("Error getting context for AlertPcapInfo. \"initdata\" argument NULL"); + SCFree(aft); + return TM_ECODE_FAILED; + } + /** Use the Ouptut Context (file pointer and mutex) */ + aft->file_ctx = ((OutputCtx *)initdata)->data; + + *data = (void *)aft; + return TM_ECODE_OK; +} + +TmEcode AlertPcapInfoThreadDeinit(ThreadVars *t, void *data) +{ + AlertPcapInfoThread *aft = (AlertPcapInfoThread *)data; + if (aft == NULL) { + return TM_ECODE_OK; + } + + /* clear memory */ + memset(aft, 0, sizeof(AlertPcapInfoThread)); + + SCFree(aft); + return TM_ECODE_OK; +} + +void AlertPcapInfoExitPrintStats(ThreadVars *tv, void *data) { + AlertPcapInfoThread *aft = (AlertPcapInfoThread *)data; + if (aft == NULL) { + return; + } + + SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, aft->file_ctx->alerts); +} + +/** + * \brief Create a new LogFileCtx for "fast" output style. + * \param conf The configuration node for this output. + * \return A LogFileCtx pointer on success, NULL on failure. + */ +OutputCtx *AlertPcapInfoInitCtx(ConfNode *conf) +{ + LogFileCtx *logfile_ctx = LogFileNewCtx(); + if (logfile_ctx == NULL) { + SCLogDebug("AlertPcapInfoInitCtx2: Could not create new LogFileCtx"); + return NULL; + } + + const char *filename = ConfNodeLookupChildValue(conf, "filename"); + if (filename == NULL) + filename = DEFAULT_LOG_FILENAME; + + const char *mode = ConfNodeLookupChildValue(conf, "append"); + if (mode == NULL) + mode = DEFAULT_PCAPINFO_MODE_APPEND; + + if (AlertPcapInfoOpenFileCtx(logfile_ctx, filename, mode) < 0) { + LogFileFreeCtx(logfile_ctx); + return NULL; + } + + OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); + if (output_ctx == NULL) + return NULL; + output_ctx->data = logfile_ctx; + output_ctx->DeInit = AlertPcapInfoDeInitCtx; + + SCLogInfo("Fast log output initialized, filename: %s", filename); + + return output_ctx; +} + +static void AlertPcapInfoDeInitCtx(OutputCtx *output_ctx) +{ + LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data; + LogFileFreeCtx(logfile_ctx); + SCFree(output_ctx); +} + +/** \brief Read the config set the file pointer, open the file + * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() + * \param filename name of log file + * \param mode append mode (bool) + * \return -1 if failure, 0 if succesful + * */ +static int AlertPcapInfoOpenFileCtx(LogFileCtx *file_ctx, const char *filename, + const char *mode) +{ + char log_path[PATH_MAX]; + char *log_dir; + + if (ConfGet("default-log-dir", &log_dir) != 1) + log_dir = DEFAULT_LOG_DIR; + + snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); + + if (ConfValIsTrue(mode)) { + file_ctx->fp = fopen(log_path, "a"); + } else { + file_ctx->fp = fopen(log_path, "w"); + } + + if (file_ctx->fp == NULL) { + SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, + strerror(errno)); + return -1; + } + + return 0; +} diff --git a/src/alert-pcapinfo.h b/src/alert-pcapinfo.h new file mode 100644 index 0000000000..871c23f512 --- /dev/null +++ b/src/alert-pcapinfo.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2011 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 Eric Leblond + */ + +#ifndef __ALERT_PCAPINFO_H__ +#define __ALERT_PCAPINFO_H__ + +void TmModuleAlertPcapInfoRegister (void); +OutputCtx *AlertPcapInfoInitCtx(ConfNode *); + +#endif /* __ALERT_PCAPINFO_H__ */ diff --git a/src/suricata.c b/src/suricata.c index 7cd32ed84e..05b1317c60 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -82,6 +82,7 @@ #include "alert-debuglog.h" #include "alert-prelude.h" #include "alert-syslog.h" +#include "alert-pcapinfo.h" #include "log-droplog.h" #include "log-httplog.h" @@ -1208,6 +1209,7 @@ int main(int argc, char **argv) TmModuleAlertUnifiedAlertRegister(); TmModuleUnified2AlertRegister(); TmModuleAlertSyslogRegister(); + TmModuleAlertPcapInfoRegister(); TmModuleLogDropLogRegister(); TmModuleStreamTcpRegister(); TmModuleLogHttpLogRegister(); diff --git a/src/tm-threads-common.h b/src/tm-threads-common.h index 7b075daeb9..d506cd123c 100644 --- a/src/tm-threads-common.h +++ b/src/tm-threads-common.h @@ -72,6 +72,7 @@ typedef enum { TMM_DECODEERFDAG, TMM_RECEIVEAFP, TMM_DECODEAFP, + TMM_ALERTPCAPINFO, TMM_SIZE, } TmmId; diff --git a/suricata.yaml b/suricata.yaml index 9214c3fdbb..03c4d1d3ee 100644 --- a/suricata.yaml +++ b/suricata.yaml @@ -77,6 +77,13 @@ outputs: filename: http.log append: yes + # a line based log to used with pcap file study. + # this module is dedicated to offline pcap parsing (empty output + # if used with an other kind of input). It can interoperate with + # pcap parser like wireshark via the suriwire plugin. + - pcap-info: + enabled: no + # Packet log... log packets in pcap format. 2 modes of operation: "normal" # and "sguil". #