]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Squashed commit of the following:
authorRuss Combs <rucombs@cisco.com>
Mon, 7 Aug 2017 02:20:21 +0000 (22:20 -0400)
committerRuss Combs <rucombs@cisco.com>
Mon, 7 Aug 2017 02:20:21 +0000 (22:20 -0400)
commit bb852740170eedb059ad0453f80bdf069b79310b
Author: Russ Combs <rucombs@cisco.com>
Date:   Sun Aug 6 21:14:46 2017 -0400

    snort: exit with zero from usage

commit 262814841a5060e349daf357a72146cb921eb7bc
Author: Russ Combs <rucombs@cisco.com>
Date:   Sun Aug 6 20:27:40 2017 -0400

    snort: add --dump-msg-map

commit c7db261aea251d9c8a887f28784dea9235483d82
Author: Russ Combs <rucombs@cisco.com>
Date:   Sun Aug 6 19:40:05 2017 -0400

    snort: fix --dump-builtin-rules to accept optional module prefix

commit b1987eb132b7bdfdc6c43a9f4f80a4e46ddb3e68
Author: Russ Combs <rucombs@cisco.com>
Date:   Sun Aug 6 09:20:02 2017 -0400

    unified2: resurrect old u2 as unified2x in extra until new u2 events are supported

15 files changed:
extra/configure.ac
extra/src/loggers/CMakeLists.txt
extra/src/loggers/Makefile.am
extra/src/loggers/unified2x/CMakeLists.txt [new file with mode: 0644]
extra/src/loggers/unified2x/Makefile.am [new file with mode: 0644]
extra/src/loggers/unified2x/unified2x.cc [new file with mode: 0644]
extra/src/loggers/unified2x/unified2x.h [new file with mode: 0644]
src/log/CMakeLists.txt
src/log/Makefile.am
src/log/obfuscator.h
src/main/help.cc
src/main/help.h
src/main/snort_module.cc
src/managers/module_manager.cc
src/managers/module_manager.h

index 2ea26c8340115906c5afa8ff1cc1d9e51282dfdc..af5dbde0f35d048f98c27ede9938853165d110b5 100644 (file)
@@ -57,6 +57,7 @@ src/loggers/alert_ex/Makefile \
 src/loggers/alert_lua/Makefile \
 src/loggers/alert_unixsock/Makefile \
 src/loggers/log_null/Makefile \
+src/loggers/unified2x/Makefile \
 src/search_engines/Makefile \
 src/search_engines/lowmem/Makefile \
 src/so_rules/Makefile \
index d8ff5e79ccd7378e9f5c447936c672c0b6423349..e4f0f4855343e8f0ddf33f4166392441a944d70e 100644 (file)
@@ -2,3 +2,4 @@ add_subdirectory ( alert_ex )
 add_subdirectory ( alert_lua )
 add_subdirectory ( alert_unixsock )
 add_subdirectory ( log_null )
+add_subdirectory ( unified2x )
index 5668ce12c3e047b7f5054dabc7c80c1f6d5ff36b..83c71ec138fd2463ed2179dfb1a3521fc5070633 100644 (file)
@@ -2,7 +2,8 @@ SUBDIRS = \
 alert_ex \
 alert_lua \
 alert_unixsock \
-log_null
+log_null \
+unified2x
 
 AM_CPPFLAGS = @AM_CPPFLAGS@
 AM_CFLAGS= @AM_CFLAGS@
diff --git a/extra/src/loggers/unified2x/CMakeLists.txt b/extra/src/loggers/unified2x/CMakeLists.txt
new file mode 100644 (file)
index 0000000..831578a
--- /dev/null
@@ -0,0 +1,42 @@
+cmake_minimum_required ( VERSION 2.8.11 )
+project ( unified2x CXX )
+
+if ( APPLE )
+    set ( CMAKE_MACOSX_RPATH OFF )
+endif ( APPLE )
+
+include ( FindPkgConfig )
+pkg_search_module ( SNORT3 REQUIRED snort>=3 )
+
+add_library (
+    unified2x MODULE
+    unified2x.cc
+    unified2x.h
+)
+
+if ( APPLE )
+    set_target_properties (
+        unified2x
+        PROPERTIES
+            LINK_FLAGS "-undefined dynamic_lookup"
+    )
+endif ( APPLE )
+
+set_target_properties (
+    unified2x
+    PROPERTIES
+        PREFIX ""
+)
+
+set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )
+
+target_include_directories (
+    unified2x PUBLIC
+    ${SNORT3_INCLUDE_DIRS}
+)
+
+install (
+    TARGETS unified2x
+    LIBRARY
+        DESTINATION "lib/${CMAKE_PROJECT_NAME}/loggers"
+)
diff --git a/extra/src/loggers/unified2x/Makefile.am b/extra/src/loggers/unified2x/Makefile.am
new file mode 100644 (file)
index 0000000..7fb63c5
--- /dev/null
@@ -0,0 +1,8 @@
+unified2xlibdir = $(pkglibdir)/loggers
+
+AM_CXXFLAGS = @SNORT3_CFLAGS@ -std=c++11
+
+unified2xlib_LTLIBRARIES = unified2x.la
+unified2x_la_CXXFLAGS = $(AM_CXXFLAGS)
+unified2x_la_LDFLAGS  = -module -export-dynamic -avoid-version -shared
+unified2x_la_SOURCES  = unified2x.cc unified2x.h
diff --git a/extra/src/loggers/unified2x/unified2x.cc b/extra/src/loggers/unified2x/unified2x.cc
new file mode 100644 (file)
index 0000000..a06bc6b
--- /dev/null
@@ -0,0 +1,1008 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2007-2013 Sourcefire, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// unified2x.cc exists to support 2X tool chains like barnyard2 and snorby
+// until they are updated to work with the new u2 events produced by Snort++.
+
+/* unified2.c
+ * Adam Keeton
+ *
+ * 09/26/06
+ * This file is literally unified.c converted to write unified2
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sfbpf_dlt.h>
+
+#include "detection/signature.h"
+#include "detection/detection_util.h"
+#include "events/event.h"
+#include "framework/logger.h"
+#include "framework/module.h"
+#include "log/messages.h"
+#include "log/obfuscator.h"
+#include "log/unified2.h"
+#include "main/snort_config.h"
+#include "packet_io/active.h"
+#include "protocols/icmp4.h"
+#include "protocols/packet.h"
+#include "protocols/vlan.h"
+#include "stream/stream.h"
+#include "utils/safec.h"
+#include "utils/util.h"
+#include "utils/util_cstring.h"
+
+#ifdef HAVE_DAQ_API
+// FIXIT-L dlt should be in packet to avoid this
+#include "packet_io/sfdaq.h"
+#endif
+
+#ifdef HAVE_APPID_API
+// FIXIT-L log appid numbers since they are fixed
+#include "network_inspectors/appid/appid_api.h"
+#endif
+
+using namespace std;
+
+#define S_NAME "unified2x"
+#define F_NAME "unified2.log"  // don't include x for back compat with tool chains
+
+/* ------------------ Data structures --------------------------*/
+
+struct Unified2Config
+{
+    unsigned int limit;
+    int nostamp;
+    int mpls_event_types;
+    int vlan_event_types;
+};
+
+struct U2
+{
+    int base_proto;
+    uint32_t timestamp;
+    char filepath[STD_BUF];
+    FILE* stream;
+    unsigned int current;
+};
+
+/* -------------------- Global Variables ----------------------*/
+
+static THREAD_LOCAL U2 u2;
+
+/* Used for buffering header and payload of unified records so only one
+ * write is necessary. */
+constexpr unsigned u2_buf_sz =
+    sizeof(Serial_Unified2_Header) + sizeof(Unified2IDSEventIPv6) + IP_MAXPACKET;
+
+// TBD - is performance any better if these buffers are off the heap?
+static THREAD_LOCAL uint8_t write_pkt_buffer[u2_buf_sz];
+
+#define MAX_XDATA_WRITE_BUF_LEN \
+    (MAX_XFF_WRITE_BUF_LENGTH - \
+    sizeof(struct in6_addr) + DECODE_BLEN)
+
+/* This buffer is used in lieu of the underlying default stream buf to
+ * prevent flushing in the middle of a record.  Every write is force
+ * flushed to disk immediately after the entire record is written so
+ * spoolers get an entire record */
+
+/* use the size of the buffer we copy record data into */
+static THREAD_LOCAL char io_buffer[u2_buf_sz];
+
+/* -------------------- Local Functions -----------------------*/
+
+/* Unified2 Output functions */
+static void Unified2InitFile(Unified2Config*);
+static inline void Unified2RotateFile(Unified2Config*);
+static void _Unified2LogPacketAlert(Packet*, const char*, Unified2Config*, const Event*);
+static void Unified2Write(uint8_t*, uint32_t, Unified2Config*);
+
+static void _AlertIP4_v2(Packet*, const char*, Unified2Config*, const Event*);
+static void _AlertIP6_v2(Packet*, const char*, Unified2Config*, const Event*);
+
+static void AlertExtraData(Flow*, void* data, LogFunction* log_funcs, uint32_t max_count, uint32_t
+    xtradata_mask, uint32_t event_id, uint32_t event_second);
+
+#define U2_PACKET_FLAG 1
+/* Obsolete flag as UI wont check the impact_flag field anymore.*/
+#define U2_FLAG_BLOCKED 0x20
+/* New flags to set the pad field (corresponds to blocked column in UI) with packet action*/
+#define U2_BLOCKED_FLAG_ALLOW 0x00
+#define U2_BLOCKED_FLAG_BLOCK 0x01
+#define U2_BLOCKED_FLAG_WOULD 0x02
+#define U2_BLOCKED_FLAG_CANT  0x03
+
+static int s_blocked_flag[] =
+{
+    U2_BLOCKED_FLAG_ALLOW,
+    U2_BLOCKED_FLAG_CANT,
+    U2_BLOCKED_FLAG_WOULD,
+    U2_BLOCKED_FLAG_BLOCK,
+};
+
+static int GetU2Flags(const Packet*, uint8_t* pimpact)
+{
+    Active::ActiveStatus dispos = Active::get_status();
+
+    if ( dispos > Active::AST_ALLOW )
+        *pimpact = U2_FLAG_BLOCKED;
+
+    return s_blocked_flag[dispos];
+}
+
+/*
+ * Function: Unified2InitFile()
+ *
+ * Purpose: Initialize the unified2 output file
+ *
+ * Arguments: config => pointer to the plugin's reference data struct
+ *
+ * Returns: void function
+ */
+static void Unified2InitFile(Unified2Config* config)
+{
+    char filepath[STD_BUF];
+    char* fname_ptr;
+
+    if (config == NULL)
+    {
+        FatalError("%s(%d) Could not initialize unified2 file: Unified2 "
+            "configuration data is NULL.\n", __FILE__, __LINE__);
+    }
+
+    u2.timestamp = (uint32_t)time(NULL);
+
+    if (!config->nostamp)
+    {
+        if (SnortSnprintf(filepath, sizeof(filepath), "%s.%u",
+            u2.filepath, u2.timestamp) != SNORT_SNPRINTF_SUCCESS)
+        {
+            FatalError("%s(%d) Failed to copy unified2 file path.\n",
+                __FILE__, __LINE__);
+        }
+
+        fname_ptr = filepath;
+    }
+    else
+    {
+        fname_ptr = u2.filepath;
+    }
+
+    // FIXIT-P should use open() instead of fopen()
+    if ((u2.stream = fopen(fname_ptr, "wb")) == NULL)
+    {
+        FatalError("%s(%d) Could not open %s: %s\n",
+            __FILE__, __LINE__, fname_ptr, get_error(errno));
+    }
+
+    /* Set buffer to size of record buffer so the system doesn't flush
+     * part of a record if it's greater than BUFSIZ */
+    if (setvbuf(u2.stream, io_buffer, _IOFBF, sizeof(io_buffer)) != 0)
+    {
+        ErrorMessage("%s(%d) Could not set I/O buffer: %s. "
+            "Using system default.\n",
+            __FILE__, __LINE__, get_error(errno));
+    }
+
+    /* If test mode, close and delete the file */
+    if (SnortConfig::test_mode())  // FIXIT-L eliminate test check; should always remove if empty
+    {
+        fclose(u2.stream);
+        u2.stream = NULL;
+        if (unlink(fname_ptr) == -1)
+        {
+            ErrorMessage("%s(%d) Running in test mode so we want to remove "
+                "test unified2 file. Could not unlink file \"%s\": %s\n",
+                __FILE__, __LINE__, fname_ptr, get_error(errno));
+        }
+    }
+}
+
+static inline void Unified2RotateFile(Unified2Config* config)
+{
+    fclose(u2.stream);
+    u2.current = 0;
+    Unified2InitFile(config);
+}
+
+static void _AlertIP4_v2(Packet* p, const char*, Unified2Config* config, const Event* event)
+{
+    Serial_Unified2_Header hdr;
+    Unified2IDSEvent alertdata;
+    uint32_t write_len = sizeof(hdr) + sizeof(alertdata);
+
+    memset(&alertdata, 0, sizeof(alertdata));
+
+    alertdata.event_id = htonl(event->event_id);
+    alertdata.event_second = htonl(event->ref_time.tv_sec);
+    alertdata.event_microsecond = htonl(event->ref_time.tv_usec);
+    alertdata.generator_id = htonl(event->sig_info->gid);
+    alertdata.signature_id = htonl(event->sig_info->sid);
+    alertdata.signature_revision = htonl(event->sig_info->rev);
+    alertdata.classification_id = htonl(event->sig_info->class_id);
+    alertdata.priority_id = htonl(event->sig_info->priority);
+
+    if (p)
+    {
+        alertdata.blocked = GetU2Flags(p, &alertdata.impact_flag);
+
+        if (p->has_ip())
+        {
+            const ip::IP4Hdr* const iph = p->ptrs.ip_api.get_ip4h();
+            alertdata.ip_source = iph->get_src();
+            alertdata.ip_destination = iph->get_dst();
+        }
+        else if (p->flow)
+        {
+            if (p->is_from_client())
+            {
+                alertdata.ip_source = *(p->flow->client_ip.get_ip4_ptr());
+                alertdata.ip_destination = *(p->flow->server_ip.get_ip4_ptr());
+            }
+            else
+            {
+                alertdata.ip_source = *(p->flow->server_ip.get_ip4_ptr());
+                alertdata.ip_destination = *(p->flow->client_ip.get_ip4_ptr());
+            }
+        }
+
+        alertdata.ip_proto = p->get_ip_proto_next();
+
+        if ( p->type() == PktType::ICMP)
+        {
+            // If PktType == ICMP, icmph is set
+            alertdata.sport_itype = htons(p->ptrs.icmph->type);
+            alertdata.dport_icode = htons(p->ptrs.icmph->code);
+        }
+
+        alertdata.sport_itype = htons(p->ptrs.sp);
+        alertdata.dport_icode = htons(p->ptrs.dp);
+
+        if ((p->proto_bits & PROTO_BIT__MPLS) && (config->mpls_event_types))
+        {
+            alertdata.mpls_label = htonl(p->ptrs.mplsHdr.label);
+        }
+        if (config->vlan_event_types)
+        {
+            if (p->proto_bits & PROTO_BIT__VLAN)
+            {
+                alertdata.vlanId = htons(layer::get_vlan_layer(p)->vid());
+            }
+
+            alertdata.pad2 = htons(p->user_policy_id);
+        }
+
+#ifdef HAVE_APPID_API
+        if ( p->flow )
+        {
+            const char* app_name = appid_api.get_application_name(p->flow, p->is_from_client());
+            if ( app_name )
+                memcpy_s(alertdata.app_name, sizeof(alertdata.app_name), app_name, strlen(app_name) + 1);
+        }
+#endif
+    }
+
+    if ( config->limit && (u2.current + write_len) > config->limit )
+        Unified2RotateFile(config);
+
+    hdr.length = htonl(sizeof(alertdata));
+    hdr.type = htonl(UNIFIED2_IDS_EVENT_VLAN);
+
+    memcpy_s(write_pkt_buffer, sizeof(write_pkt_buffer), &hdr, sizeof(hdr));
+
+    size_t offset = sizeof(hdr);
+
+    memcpy_s(write_pkt_buffer + offset, sizeof(write_pkt_buffer) - offset, &alertdata, sizeof(alertdata));
+
+    Unified2Write(write_pkt_buffer, write_len, config);
+}
+
+static void _AlertIP6_v2(Packet* p, const char*, Unified2Config* config, const Event* event)
+{
+    Serial_Unified2_Header hdr;
+    Unified2IDSEventIPv6 alertdata;
+    uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Unified2IDSEventIPv6);
+
+    memset(&alertdata, 0, sizeof(alertdata));
+
+    alertdata.event_id = htonl(event->event_id);
+    alertdata.event_second = htonl(event->ref_time.tv_sec);
+    alertdata.event_microsecond = htonl(event->ref_time.tv_usec);
+    alertdata.generator_id = htonl(event->sig_info->gid);
+    alertdata.signature_id = htonl(event->sig_info->sid);
+    alertdata.signature_revision = htonl(event->sig_info->rev);
+    alertdata.classification_id = htonl(event->sig_info->class_id);
+    alertdata.priority_id = htonl(event->sig_info->priority);
+
+    if (p)
+    {
+        alertdata.blocked = GetU2Flags(p, &alertdata.impact_flag);
+
+        if(p->ptrs.ip_api.is_ip())
+        {
+            const SfIp* ip;
+            ip = p->ptrs.ip_api.get_src();
+            alertdata.ip_source = *(struct in6_addr*)ip->get_ip6_ptr();
+            ip = p->ptrs.ip_api.get_dst();
+            alertdata.ip_destination = *(struct in6_addr*)ip->get_ip6_ptr();
+        }
+        else if (p->flow)
+        {
+            if (p->is_from_client())
+            {
+                alertdata.ip_source = *(struct in6_addr*)p->flow->client_ip.get_ip6_ptr();
+                alertdata.ip_destination = *(struct in6_addr*)p->flow->server_ip.get_ip6_ptr();
+            }
+            else
+            {
+                alertdata.ip_source = *(struct in6_addr*)p->flow->server_ip.get_ip6_ptr();
+                alertdata.ip_destination = *(struct in6_addr*)p->flow->client_ip.get_ip6_ptr();
+            }
+        }
+
+        alertdata.ip_proto = p->get_ip_proto_next();
+
+        if ( p->type() == PktType::ICMP)
+        {
+            // If PktType == ICMP, icmph is set
+            alertdata.sport_itype = htons(p->ptrs.icmph->type);
+            alertdata.dport_icode = htons(p->ptrs.icmph->code);
+        }
+
+        alertdata.sport_itype = htons(p->ptrs.sp);
+        alertdata.dport_icode = htons(p->ptrs.dp);
+
+        if ((p->proto_bits & PROTO_BIT__MPLS) && (config->mpls_event_types))
+        {
+            alertdata.mpls_label = htonl(p->ptrs.mplsHdr.label);
+        }
+        if (config->vlan_event_types)
+        {
+            if (p->proto_bits & PROTO_BIT__VLAN)
+            {
+                alertdata.vlanId = htons(layer::get_vlan_layer(p)->vid());
+            }
+
+            alertdata.pad2 = htons(p->user_policy_id);
+        }
+
+#ifdef HAVE_APPID_API
+        if ( p->flow )
+        {
+            const char* app_name = appid_api.get_application_name(p->flow, p->is_from_client());
+            if ( app_name )
+                memcpy_s(alertdata.app_name, sizeof(alertdata.app_name), app_name, strlen(app_name) + 1);
+        }
+#endif
+    }
+
+    if ( config->limit && (u2.current + write_len) > config->limit )
+        Unified2RotateFile(config);
+
+    hdr.length = htonl(sizeof(Unified2IDSEventIPv6));
+    hdr.type = htonl(UNIFIED2_IDS_EVENT_IPV6_VLAN);
+
+    memcpy_s(write_pkt_buffer, sizeof(write_pkt_buffer), &hdr, sizeof(hdr));
+
+    size_t offset = sizeof(hdr);
+
+    memcpy_s(write_pkt_buffer + offset, sizeof(write_pkt_buffer) - offset,
+        &alertdata, sizeof(alertdata));
+
+    Unified2Write(write_pkt_buffer, write_len, config);
+}
+
+static void _WriteExtraData(Unified2Config* config,
+    uint32_t event_id,
+    uint32_t event_second,
+    const uint8_t* buffer,
+    uint32_t len,
+    uint32_t type)
+{
+    Serial_Unified2_Header hdr;
+    SerialUnified2ExtraData alertdata;
+    Unified2ExtraDataHdr alertHdr;
+    uint8_t write_buffer[MAX_XDATA_WRITE_BUF_LEN];
+    uint8_t* ptr = NULL;
+
+    uint32_t write_len = sizeof(hdr) + sizeof(alertHdr);
+
+    alertdata.sensor_id = 0;
+    alertdata.event_id = htonl(event_id);
+    alertdata.event_second = htonl(event_second);
+    alertdata.data_type = htonl(EVENT_DATA_TYPE_BLOB);
+
+    alertdata.type = htonl(type);
+    alertdata.blob_length = htonl(sizeof(alertdata.data_type) +
+        sizeof(alertdata.blob_length) + len);
+
+    write_len = write_len + sizeof(alertdata) + len;
+    alertHdr.event_type = htonl(EVENT_TYPE_EXTRA_DATA);
+    alertHdr.event_length = htonl(write_len - sizeof(hdr));
+
+    if (write_len > sizeof(write_buffer))
+        return;
+
+    if ( config->limit && (u2.current + write_len) > config->limit )
+        Unified2RotateFile(config);
+
+    hdr.length = htonl(write_len - sizeof(hdr));
+    hdr.type = htonl(UNIFIED2_EXTRA_DATA);
+
+    ptr = write_buffer;
+
+    memcpy_s(ptr, sizeof(write_buffer), &hdr, sizeof(hdr));
+
+    size_t offset = sizeof(hdr);
+
+    memcpy_s(ptr + offset, sizeof(write_buffer) - offset, &alertHdr, sizeof(alertHdr));
+
+    offset += sizeof(alertHdr);
+
+    memcpy_s(ptr + offset, sizeof(write_buffer) - offset, &alertdata, sizeof(alertdata));
+
+    offset += sizeof(alertdata);
+
+    memcpy_s(ptr + offset, sizeof(write_buffer) - offset, buffer, len);
+
+    Unified2Write(write_buffer, write_len, config);
+}
+
+static void AlertExtraData(
+    Flow* flow, void* data,
+    LogFunction* log_funcs, uint32_t max_count,
+    uint32_t xtradata_mask,
+    uint32_t event_id, uint32_t event_second)
+{
+    Unified2Config* config = (Unified2Config*)data;
+    uint32_t xid;
+
+    if ((config == NULL) || !xtradata_mask || !event_second)
+        return;
+
+    xid = ffs(xtradata_mask);
+
+    while ( xid && (xid <= max_count) )
+    {
+        uint32_t len = 0;
+        uint32_t type = 0;
+        uint8_t* write_buffer;
+
+        if ( log_funcs[xid-1](flow, &write_buffer, &len, &type) && (len > 0) )
+        {
+            _WriteExtraData(config, event_id, event_second, write_buffer, len, type);
+        }
+        xtradata_mask ^= BIT(xid);
+        xid = ffs(xtradata_mask);
+    }
+}
+
+static void _Unified2LogPacketAlert(
+    Packet* p, const char*, Unified2Config* config, const Event* event)
+{
+    Serial_Unified2_Header hdr;
+    Serial_Unified2Packet logheader;
+    uint32_t pkt_length = 0;
+    uint32_t write_len = sizeof(hdr) + sizeof(Serial_Unified2Packet) - 4;
+
+    logheader.sensor_id = 0;
+    logheader.linktype = u2.base_proto;
+
+    if (event != NULL)
+    {
+        logheader.event_id = htonl(event->event_reference);
+        logheader.event_second = htonl(event->ref_time.tv_sec);
+
+        DebugMessage(DEBUG_LOG, "------------\n");
+    }
+    else
+    {
+        logheader.event_id = 0;
+        logheader.event_second = 0;
+    }
+
+    if ( p and p->pkth )
+    {
+        logheader.packet_second = htonl((uint32_t)p->pkth->ts.tv_sec);
+        logheader.packet_microsecond = htonl((uint32_t)p->pkth->ts.tv_usec);
+        pkt_length = ( p->is_rebuilt() ) ? p->dsize : p->pkth->caplen;
+        logheader.packet_length = htonl(pkt_length);
+        write_len += pkt_length;
+    }
+    else
+    {
+        logheader.packet_second = 0;
+        logheader.packet_microsecond = 0;
+        logheader.packet_length = 0;
+    }
+
+    if ( config->limit && (u2.current + write_len) > config->limit )
+        Unified2RotateFile(config);
+
+    hdr.length = htonl(sizeof(Serial_Unified2Packet) - 4 + pkt_length);
+    hdr.type = ( p and p->is_rebuilt() ) ? htonl(UNIFIED2_BUFFER) : htonl(UNIFIED2_PACKET);
+
+    memcpy_s(write_pkt_buffer, sizeof(write_pkt_buffer), &hdr, sizeof(hdr));
+
+    size_t offset = sizeof(hdr);
+
+    memcpy_s(write_pkt_buffer + offset, sizeof(write_pkt_buffer) - offset,
+        &logheader, sizeof(logheader) - 4);
+
+    offset += sizeof(logheader) - 4;
+
+    if (pkt_length != 0)
+    {
+        if (pkt_length > sizeof(write_pkt_buffer) - offset)
+            return;
+
+        uint8_t *start = write_pkt_buffer + offset;
+
+        memcpy_s(start, sizeof(write_pkt_buffer) - offset,
+            p->is_data() ? p->data : p->pkt, pkt_length);
+
+        if ( p->obfuscator )
+        {
+            off_t off = p->data - p->pkt;
+
+            if ( p->is_data() )
+                off = 0;
+
+            for ( const auto& b : *p->obfuscator )
+                memset(&start[ off + b.offset ], p->obfuscator->get_mask_char(), b.length);
+        }
+    }
+
+    Unified2Write(write_pkt_buffer, write_len, config);
+}
+
+/******************************************************************************
+ * Function: Unified2Write()
+ *
+ * Main function for writing to the unified2 file.
+ *
+ * For low level I/O errors, the current unified2 file is closed and a new
+ * one created and a write to the new unified2 file is done.  It was found
+ * that when writing to an NFS mounted share that is using a soft mount option,
+ * writes sometimes fail and leave the unified2 file corrupted.  If the write
+ * to the newly created unified2 file fails, Snort will fatal error.
+ *
+ * In the case of interrupt errors, the write is retried, but only for a
+ * finite number of times.
+ *
+ * All other errors are treated as non-recoverable and Snort will fatal error.
+ *
+ * Upon successful completion of write, the length of the data written is
+ * added to the current amount of total data written thus far to the
+ * unified2 file.
+ *
+ * Arguments
+ *  uint8_t *
+ *      The buffer containing the data to write
+ *  uint32_t
+ *      The length of the data to write
+ *  Unified2Config *
+ *      A pointer to the unified2 configuration data
+ *
+ * Returns: None
+ *
+ ******************************************************************************/
+static void Unified2Write(uint8_t* buf, uint32_t buf_len, Unified2Config* config)
+{
+    size_t fwcount = 0;
+    int ffstatus = 0;
+
+    /* Nothing to write or nothing to write to */
+    if ((buf == NULL) || (config == NULL) || (u2.stream == NULL))
+        return;
+
+    /* Don't use fsync().  It is a total performance killer */
+    if (((fwcount = fwrite(buf, (size_t)buf_len, 1, u2.stream)) != 1) ||
+        ((ffstatus = fflush(u2.stream)) != 0))
+    {
+        /* errno is saved just to avoid other intervening calls
+         * (e.g. ErrorMessage) potentially resetting it to something else. */
+        int error = errno;
+        int max_retries = 3;
+
+        /* On iterations other than the first, the only non-zero error will be
+         * EINTR or interrupt.  Only iterate a maximum of max_retries times so
+         * there is no chance of infinite looping if for some reason the write
+         * is constantly interrupted */
+        while ((error != 0) && (max_retries != 0))
+        {
+            if (config->nostamp)
+            {
+                ErrorMessage("%s(%d) Failed to write to unified2 file (%s): %s\n",
+                    __FILE__, __LINE__, u2.filepath, get_error(error));
+            }
+            else
+            {
+                ErrorMessage("%s(%d) Failed to write to unified2 file (%s.%u): %s\n",
+                    __FILE__, __LINE__, u2.filepath,
+                    u2.timestamp, get_error(error));
+            }
+
+            while ((error == EINTR) && (max_retries != 0))
+            {
+                max_retries--;
+
+                /* Supposedly an interrupt can only occur before anything
+                 * has been written.  Try again */
+                ErrorMessage("%s(%d) Got interrupt. Retry write to unified2 "
+                    "file.\n", __FILE__, __LINE__);
+
+                if (fwcount != 1)
+                {
+                    /* fwrite() failed.  Redo fwrite and fflush */
+                    if (((fwcount = fwrite(buf, (size_t)buf_len, 1, u2.stream)) == 1) &&
+                        ((ffstatus = fflush(u2.stream)) == 0))
+                    {
+                        ErrorMessage("%s(%d) Write to unified2 file succeeded\n",
+                            __FILE__, __LINE__);
+                        error = 0;
+                        break;
+                    }
+                }
+                else if ((ffstatus = fflush(u2.stream)) == 0)
+                {
+                    ErrorMessage("%s(%d) Write to unified2 file succeeded\n",
+                        __FILE__, __LINE__);
+                    error = 0;
+                    break;
+                }
+
+                error = errno;
+
+                ErrorMessage("%s(%d) Retrying write to unified2 file failed.\n",
+                    __FILE__, __LINE__);
+            }
+
+            /* If we've reached the maximum number of interrupt retries,
+             * just bail out of the main while loop */
+            if (max_retries == 0)
+                continue;
+
+            switch (error)
+            {
+            case 0:
+                break;
+
+            case EIO:
+                ErrorMessage("%s(%d) Unified2 file is possibly corrupt. "
+                    "Closing this unified2 file and creating "
+                    "a new one.\n", __FILE__, __LINE__);
+
+                Unified2RotateFile(config);
+
+                if (config->nostamp)
+                {
+                    ErrorMessage("%s(%d) New unified2 file: %s\n",
+                        __FILE__, __LINE__, u2.filepath);
+                }
+                else
+                {
+                    ErrorMessage("%s(%d) New unified2 file: %s.%u\n",
+                        __FILE__, __LINE__,
+                        u2.filepath, u2.timestamp);
+                }
+
+                if (((fwcount = fwrite(buf, (size_t)buf_len, 1, u2.stream)) == 1) &&
+                    ((ffstatus = fflush(u2.stream)) == 0))
+                {
+                    ErrorMessage("%s(%d) Write to unified2 file succeeded\n",
+                        __FILE__, __LINE__);
+                    error = 0;
+                    break;
+                }
+
+                error = errno;
+
+                /* Loop again if interrupt */
+                if (error == EINTR)
+                    break;
+
+                /* Write out error message again, then fall through and fatal */
+                if (config->nostamp)
+                {
+                    ErrorMessage("%s(%d) Failed to write to unified2 file (%s): %s\n",
+                        __FILE__, __LINE__, u2.filepath, get_error(error));
+                }
+                else
+                {
+                    ErrorMessage("%s(%d) Failed to write to unified2 file (%s.%u): %s\n",
+                        __FILE__, __LINE__, u2.filepath,
+                        u2.timestamp, get_error(error));
+                }
+
+            /* Fall through */
+
+            case EAGAIN:      /* We're not in non-blocking mode */
+            case EBADF:
+            case EFAULT:
+            case EFBIG:
+            case EINVAL:
+            case ENOSPC:
+            case EPIPE:
+            default:
+                FatalError("%s(%d) Cannot write to device.\n", __FILE__, __LINE__);
+            }
+        }
+
+        if ((max_retries == 0) && (error != 0))
+        {
+            FatalError("%s(%d) Maximum number of interrupts exceeded. "
+                "Cannot write to device.\n", __FILE__, __LINE__);
+        }
+    }
+
+    u2.current += buf_len;
+}
+
+//-------------------------------------------------------------------------
+// unified2 module
+//-------------------------------------------------------------------------
+
+static const Parameter s_params[] =
+{
+    { "limit", Parameter::PT_INT, "0:", "0",
+      "set limit (0 is unlimited)" },
+
+    { "units", Parameter::PT_ENUM, "B | K | M | G", "B",
+      "limit multiplier" },
+
+    { "nostamp", Parameter::PT_BOOL, nullptr, "true",
+      "append file creation time to name (in Unix Epoch format)" },
+
+    { "mpls_event_types", Parameter::PT_BOOL, nullptr, "false",
+      "include mpls labels in events" },
+
+    { "vlan_event_types", Parameter::PT_BOOL, nullptr, "false",
+      "include vlan IDs in events" },
+
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#define s_help \
+    "output event and packet in unified2 format file"
+
+class U2Module : public Module
+{
+public:
+    U2Module() : Module(S_NAME, s_help, s_params) { }
+
+    bool set(const char*, Value&, SnortConfig*) override;
+    bool begin(const char*, int, SnortConfig*) override;
+    bool end(const char*, int, SnortConfig*) override;
+
+public:
+    unsigned limit;
+    unsigned units;
+    bool nostamp;
+    bool mpls;
+    bool vlan;
+};
+
+bool U2Module::set(const char*, Value& v, SnortConfig*)
+{
+    if ( v.is("limit") )
+        limit = v.get_long();
+
+    else if ( v.is("units") )
+        units = v.get_long();
+
+    else if ( v.is("nostamp") )
+        nostamp = v.get_bool();
+
+    else if ( v.is("mpls_event_types") )
+        mpls = v.get_bool();
+
+    else if ( v.is("vlan_event_types") )
+        vlan = v.get_bool();
+
+    else
+        return false;
+
+    return true;
+}
+
+bool U2Module::begin(const char*, int, SnortConfig*)
+{
+    limit = 0;
+    units = 0;
+    nostamp = SnortConfig::output_no_timestamp();
+    mpls = vlan = false;
+    return true;
+}
+
+bool U2Module::end(const char*, int, SnortConfig*)
+{
+    while ( units-- )
+        limit *= 1024;
+
+    return true;
+}
+
+//-------------------------------------------------------------------------
+// logger stuff
+//-------------------------------------------------------------------------
+
+class U2Logger : public Logger
+{
+public:
+    U2Logger(U2Module*);
+    ~U2Logger();
+
+    void open() override;
+    void close() override;
+
+    void alert(Packet*, const char* msg, const Event&) override;
+    void log(Packet*, const char* msg, Event*) override;
+
+private:
+    Unified2Config config;
+};
+
+U2Logger::U2Logger(U2Module* m)
+{
+    config.limit = m->limit;
+    config.nostamp = m->nostamp;
+    config.mpls_event_types = m->mpls;
+    config.vlan_event_types = m->vlan;
+}
+
+U2Logger::~U2Logger()
+{ }
+
+void U2Logger::open()
+{
+    int status;
+
+    std::string name;
+    get_instance_file(name, F_NAME);
+
+    status = SnortSnprintf(
+        u2.filepath, sizeof(u2.filepath), "%s", name.c_str());
+
+    if (status != SNORT_SNPRINTF_SUCCESS)
+    {
+        FatalError("%s(%d) Failed to copy unified2 file name\n",
+            __FILE__, __LINE__);
+    }
+#ifdef HAVE_DAQ_API
+    u2.base_proto = htonl(SFDAQ::get_base_protocol());
+#else
+    u2.base_proto = htonl(DLT_EN10MB);
+#endif
+
+    Unified2InitFile(&config);
+
+    Stream::reg_xtra_data_log(AlertExtraData, &config);
+}
+
+void U2Logger::close()
+{
+    if ( u2.stream )
+        fclose(u2.stream);
+}
+
+void U2Logger::alert(Packet* p, const char* msg, const Event& event)
+{
+    if (p->ptrs.ip_api.is_ip6())
+    {
+        _AlertIP6_v2(p, msg, &config, &event);
+
+        if (p->ptrs.ip_api.is_ip6())
+        {
+            const SfIp* ip = p->ptrs.ip_api.get_src();
+            _WriteExtraData(&config, event.event_id, event.ref_time.tv_sec,
+                (const uint8_t*) ip->get_ip6_ptr(), sizeof(struct in6_addr), EVENT_INFO_IPV6_SRC);
+            ip = p->ptrs.ip_api.get_dst();
+            _WriteExtraData(&config, event.event_id, event.ref_time.tv_sec,
+                (const uint8_t*) ip->get_ip6_ptr(), sizeof(struct in6_addr), EVENT_INFO_IPV6_DST);
+        }
+    }
+    else // ip4 or data
+    {
+        _AlertIP4_v2(p, msg, &config, &event);
+    }
+
+    if ( p->flow )
+        Stream::update_flow_alert(
+            p->flow, p, event.sig_info->gid, event.sig_info->sid,
+            event.event_id, event.ref_time.tv_sec);
+
+    if ( p->xtradata_mask )
+    {
+        LogFunction* log_funcs;
+        uint32_t max_count = Stream::get_xtra_data_map(log_funcs);
+
+        if ( max_count > 0 )
+            AlertExtraData(
+                p->flow, &config, log_funcs, max_count, p->xtradata_mask,
+                event.event_id, event.ref_time.tv_sec);
+    }
+}
+
+void U2Logger::log(Packet* p, const char* msg, Event* event)
+{
+    if (p)
+    {
+        if ( (p->packet_flags & PKT_REBUILT_STREAM) and !p->is_data() )
+        {
+            DebugMessage(DEBUG_LOG,
+                "[*] Reassembled packet, dumping stream packets\n");
+            // FIXIT-H replace with reassembled stream data and
+            // optionally the first captured packet
+            //_Unified2LogStreamAlert(p, msg, &config, event);
+        }
+        else
+        {
+            DebugMessage(DEBUG_LOG, "[*] Logging unified 2 packets...\n");
+            _Unified2LogPacketAlert(p, msg, &config, event);
+        }
+    }
+}
+
+//-------------------------------------------------------------------------
+// api stuff
+//-------------------------------------------------------------------------
+
+static Module* mod_ctor()
+{ return new U2Module; }
+
+static void mod_dtor(Module* m)
+{ delete m; }
+
+static Logger* u2_ctor(SnortConfig*, Module* mod)
+{ return new U2Logger((U2Module*)mod); }
+
+static void u2_dtor(Logger* p)
+{ delete p; }
+
+static LogApi u2_api
+{
+    {
+        PT_LOGGER,
+        sizeof(LogApi),
+        LOGAPI_VERSION,
+        0,
+        API_RESERVED,
+        API_OPTIONS,
+        S_NAME,
+        s_help,
+        mod_ctor,
+        mod_dtor
+    },
+    OUTPUT_TYPE_FLAG__LOG | OUTPUT_TYPE_FLAG__ALERT,
+    u2_ctor,
+    u2_dtor
+};
+
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+    &u2_api.base,
+    nullptr
+};
+
diff --git a/extra/src/loggers/unified2x/unified2x.h b/extra/src/loggers/unified2x/unified2x.h
new file mode 100644 (file)
index 0000000..003f537
--- /dev/null
@@ -0,0 +1,233 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2002-2013 Sourcefire, Inc.
+// Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+#ifndef UNIFIED2_H
+#define UNIFIED2_H
+
+#include <netinet/in.h>
+
+#include "protocols/protocol_ids.h"
+
+// SNORT DEFINES
+// Long time ago...
+#define UNIFIED2_EVENT               1
+
+// CURRENT
+#define UNIFIED2_PACKET              2
+#define UNIFIED2_BUFFER              3
+#define UNIFIED2_IDS_EVENT           7
+#define UNIFIED2_IDS_EVENT_IPV6      72
+#define UNIFIED2_IDS_EVENT_MPLS      99
+#define UNIFIED2_IDS_EVENT_IPV6_MPLS 100
+#define UNIFIED2_IDS_EVENT_VLAN      104
+#define UNIFIED2_IDS_EVENT_IPV6_VLAN 105
+#define UNIFIED2_EXTRA_DATA          110
+#define UNIFIED2_IDS_EVENT_APPSTAT   113
+
+#define MAX_EVENT_APPNAME_LEN        64
+
+/* Data structure used for serialization of Unified2 Records */
+typedef struct _Serial_Unified2_Header
+{
+    uint32_t type;
+    uint32_t length;
+} Serial_Unified2_Header;
+
+// UNIFIED2_IDS_EVENT_VLAN = type 104
+// comes from SFDC to EStreamer archive in serialized form with the extended header
+struct Unified2IDSEvent
+{
+    uint32_t sensor_id;
+    uint32_t event_id;
+    uint32_t event_second;
+    uint32_t event_microsecond;
+    uint32_t signature_id;
+    uint32_t generator_id;
+    uint32_t signature_revision;
+    uint32_t classification_id;
+    uint32_t priority_id;
+    uint32_t ip_source;
+    uint32_t ip_destination;
+    uint16_t sport_itype;
+    uint16_t dport_icode;
+    IpProtocol ip_proto;
+    uint8_t impact_flag; // overloads packet_action
+    uint8_t impact;
+    uint8_t blocked;
+    uint32_t mpls_label;
+    uint16_t vlanId;
+    uint16_t pad2; // Policy ID
+    char app_name[MAX_EVENT_APPNAME_LEN];
+};
+
+// UNIFIED2_IDS_EVENT_IPV6_VLAN = type 105
+typedef struct _Unified2IDSEventIPv6
+{
+    uint32_t sensor_id;
+    uint32_t event_id;
+    uint32_t event_second;
+    uint32_t event_microsecond;
+    uint32_t signature_id;
+    uint32_t generator_id;
+    uint32_t signature_revision;
+    uint32_t classification_id;
+    uint32_t priority_id;
+    struct in6_addr ip_source;
+    struct in6_addr ip_destination;
+    uint16_t sport_itype;
+    uint16_t dport_icode;
+    IpProtocol ip_proto;
+    uint8_t impact_flag;
+    uint8_t impact;
+    uint8_t blocked;
+    uint32_t mpls_label;
+    uint16_t vlanId;
+    uint16_t pad2; /*could be IPS Policy local id to support local sensor alerts*/
+    char app_name[MAX_EVENT_APPNAME_LEN];
+} Unified2IDSEventIPv6;
+
+// UNIFIED2_PACKET = type 2
+typedef struct _Serial_Unified2Packet
+{
+    uint32_t sensor_id;
+    uint32_t event_id;
+    uint32_t event_second;
+    uint32_t packet_second;
+    uint32_t packet_microsecond;
+    uint32_t linktype;
+    uint32_t packet_length;
+    uint8_t packet_data[4];
+} Serial_Unified2Packet;
+
+typedef struct _Unified2ExtraDataHdr
+{
+    uint32_t event_type;
+    uint32_t event_length;
+}Unified2ExtraDataHdr;
+
+// UNIFIED2_EXTRA_DATA - type 110
+typedef struct _SerialUnified2ExtraData
+{
+    uint32_t sensor_id;
+    uint32_t event_id;
+    uint32_t event_second;
+    uint32_t type;              /* EventInfo */
+    uint32_t data_type;         /*EventDataType */
+    uint32_t blob_length;       /* Length of the data + sizeof(blob_length) + sizeof(data_type)*/
+} SerialUnified2ExtraData;
+
+typedef struct _Data_Blob
+{
+    uint32_t length;
+    const uint8_t* data;
+} Data_Blob;
+
+// UNIFIED2_EXTRA_DATA - type 110
+typedef struct _Serial_Unified2ExtraData
+{
+    uint32_t sensor_id;
+    uint32_t event_id;
+    uint32_t event_second;
+    uint32_t type;
+    Data_Blob data;
+} Unified2ExtraData;
+
+typedef enum _EventInfoEnum
+{
+    EVENT_INFO_XFF_IPV4 = 1,
+    EVENT_INFO_XFF_IPV6,
+    EVENT_INFO_REVIEWED_BY,
+    EVENT_INFO_GZIP_DATA,
+    EVENT_INFO_SMTP_FILENAME,
+    EVENT_INFO_SMTP_MAILFROM,
+    EVENT_INFO_SMTP_RCPTTO,
+    EVENT_INFO_SMTP_EMAIL_HDRS,
+    EVENT_INFO_HTTP_URI,
+    EVENT_INFO_HTTP_HOSTNAME,
+    EVENT_INFO_IPV6_SRC,
+    EVENT_INFO_IPV6_DST,
+    EVENT_INFO_JSNORM_DATA
+}EventInfoEnum;
+
+typedef enum _EventDataType
+{
+    EVENT_DATA_TYPE_BLOB = 1,
+    EVENT_DATA_TYPE_MAX
+}EventDataType;
+
+#define EVENT_TYPE_EXTRA_DATA   4
+
+#define MAX_XFF_WRITE_BUF_LENGTH \
+    (sizeof(Serial_Unified2_Header) + \
+    sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData) \
+    + sizeof(struct in6_addr))
+
+#define Serial_Unified2IDSEvent Unified2IDSEvent
+#define Serial_Unified2IDSEventIPv6 Unified2IDSEventIPv6
+
+//---------------LEGACY, type '7'
+// These structures are not used anymore in the product
+typedef struct _Serial_Unified2IDSEvent_legacy
+{
+    uint32_t sensor_id;
+    uint32_t event_id;
+    uint32_t event_second;
+    uint32_t event_microsecond;
+    uint32_t signature_id;
+    uint32_t generator_id;
+    uint32_t signature_revision;
+    uint32_t classification_id;
+    uint32_t priority_id;
+    uint32_t ip_source;
+    uint32_t ip_destination;
+    uint16_t sport_itype;
+    uint16_t dport_icode;
+    IpProtocol ip_proto;
+    uint8_t impact_flag; // sets packet_action
+    uint8_t impact;
+    uint8_t blocked;
+} Serial_Unified2IDSEvent_legacy;
+
+//----------LEGACY, type '72'
+typedef struct _Serial_Unified2IDSEventIPv6_legacy
+{
+    uint32_t sensor_id;
+    uint32_t event_id;
+    uint32_t event_second;
+    uint32_t event_microsecond;
+    uint32_t signature_id;
+    uint32_t generator_id;
+    uint32_t signature_revision;
+    uint32_t classification_id;
+    uint32_t priority_id;
+    struct in6_addr ip_source;
+    struct in6_addr ip_destination;
+    uint16_t sport_itype;
+    uint16_t dport_icode;
+    IpProtocol ip_proto;
+    uint8_t impact_flag;
+    uint8_t impact;
+    uint8_t blocked;
+} Serial_Unified2IDSEventIPv6_legacy;
+
+////////////////////-->LEGACY
+
+#endif
+
index 969defee2978eb7c328c88a318d77aed157e3e3a..068b8c1546881128712518b80fd2f27cfcd7381e 100644 (file)
@@ -1,6 +1,7 @@
 
 set (LOG_INCLUDES
     messages.h
+    obfuscator.h
     text_log.h
     unified2.h
 )
@@ -13,7 +14,6 @@ add_library ( log STATIC
     log_text.h
     messages.cc
     obfuscator.cc
-    obfuscator.h
     packet_tracer.cc
     packet_tracer.h
     text_log.cc
index 7fa028aeca543b33a58f4244e7e06bc29282e1f3..a3ec813a2b979b84e049a5a49dde59d5974e095f 100644 (file)
@@ -5,6 +5,7 @@ x_includedir = $(pkgincludedir)/log
 
 x_include_HEADERS = \
 messages.h \
+obfuscator.h \
 text_log.h \
 unified2.h
 
@@ -15,7 +16,6 @@ log_text.cc \
 log_text.h \
 messages.cc \
 obfuscator.cc \
-obfuscator.h \
 packet_tracer.cc \
 packet_tracer.h \
 text_log.cc
index c0ae8d08e4a9dad9c673b4a1de2df2a14564f89c..d127534b9924b9dc71857a56a2de0d41386b174c 100644 (file)
@@ -25,6 +25,8 @@
 #include <cstdint>
 #include <set>
 
+#include "main/snort_types.h"
+
 struct ObfuscatorBlock
 {
     // Only used by `class Obfuscator`
@@ -40,7 +42,7 @@ struct ObfuscatorBlock
     size_t length;
 };
 
-class Obfuscator
+class SO_PUBLIC Obfuscator
 {
 public:
     struct BlockCompare
index 2eeecef790bb767b2b851913936a29dbe9c4f2c1..e86f862aee64358775b4a1c2bc3d19f5e0cffc9a 100644 (file)
@@ -127,7 +127,7 @@ NORETURN void help_usage(SnortConfig*, const char* s)
     fprintf(stdout, "    %s [-options] -c conf [-T]: validate conf\n", s);
     fprintf(stdout, "    %s [-options] -c conf -i iface: process live\n", s);
     fprintf(stdout, "    %s [-options] -c conf -r pcap: process readback\n", s);
-    exit(1);
+    exit(0);
 }
 
 NORETURN void help_options(SnortConfig*, const char* val)
@@ -144,9 +144,9 @@ NORETURN void help_signals(SnortConfig*, const char*)
 
 enum HelpType
 {
-    HT_CFG, HT_CMD, HT_GID, HT_IPS, HT_MOD,
-    HT_BUF, HT_LST, HT_PLG, HT_DDR, HT_DBR,
-    HT_HMO, HT_HPL, HT_DFL, HT_PEG
+    HT_BUF, HT_CFG, HT_CMD, HT_DBR, HT_DDR,
+    HT_DMM, HT_GID, HT_HMO, HT_HPL, HT_DFL,
+    HT_IPS, HT_LST, HT_MOD, HT_PEG, HT_PLG
 };
 
 NORETURN static void show_help(SnortConfig* sc, const char* val, HelpType ht)
@@ -158,35 +158,29 @@ NORETURN static void show_help(SnortConfig* sc, const char* val, HelpType ht)
 
     switch ( ht )
     {
+    case HT_BUF:
+        InspectorManager::dump_buffers();
+        break;
     case HT_CFG:
         ModuleManager::show_configs(val);
         break;
     case HT_CMD:
         ModuleManager::show_commands(val);
         break;
-    case HT_GID:
-        ModuleManager::show_gids(val);
-        break;
-    case HT_IPS:
-        ModuleManager::show_rules(val);
-        break;
-    case HT_MOD:
-        ModuleManager::show_module(val);
-        break;
-    case HT_BUF:
-        InspectorManager::dump_buffers();
-        break;
-    case HT_LST:
-        ModuleManager::list_modules(val);
-        break;
-    case HT_PLG:
-        PluginManager::list_plugins();
+    case HT_DBR:
+        ModuleManager::dump_rules(val);
         break;
     case HT_DDR:
         SoManager::dump_rule_stubs(val);
         break;
-    case HT_DBR:
-        ModuleManager::dump_rules(val);
+    case HT_DFL:
+        ModuleManager::dump_defaults(val);
+        break;
+    case HT_DMM:
+        ModuleManager::dump_msg_map(val);
+        break;
+    case HT_GID:
+        ModuleManager::show_gids(val);
         break;
     case HT_HMO:
         ModuleManager::show_modules();
@@ -194,12 +188,21 @@ NORETURN static void show_help(SnortConfig* sc, const char* val, HelpType ht)
     case HT_HPL:
         PluginManager::show_plugins();
         break;
-    case HT_DFL:
-        ModuleManager::dump_defaults(val);
+    case HT_IPS:
+        ModuleManager::show_rules(val);
+        break;
+    case HT_LST:
+        ModuleManager::list_modules(val);
+        break;
+    case HT_MOD:
+        ModuleManager::show_module(val);
         break;
     case HT_PEG:
         ModuleManager::show_pegs(val);
         break;
+    case HT_PLG:
+        PluginManager::list_plugins();
+        break;
     }
     ModuleManager::term();
     PluginManager::release_plugins();
@@ -238,6 +241,11 @@ NORETURN void help_builtin(SnortConfig* sc, const char* val)
     show_help(sc, val, HT_IPS);
 }
 
+NORETURN void help_counts(SnortConfig* sc, const char* val)
+{
+    show_help(sc, val, HT_PEG);
+}
+
 NORETURN void help_module(SnortConfig* sc, const char* val)
 {
     show_help(sc, val, HT_MOD);
@@ -253,6 +261,26 @@ NORETURN void help_plugins(SnortConfig* sc, const char* val)
     show_help(sc, val, HT_HPL);
 }
 
+NORETURN void help_version(SnortConfig*)
+{
+    DisplayBanner();
+    exit(0);
+}
+
+NORETURN void list_daqs(SnortConfig* sc)
+{
+    SFDAQ::load(sc);
+    SFDAQ::print_types(cout);
+    SFDAQ::unload();
+    exit(0);
+}
+
+NORETURN void list_interfaces(SnortConfig*)
+{
+    PrintAllInterfaces();
+    exit(0);
+}
+
 NORETURN void list_modules(SnortConfig* sc, const char* val)
 {
     show_help(sc, val, HT_LST);
@@ -278,9 +306,9 @@ NORETURN void dump_dynamic_rules(SnortConfig* sc, const char* val)
     show_help(sc, val, HT_DDR);
 }
 
-NORETURN void help_counts(SnortConfig* sc, const char* val)
+NORETURN void dump_msg_map(SnortConfig* sc, const char* val)
 {
-    show_help(sc, val, HT_PEG);
+    show_help(sc, val, HT_DMM);
 }
 
 NORETURN void dump_rule_hex(SnortConfig*, const char* val)
@@ -301,23 +329,3 @@ NORETURN void dump_version(SnortConfig*)
     exit(0);
 }
 
-NORETURN void help_version(SnortConfig*)
-{
-    DisplayBanner();
-    exit(0);
-}
-
-NORETURN void list_interfaces(SnortConfig*)
-{
-    PrintAllInterfaces();
-    exit(0);
-}
-
-NORETURN void list_daqs(SnortConfig* sc)
-{
-    SFDAQ::load(sc);
-    SFDAQ::print_types(cout);
-    SFDAQ::unload();
-    exit(0);
-}
-
index 323053a820611a962f08fe4c2904e9ea37d19602..2f249b01c194fc333333b45a77c906c3b9a40def 100644 (file)
@@ -51,6 +51,7 @@ void list_daqs(SnortConfig* sc);
 void dump_defaults(SnortConfig* sc, const char*);
 void dump_builtin_rules(SnortConfig* sc, const char*);
 void dump_dynamic_rules(SnortConfig* sc, const char*);
+void dump_msg_map(SnortConfig* sc, const char*);
 void dump_rule_hex(SnortConfig* sc, const char*);
 void dump_rule_text(SnortConfig* sc, const char*);
 void dump_version(SnortConfig* sc);
index afdbfd8b25fa90bd933642fb39c14ee6430a52af..fcb83a1badeeb015f33635bc5a6785e0ea6dbc3d 100644 (file)
@@ -276,7 +276,7 @@ static const Parameter s_params[] =
     { "--dirty-pig", Parameter::PT_IMPLIED, nullptr, nullptr,
       "don't flush packets on shutdown" },
 
-    { "--dump-builtin-rules", Parameter::PT_IMPLIED, nullptr, nullptr,
+    { "--dump-builtin-rules", Parameter::PT_STRING, "(optional)", nullptr,
       "[<module prefix>] output stub rules for selected modules" },
 
     // FIXIT-L add --list-dynamic-rules like --list-builtin-rules
@@ -292,6 +292,9 @@ static const Parameter s_params[] =
     { "--enable-inline-test", Parameter::PT_IMPLIED, nullptr, nullptr,
       "enable Inline-Test Mode Operation" },
 
+    { "--gen-msg-map", Parameter::PT_IMPLIED, nullptr, nullptr,
+      "dump builtin rules in gen-msg.map format for use by other tools" },
+
     { "--help", Parameter::PT_IMPLIED, nullptr, nullptr,
       "list command line options" },
 
@@ -311,7 +314,7 @@ static const Parameter s_params[] =
       "list all available modules with brief help" },
 
     { "--help-options", Parameter::PT_STRING, "(optional)", nullptr,
-      "<option prefix> output matching command line option quick help (same as -?)" },
+      "[<option prefix>] output matching command line option quick help (same as -?)" },
 
     { "--help-plugins", Parameter::PT_IMPLIED, nullptr, nullptr,
       "list all available plugins with brief help" },
@@ -329,7 +332,7 @@ static const Parameter s_params[] =
       "output available inspection buffers" },
 
     { "--list-builtin", Parameter::PT_STRING, "(optional)", nullptr,
-      "<module prefix> output matching builtin rules" },
+      "[<module prefix>] output matching builtin rules" },
 
     { "--list-gids", Parameter::PT_STRING, "(optional)", nullptr,
       "[<module prefix>] output matching generators" },
@@ -721,6 +724,9 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc)
     else if ( v.is("--enable-inline-test") )
         sc->run_flags |= RUN_FLAG__INLINE_TEST;
 
+    else if ( v.is("--gen-msg-map") )
+        dump_msg_map(sc, v.get_string());
+
     else if ( v.is("--help") )
         help_basic(sc, v.get_string());
 
index 993087c9d6d6c17089ccd7810f16b6fd737d85da..49eebe3e5cfff7f90476ce739d4f98787346f769 100644 (file)
@@ -1260,6 +1260,39 @@ void ModuleManager::dump_rules(const char* pfx)
         cout << "no match" << endl;
 }
 
+void ModuleManager::dump_msg_map(const char* pfx)
+{
+    s_modules.sort(comp_gids);
+    unsigned len = pfx ? strlen(pfx) : 0;
+    unsigned c = 0;
+
+    for ( auto p : s_modules )
+    {
+        const Module* m = p->mod;
+
+        if ( pfx && strncmp(m->get_name(), pfx, len) )
+            continue;
+
+        const RuleMap* r = m->get_rules();
+
+        if ( !r )
+            continue;
+
+        unsigned gid = m->get_gid();
+
+        while ( r->msg )
+        {
+            cout << gid << " || " << r->sid << " || ";
+            cout << m->get_name() << ": ";
+            cout << r->msg << endl;
+            r++;
+        }
+        c++;
+    }
+    if ( !c )
+        cout << "no match" << endl;
+}
+
 void ModuleManager::dump_stats(SnortConfig*, const char* skip)
 {
     for ( auto p : s_modules )
index 60007fd93225181b1449802a943b2314fd9443e4..19d0fc00499f086ae59b1d2d241cd543c5ea078e 100644 (file)
@@ -58,6 +58,7 @@ public:
     static void show_pegs(const char* = nullptr, bool exact = false);
     static void show_rules(const char* = nullptr, bool exact = false);
 
+    static void dump_msg_map(const char* = nullptr);
     static void dump_rules(const char* = nullptr);
     static void dump_defaults(const char* = nullptr);