From: Eric Leblond Date: Sun, 1 Nov 2020 08:54:47 +0000 (+0100) Subject: log/pcap: conditional logging X-Git-Tag: suricata-7.0.0-beta1~582 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4cab5e5262f358b530cf4478498701c0316c7ef5;p=thirdparty%2Fsuricata.git log/pcap: conditional logging Add an option to only write to pcap packets with alerts and flow that have alerted. --- diff --git a/src/alert-debuglog.c b/src/alert-debuglog.c index 8a20a8b5ac..a272740dd0 100644 --- a/src/alert-debuglog.c +++ b/src/alert-debuglog.c @@ -468,7 +468,7 @@ error: return result; } -static int AlertDebugLogCondition(ThreadVars *tv, const Packet *p) +static int AlertDebugLogCondition(ThreadVars *tv, void *thread_data, const Packet *p) { return (p->alerts.cnt ? TRUE : FALSE); } diff --git a/src/alert-fastlog.c b/src/alert-fastlog.c index 8a07f29822..5800ea3075 100644 --- a/src/alert-fastlog.c +++ b/src/alert-fastlog.c @@ -69,7 +69,7 @@ TmEcode AlertFastLogThreadDeinit(ThreadVars *, void *); void AlertFastLogRegisterTests(void); static void AlertFastLogDeInitCtx(OutputCtx *); -int AlertFastLogCondition(ThreadVars *tv, const Packet *p); +int AlertFastLogCondition(ThreadVars *tv, void *thread_data, const Packet *p); int AlertFastLogger(ThreadVars *tv, void *data, const Packet *p); void AlertFastLogRegister(void) @@ -85,7 +85,7 @@ typedef struct AlertFastLogThread_ { LogFileCtx* file_ctx; } AlertFastLogThread; -int AlertFastLogCondition(ThreadVars *tv, const Packet *p) +int AlertFastLogCondition(ThreadVars *tv, void *thread_data, const Packet *p) { return (p->alerts.cnt ? TRUE : FALSE); } diff --git a/src/alert-syslog.c b/src/alert-syslog.c index 6307d982d6..bba155c8ed 100644 --- a/src/alert-syslog.c +++ b/src/alert-syslog.c @@ -367,7 +367,7 @@ static TmEcode AlertSyslogDecoderEvent(ThreadVars *tv, const Packet *p, void *da return TM_ECODE_OK; } -static int AlertSyslogCondition(ThreadVars *tv, const Packet *p) +static int AlertSyslogCondition(ThreadVars *tv, void *thread_data, const Packet *p) { return (p->alerts.cnt > 0 ? TRUE : FALSE); } diff --git a/src/log-pcap.c b/src/log-pcap.c index a7a5ccd8c4..3c44d3fd2b 100644 --- a/src/log-pcap.c +++ b/src/log-pcap.c @@ -75,6 +75,11 @@ #define LOGMODE_SGUIL 1 #define LOGMODE_MULTI 2 +typedef enum LogModeConditionalType_ { + LOGMODE_COND_ALL, + LOGMODE_COND_ALERTS +} LogModeConditionalType; + #define RING_BUFFER_MODE_DISABLED 0 #define RING_BUFFER_MODE_ENABLED 1 @@ -155,6 +160,8 @@ typedef struct PcapLogData_ { uint64_t profile_data_size; /**< track in bytes how many bytes we wrote */ uint32_t file_cnt; /**< count of pcap files we currently have */ uint32_t max_files; /**< maximum files to use in ring buffer mode */ + LogModeConditionalType + conditional; /**< log all packets or just packets and flows with alerts */ PcapLogProfileData profile_lock; PcapLogProfileData profile_write; @@ -200,7 +207,7 @@ static TmEcode PcapLogDataDeinit(ThreadVars *, void *); static void PcapLogFileDeInitCtx(OutputCtx *); static OutputInitResult PcapLogInitCtx(ConfNode *); static void PcapLogProfilingDump(PcapLogData *); -static int PcapLogCondition(ThreadVars *, const Packet *); +static int PcapLogCondition(ThreadVars *, void *, const Packet *); void PcapLogRegister(void) { @@ -220,14 +227,24 @@ void PcapLogRegister(void) (prof).total += (UtilCpuGetTicks() - pcaplog_profile_ticks); \ (prof).cnt++ -static int PcapLogCondition(ThreadVars *tv, const Packet *p) +static int PcapLogCondition(ThreadVars *tv, void *thread_data, const Packet *p) { + PcapLogThreadData *ptd = (PcapLogThreadData *)thread_data; + if (p->flags & PKT_PSEUDO_STREAM_END) { return FALSE; } if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) { return FALSE; } + /* Log alerted flow */ + if (ptd->pcap_log->conditional == LOGMODE_COND_ALERTS) { + if (p->alerts.cnt || (p->flow && FlowHasAlerts(p->flow))) { + return TRUE; + } else { + return FALSE; + } + } return TRUE; } @@ -630,6 +647,7 @@ static PcapLogData *PcapLogDataCopy(const PcapLogData *pl) copy->timestamp_format = pl->timestamp_format; copy->use_stream_depth = pl->use_stream_depth; copy->size_limit = pl->size_limit; + copy->conditional = pl->conditional; const PcapLogCompressionData *comp = &pl->compression; PcapLogCompressionData *copy_comp = ©->compression; @@ -1194,6 +1212,7 @@ static OutputInitResult PcapLogInitCtx(ConfNode *conf) pl->timestamp_format = TS_FORMAT_SEC; pl->use_stream_depth = USE_STREAM_DEPTH_DISABLED; pl->honor_pass_rules = HONOR_PASS_RULES_DISABLED; + pl->conditional = LOGMODE_COND_ALL; TAILQ_INIT(&pl->pcap_file_list); @@ -1416,6 +1435,21 @@ static OutputInitResult PcapLogInitCtx(ConfNode *conf) SCLogInfo("Selected pcap-log compression method: %s", compression_str ? compression_str : "none"); + + const char *s_conditional = ConfNodeLookupChildValue(conf, "conditional"); + if (s_conditional != NULL) { + if (strcasecmp(s_conditional, "alerts") == 0) { + pl->conditional = LOGMODE_COND_ALERTS; + } else if (strcasecmp(s_conditional, "all") != 0) { + FatalError(SC_ERR_INVALID_ARGUMENT, + "log-pcap: invalid conditional \"%s\". Valid options: \"all\", " + "or \"alerts\" mode ", + s_conditional); + } + } + + SCLogInfo( + "Selected pcap-log conditional logging: %s", s_conditional ? s_conditional : "all"); } if (ParseFilename(pl, filename) != 0) diff --git a/src/output-json-alert.c b/src/output-json-alert.c index feafebaf34..3f32692d96 100644 --- a/src/output-json-alert.c +++ b/src/output-json-alert.c @@ -836,7 +836,7 @@ static int JsonAlertLogger(ThreadVars *tv, void *thread_data, const Packet *p) return 0; } -static int JsonAlertLogCondition(ThreadVars *tv, const Packet *p) +static int JsonAlertLogCondition(ThreadVars *tv, void *thread_data, const Packet *p) { if (p->alerts.cnt || (p->flags & PKT_HAS_TAG)) { return TRUE; diff --git a/src/output-json-anomaly.c b/src/output-json-anomaly.c index 7864f8fe56..c2f9f9709e 100644 --- a/src/output-json-anomaly.c +++ b/src/output-json-anomaly.c @@ -280,7 +280,7 @@ static int JsonAnomalyLogger(ThreadVars *tv, void *thread_data, const Packet *p) return AnomalyJson(tv, aft, p); } -static int JsonAnomalyLogCondition(ThreadVars *tv, const Packet *p) +static int JsonAnomalyLogCondition(ThreadVars *tv, void *thread_data, const Packet *p) { return p->events.cnt > 0 || (p->app_layer_events && p->app_layer_events->cnt > 0) || diff --git a/src/output-json-drop.c b/src/output-json-drop.c index b2b5925e0a..bd10f49e33 100644 --- a/src/output-json-drop.c +++ b/src/output-json-drop.c @@ -324,7 +324,7 @@ static int JsonDropLogger(ThreadVars *tv, void *thread_data, const Packet *p) * * \retval bool TRUE or FALSE */ -static int JsonDropLogCondition(ThreadVars *tv, const Packet *p) +static int JsonDropLogCondition(ThreadVars *tv, void *data, const Packet *p) { if (!EngineModeIsIPS()) { SCLogDebug("engine is not running in inline mode, so returning"); diff --git a/src/output-json-frame.c b/src/output-json-frame.c index ac2bcce0e4..76e0475446 100644 --- a/src/output-json-frame.c +++ b/src/output-json-frame.c @@ -368,7 +368,7 @@ static int JsonFrameLogger(ThreadVars *tv, void *thread_data, const Packet *p) return FrameJson(tv, aft, p); } -static int JsonFrameLogCondition(ThreadVars *tv, const Packet *p) +static int JsonFrameLogCondition(ThreadVars *tv, void *thread_data, const Packet *p) { if (p->flow == NULL || p->flow->alproto == ALPROTO_UNKNOWN) return FALSE; diff --git a/src/output-json-metadata.c b/src/output-json-metadata.c index 62583dfcdf..6ec943ddd5 100644 --- a/src/output-json-metadata.c +++ b/src/output-json-metadata.c @@ -88,7 +88,7 @@ static int JsonMetadataLogger(ThreadVars *tv, void *thread_data, const Packet *p return MetadataJson(tv, aft, p); } -static int JsonMetadataLogCondition(ThreadVars *tv, const Packet *p) +static int JsonMetadataLogCondition(ThreadVars *tv, void *data, const Packet *p) { if (p->pktvar) { return TRUE; diff --git a/src/output-lua.c b/src/output-lua.c index 09bafc5ac3..8e1ae3c7e0 100644 --- a/src/output-lua.c +++ b/src/output-lua.c @@ -230,7 +230,7 @@ not_supported: SCReturnInt(0); } -static int LuaPacketConditionAlerts(ThreadVars *tv, const Packet *p) +static int LuaPacketConditionAlerts(ThreadVars *tv, void *data, const Packet *p) { if (p->alerts.cnt > 0) return TRUE; @@ -280,7 +280,7 @@ not_supported: SCReturnInt(0); } -static int LuaPacketCondition(ThreadVars *tv, const Packet *p) +static int LuaPacketCondition(ThreadVars *tv, void *data, const Packet *p) { return TRUE; } diff --git a/src/output-packet.c b/src/output-packet.c index 8a5e851cfc..c7b509520d 100644 --- a/src/output-packet.c +++ b/src/output-packet.c @@ -106,7 +106,7 @@ static TmEcode OutputPacketLog(ThreadVars *tv, Packet *p, void *thread_data) while (logger && store) { DEBUG_VALIDATE_BUG_ON(logger->LogFunc == NULL || logger->ConditionFunc == NULL); - if ((logger->ConditionFunc(tv, (const Packet *)p)) == TRUE) { + if ((logger->ConditionFunc(tv, store->thread_data, (const Packet *)p)) == TRUE) { PACKET_PROFILING_LOGGER_START(p, logger->logger_id); logger->LogFunc(tv, store->thread_data, (const Packet *)p); PACKET_PROFILING_LOGGER_END(p, logger->logger_id); diff --git a/src/output-packet.h b/src/output-packet.h index da40ccde47..d51f855453 100644 --- a/src/output-packet.h +++ b/src/output-packet.h @@ -35,7 +35,7 @@ typedef int (*PacketLogger)(ThreadVars *, void *thread_data, const Packet *); /** packet logger condition function pointer type, * must return true for packets that should be logged */ -typedef int (*PacketLogCondition)(ThreadVars *, const Packet *); +typedef int (*PacketLogCondition)(ThreadVars *, void *thread_data, const Packet *); int OutputRegisterPacketLogger(LoggerId logger_id, const char *name, PacketLogger LogFunc, PacketLogCondition ConditionFunc, OutputCtx *, diff --git a/suricata.yaml.in b/suricata.yaml.in index 1876adaf87..280c8791bb 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -402,6 +402,8 @@ outputs: #ts-format: usec # sec or usec second format (default) is filename.sec usec is filename.sec.usec use-stream-depth: no #If set to "yes" packets seen after reaching stream inspection depth are ignored. "no" logs all packets honor-pass-rules: no # If set to "yes", flows in which a pass rule matched will stop being logged. + # Use "all" to log all packets or use "alerts" to log only alerted packets and flows + #conditional: all # a full alert log containing much information for signature writers # or for investigating suspected false positives.