]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1659 in SNORT/snort3 from ~MDAGON/snort3:hpack_int to master
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 2 Jul 2019 17:24:36 +0000 (13:24 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 2 Jul 2019 17:24:36 +0000 (13:24 -0400)
Squashed commit of the following:

commit 1aa88db8a750eb3efc4a66b0483cb515a60d613e
Author: mdagon <mdagon@cisco.com>
Date:   Thu Jun 20 16:42:53 2019 -0400

    http2: decode HPACK uint

21 files changed:
src/service_inspectors/http2_inspect/CMakeLists.txt
src/service_inspectors/http2_inspect/http2_enum.h
src/service_inspectors/http2_inspect/http2_hpack_decode.cc [new file with mode: 0644]
src/service_inspectors/http2_inspect/http2_hpack_decode.h [new file with mode: 0644]
src/service_inspectors/http2_inspect/http2_tables.cc
src/service_inspectors/http2_inspect/test/CMakeLists.txt
src/service_inspectors/http2_inspect/test/http2_hpack_decode_test.cc [new file with mode: 0644]
src/service_inspectors/http_inspect/CMakeLists.txt
src/service_inspectors/http_inspect/http_cutter.h
src/service_inspectors/http_inspect/http_event.h [moved from src/service_inspectors/http_inspect/http_event_gen.h with 64% similarity]
src/service_inspectors/http_inspect/http_flow_data.h
src/service_inspectors/http_inspect/http_header_normalizer.h
src/service_inspectors/http_inspect/http_js_norm.h
src/service_inspectors/http_inspect/http_normalizers.h
src/service_inspectors/http_inspect/http_transaction.cc
src/service_inspectors/http_inspect/http_transaction.h
src/service_inspectors/http_inspect/http_uri.h
src/service_inspectors/http_inspect/http_uri_norm.h
src/utils/CMakeLists.txt
src/utils/event_gen.h [new file with mode: 0644]
src/utils/infractions.h [moved from src/service_inspectors/http_inspect/http_infractions.h with 77% similarity]

index 84d7b8f8a48101cd669adbdf77dae654881d30f5..90b40758f8ff053c2605e14dee78f48f462972b5 100644 (file)
@@ -5,6 +5,8 @@ set (FILE_LIST
     http2_enum.h
     http2_flow_data.cc
     http2_flow_data.h
+    http2_hpack_decode.cc
+    http2_hpack_decode.h
     http2_inspect.cc
     http2_inspect_impl.cc
     http2_inspect.h
index ae0c26fa45f9e2bd68276a73ea974478e73015b7..a1fc4ca1de25650fb1c77567d97a39a7620c9910 100644 (file)
@@ -49,9 +49,22 @@ enum PEG_COUNT { PEG_CONCURRENT_SESSIONS = 0, PEG_MAX_CONCURRENT_SESSIONS, PEG_F
 enum EventSid
 {
     EVENT__NONE = -1,
+    EVENT_INT_DECODE_FAILURE = 1,
+    EVENT_INT_LEADING_ZEROS = 2,
     EVENT__MAX_VALUE
 };
 
+// All the infractions we might find while parsing and analyzing a message
+enum Infraction
+{
+    INF__NONE = -1,
+    INF_INT_EMPTY_BUFF = 0,
+    INF_INT_MISSING_BYTES = 1,
+    INF_INT_OVERFLOW = 2,
+    INF_INT_LEADING_ZEROS = 3,
+    INF__MAX_VALUE
+};    
 } // end namespace Http2Enums
 
 #endif
diff --git a/src/service_inspectors/http2_inspect/http2_hpack_decode.cc b/src/service_inspectors/http2_inspect/http2_hpack_decode.cc
new file mode 100644 (file)
index 0000000..e723012
--- /dev/null
@@ -0,0 +1,101 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+// http2_hpack_decode.cc author Maya Dagon <mdagon@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "http2_hpack_decode.h"
+
+#include "http2_enum.h"
+
+using namespace Http2Enums;
+
+static const uint8_t VAL_MASK = 0x7F;
+static const uint8_t FLAG_BIT = 0x80;
+
+Http2HpackIntDecode::Http2HpackIntDecode(uint8_t prefix, Http2EventGen* events,
+    Http2Infractions* infractions) : prefix_mask(((uint16_t)1 << prefix) - 1), events(events),
+    infractions(infractions)
+{
+    assert ((0 < prefix) && (prefix < 9));
+}
+
+bool Http2HpackIntDecode::translate(const Field& msg, int32_t& bytes_consumed, uint64_t& result)
+{
+    bytes_consumed = 0;
+    result = 0;
+
+    if (bytes_consumed >= msg.length())
+    {
+        *infractions += INF_INT_EMPTY_BUFF;
+        events->create_event(EVENT_INT_DECODE_FAILURE);
+        return false;
+    }
+
+    const uint8_t* buff = msg.start();
+    const uint8_t prefix_val = buff[bytes_consumed++] & prefix_mask;
+
+    if (prefix_val < prefix_mask)
+    {
+        result = prefix_val;
+        return true;
+    }
+
+    uint8_t byte = 0;
+    for (uint8_t multiplier = 0; multiplier < 64; multiplier += 7)
+    {
+        if (bytes_consumed >= msg.length())
+        {
+            *infractions += INF_INT_MISSING_BYTES;
+            events->create_event(EVENT_INT_DECODE_FAILURE);
+            return false;
+        }
+        byte = buff[bytes_consumed++];
+
+        // For multiplier == 63, do overflow checks
+        if (multiplier == 63)
+        {
+            if (((byte & FLAG_BIT) != 0) || ((byte & VAL_MASK) > 1) ||
+                ((result + ((uint64_t)(byte & VAL_MASK) << multiplier) + prefix_mask) < result))
+            {
+                *infractions += INF_INT_OVERFLOW;
+                events->create_event(EVENT_INT_DECODE_FAILURE);
+                return false;
+            }
+        }
+
+        result += (uint64_t)(byte & VAL_MASK) << multiplier;
+
+        if ((byte & FLAG_BIT) == 0)
+            break;
+    }
+
+    // Alert on leading 0s, allow for value 2^N-1
+    if (((byte & VAL_MASK) == 0) && (bytes_consumed != 2))
+    {
+        *infractions += INF_INT_LEADING_ZEROS;
+        events->create_event(EVENT_INT_LEADING_ZEROS);
+    }
+
+    result += prefix_mask;
+
+    return true;
+}
+
diff --git a/src/service_inspectors/http2_inspect/http2_hpack_decode.h b/src/service_inspectors/http2_inspect/http2_hpack_decode.h
new file mode 100644 (file)
index 0000000..bc22111
--- /dev/null
@@ -0,0 +1,47 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+// http2_hpack_decode.h author Maya Dagon <mdagon@cisco.com>
+
+#ifndef HTTP2_HPACK_DECODE_H
+#define HTTP2_HPACK_DECODE_H
+
+#include "http2_enum.h"
+#include "main/snort_types.h"
+#include "service_inspectors/http_inspect/http_field.h"
+#include "utils/event_gen.h"
+#include "utils/infractions.h"
+
+using Http2Infractions = Infractions<Http2Enums::INF__MAX_VALUE, Http2Enums::INF__NONE>;
+
+using Http2EventGen = EventGen<Http2Enums::EVENT__MAX_VALUE, Http2Enums::EVENT__NONE,
+    Http2Enums::HTTP2_GID>;
+
+class Http2HpackIntDecode
+{
+public:
+    Http2HpackIntDecode(uint8_t prefix, Http2EventGen* events, Http2Infractions* infractions);
+    bool translate(const Field& msg, int32_t& bytes_consumed, uint64_t& result);
+
+private:
+    const uint8_t prefix_mask;
+    Http2EventGen* const events;
+    Http2Infractions* const infractions;
+};
+
+#endif
+
index e765bb84e3cffdc20bd7017c019c54a67e454425..cb52a679552fea95f2eed07c61cbc5c0373e229d 100644 (file)
@@ -30,6 +30,8 @@ using namespace Http2Enums;
 
 const snort::RuleMap Http2Module::http2_events[] =
 {
+    { EVENT_INT_DECODE_FAILURE, "Failed to decode integer value" },
+    { EVENT_INT_LEADING_ZEROS, "Integer value has leading zeros" },
     { 0, nullptr }
 };
 
index 017e0287eb9d82e1f5a48b0d9b87c8b9c25c6070..6402e3e660adfffb915db005199841852c68ec45 100644 (file)
@@ -14,4 +14,7 @@ add_cpputest( http2_stream_splitter_impl_test
         ../http2_tables.cc
         ../../../framework/module.cc
 )
-
+add_cpputest( http2_hpack_decode_test
+    SOURCES
+        ../http2_hpack_decode.cc
+)
diff --git a/src/service_inspectors/http2_inspect/test/http2_hpack_decode_test.cc b/src/service_inspectors/http2_inspect/test/http2_hpack_decode_test.cc
new file mode 100644 (file)
index 0000000..facce5e
--- /dev/null
@@ -0,0 +1,348 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+
+// http2_hpack_decode_test.cc author Maya Dagon <mdagon@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../http2_enum.h"
+#include "../http2_hpack_decode.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+namespace snort
+{
+// Stubs whose sole purpose is to make the test code link
+int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
+}
+
+using namespace Http2Enums;
+
+
+//
+// The following tests should result in a successful decode, no infractions/events
+//
+TEST_GROUP(http2_hpack_decode_success)
+{
+    Http2EventGen events;
+    Http2Infractions inf;
+    Http2HpackIntDecode* const decode = new Http2HpackIntDecode(5, &events, &inf);
+
+    void teardown() override
+    {
+        CHECK(inf.none_found() == true);
+        CHECK(events.none_found() == true);
+        delete decode;
+    }
+};
+
+TEST(http2_hpack_decode_success, 10_using_5_bits)
+{
+    // prepare field to decode - example from RFC 7541 c.1.1
+    uint8_t buf = 10;
+    Field f(1, &buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode->translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 10);
+    CHECK(bytes_processed == 1);
+}
+
+TEST(http2_hpack_decode_success, 10_using_5_bits_wtail)
+{
+    // prepare field to decode - same as above with an extra byte as leftover
+    uint8_t buf[2] = { 10, 0xff };
+    Field f(2, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode->translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 10);
+    CHECK(bytes_processed == 1);
+}
+
+TEST(http2_hpack_decode_success, 1337_using_5_bits)
+{
+    // prepare field to decode - example from RFC 7541 c.1.2
+    uint8_t buf[3] = { 31, 0x9a, 10 };
+    Field f(3, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode->translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 1337);
+    CHECK(bytes_processed == 3);
+}
+
+TEST(http2_hpack_decode_success, 42_using_8_bits)
+{
+    // prepare decode object  
+    Http2HpackIntDecode decode_8(8, &events, &inf);
+    // prepare field to decode - example from RFC 7541 c.1.3
+    uint8_t buf = 42;
+    Field f(1, &buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode_8.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 42);
+    CHECK(bytes_processed == 1);
+}
+
+TEST(http2_hpack_decode_success, max_val_using_5_bit)
+{
+    // prepare field to decode - 2^64-1
+    uint8_t buf[11] = { 31, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1};
+    Field f(11, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode->translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 0xFFFFFFFFFFFFFFFF);
+    CHECK(bytes_processed == 11);
+}
+
+TEST(http2_hpack_decode_success, 31_using_5_bits)
+{ 
+    // prepare field to decode - 2^N -1
+    uint8_t buf[2] = {31, 0};
+    Field f(2, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode->translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 31);
+    CHECK(bytes_processed == 2);
+}
+
+TEST(http2_hpack_decode_success, 0_using_5_bits)
+{ 
+    // prepare field to decode - 0 using 5 bits
+    uint8_t buf = 0;
+    Field f(1, &buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode->translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 0);
+    CHECK(bytes_processed == 1);
+}
+
+
+//
+// The following tests should result in a failure and set infractions/events
+//
+TEST_GROUP(http2_hpack_decode_failure)
+{
+};
+
+TEST(http2_hpack_decode_failure, 0_len_field)
+{
+    // prepare decode object  
+    Http2EventGen local_events;
+    Http2Infractions local_inf;
+    Http2HpackIntDecode decode_8(8, &local_events, &local_inf);
+    // prepare field to decode - use field length 0
+    uint8_t buf = 42;
+    Field f(0, &buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode_8.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == false);
+    CHECK(bytes_processed == 0);
+    CHECK(local_inf.get_raw() == (1<<INF_INT_EMPTY_BUFF));
+    CHECK(local_events.get_raw() == (1<<(EVENT_INT_DECODE_FAILURE-1)));
+}
+
+TEST(http2_hpack_decode_failure, too_short)
+{
+    // prepare decode object  
+    Http2EventGen local_events;
+    Http2Infractions local_inf;
+    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    // prepare field to decode - buffer ends before decode finished
+    uint8_t buf[3] = { 31, 0x9a, 10 };
+    Field f(2, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = local_decode.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == false);
+    CHECK(bytes_processed == 2);
+    CHECK(local_inf.get_raw() == (1<<INF_INT_MISSING_BYTES));
+    CHECK(local_events.get_raw() == (1<<(EVENT_INT_DECODE_FAILURE-1)));
+}
+
+TEST(http2_hpack_decode_failure, multiplier_bigger_than_63)
+{
+    // prepare decode object
+    Http2EventGen local_events;
+    Http2Infractions local_inf;
+    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    // prepare field to decode - multiplier > 63
+    uint8_t buf[13] = { 31, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 1 };
+    Field f(13, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = local_decode.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == false);
+    CHECK(bytes_processed == 11);
+    CHECK(local_inf.get_raw() == (1<<INF_INT_OVERFLOW));
+    CHECK(local_events.get_raw() == (1<<(EVENT_INT_DECODE_FAILURE-1)));
+}
+
+TEST(http2_hpack_decode_failure, add_val_overflow)
+{
+    // prepare decode object    
+    Http2EventGen local_events;
+    Http2Infractions local_inf;
+    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    // prepare field to decode - value to add itself is already creating overflow
+    uint8_t buf[12] = { 31, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 1 };
+    Field f(12, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = local_decode.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == false);
+    CHECK(bytes_processed == 11);
+    CHECK(local_inf.get_raw() == (1<<INF_INT_OVERFLOW));
+    CHECK(local_events.get_raw() == (1<<(EVENT_INT_DECODE_FAILURE-1)));
+}
+
+TEST(http2_hpack_decode_failure, add_val_overflow2)
+{
+    // prepare decode object    
+    Http2EventGen local_events;
+    Http2Infractions local_inf;
+    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    // prepare field to decode - adding value to result kept so far creates overflow
+    uint8_t buf[11] = { 31, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1};
+    Field f(11, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = local_decode.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == false);
+    CHECK(bytes_processed == 11);
+    CHECK(local_inf.get_raw() == (1<<INF_INT_OVERFLOW));
+    CHECK(local_events.get_raw() == (1<<(EVENT_INT_DECODE_FAILURE-1)));
+}
+
+TEST(http2_hpack_decode_failure, 2_64_using_5_bit)
+{
+    // prepare decode object    
+    Http2EventGen local_events;
+    Http2Infractions local_inf;
+    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    // prepare field to decode - 2^64
+    uint8_t buf[11] = { 31, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1};
+    Field f(11, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = local_decode.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == false);
+    CHECK(bytes_processed == 11);
+    CHECK(local_inf.get_raw() == (1<<INF_INT_OVERFLOW));
+    CHECK(local_events.get_raw() == (1<<(EVENT_INT_DECODE_FAILURE-1)));
+}
+
+
+//
+// The following tests should result in a successful decode and set
+// leading zeros infraction and event
+//
+TEST_GROUP(http2_hpack_decode_leading_zeros)
+{
+};
+
+TEST(http2_hpack_decode_leading_zeros, leading_zeros)
+{
+    // prepare decode object    
+    Http2EventGen local_events;
+    Http2Infractions local_inf;
+    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    // prepare field to decode - MSB is zero
+    uint8_t buf[3] = { 31, 0x80, 0};
+    Field f(3, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = local_decode.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 31);
+    CHECK(bytes_processed == 3);
+    CHECK(local_inf.get_raw() == (1<<INF_INT_LEADING_ZEROS));
+    CHECK(local_events.get_raw() == (1<<(EVENT_INT_LEADING_ZEROS-1)));
+}
+
+TEST(http2_hpack_decode_leading_zeros, leading_0_byte_11)
+{
+    // prepare decode object    
+    Http2EventGen local_events;
+    Http2Infractions local_inf;
+    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    // prepare field to decode - multiplier 63 doesn't create overflow, should alert on
+    // leading 0
+    uint8_t buf[11] = { 31, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0};
+    Field f(11, buf, false);
+    // decode
+    int32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = local_decode.translate(f, bytes_processed, res);
+    // check results
+    CHECK(success == true);
+    CHECK(res == 0x7FFFFFFFFFFFFFFF);
+    CHECK(bytes_processed == 11);
+    CHECK(local_inf.get_raw() == (1<<INF_INT_LEADING_ZEROS));
+    CHECK(local_events.get_raw() == (1<<(EVENT_INT_LEADING_ZEROS-1)));
+}
+
+int main(int argc, char** argv)
+{
+    return CommandLineTestRunner::RunAllTests(argc, argv);
+}
index 2950654703ed87c368368b6b8b5f2ddbdf59d5fd..d1918aebbeb1df9fdd25ef0d8c1954e83838ba31 100644 (file)
@@ -61,8 +61,7 @@ set (FILE_LIST
     http_stream_splitter.h
     http_cutter.cc
     http_cutter.h
-    http_infractions.h
-    http_event_gen.h
+    http_event.h
     http_js_norm.cc
     http_js_norm.h
 )
index 6f4313299c9bcf8090bdf8653807753f8758017e..dcdba544b17e2739d7d772faa00fed5ae7ae1c49 100644 (file)
@@ -23,8 +23,7 @@
 #include <cassert>
 
 #include "http_enum.h"
-#include "http_event_gen.h"
-#include "http_infractions.h"
+#include "http_event.h"
 
 //-------------------------------------------------------------------------
 // HttpCutter class and subclasses
similarity index 64%
rename from src/service_inspectors/http_inspect/http_event_gen.h
rename to src/service_inspectors/http_inspect/http_event.h
index 60bb96201d49c308f096fe7d5158fb03a6c633fa..f5c33c718e32d5ba0e6535d906d36f81e5c2ced0 100644 (file)
 // with this program; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
-// http_event_gen.h author Tom Peters <thopeter@cisco.com>
+// http_event.h author Tom Peters <thopeter@cisco.com>
 
-#ifndef HTTP_EVENT_GEN_H
-#define HTTP_EVENT_GEN_H
+#ifndef HTTP_EVENT_H
+#define HTTP_EVENT_H
 
 #include <bitset>
-#include <cassert>
 
-#include "detection/detection_engine.h"
 #include "events/event_queue.h"
+#include "utils/event_gen.h"
+#include "utils/infractions.h"
 #include "utils/util_cstring.h"
 
 #include "http_enum.h"
 
 //-------------------------------------------------------------------------
-// Event generator class
+// HTTP Event generator class
 //-------------------------------------------------------------------------
 
-class HttpEventGen
+class HttpEventGen : public EventGen<HttpEnums::EVENT__MAX_VALUE, HttpEnums::EVENT__NONE,
+        HttpEnums::HTTP_GID>
 {
 public:
-    virtual ~HttpEventGen() = default;
-
-    virtual void create_event(int sid)
-    {
-        if (sid == HttpEnums::EVENT__NONE)
-            return;
-        assert((sid > 0) && (sid <= MAX));
-        if (!events_generated[sid-1])
-        {
-            snort::DetectionEngine::queue_event(HttpEnums::HTTP_GID, (uint32_t)sid);
-            events_generated[sid-1] = true;
-        }
-    }
-
     void generate_misformatted_http(const uint8_t* buffer, uint32_t length)
     {
         if ( snort::SnortStrnStr((const char*)buffer, length, "HTTP/") != nullptr )
@@ -59,18 +46,23 @@ public:
     }
 
     // The following methods are for convenience of debug and test output only!
-    uint64_t get_raw() const { return
-       (events_generated & std::bitset<MAX>(0xFFFFFFFFFFFFFFFF)).to_ulong(); }
     uint64_t get_raw2() const { return
-       ((events_generated >> BASE_1XX_EVENTS) & std::bitset<MAX>(0xFFFFFFFFFFFFFFFF)).to_ulong(); }
+       ((events_generated >> BASE_1XX_EVENTS) & bitmask).to_ulong(); }
+
     uint64_t get_raw3() const { return
-       ((events_generated >> BASE_2XX_EVENTS) & std::bitset<MAX>(0xFFFFFFFFFFFFFFFF)).to_ulong(); }
+       ((events_generated >> BASE_2XX_EVENTS) & bitmask).to_ulong(); }
+
 private:
     static const unsigned BASE_1XX_EVENTS = 100;
     static const unsigned BASE_2XX_EVENTS = 200;
-    static const int MAX = HttpEnums::EVENT__MAX_VALUE;
-    std::bitset<MAX> events_generated = 0;
 };
 
+
+//-------------------------------------------------------------------------
+// Http Infractions
+//-------------------------------------------------------------------------
+
+using HttpInfractions = Infractions<HttpEnums::INF__MAX_VALUE, HttpEnums::INF__NONE>;
+
 #endif
 
index dea0c1ee7913e8fcca3ebf0ad18c6b4c8d157bd3..42769c3270be66141be08ce84b56e043038c07f2 100644 (file)
@@ -29,8 +29,7 @@
 #include "utils/util_utf.h"
 #include "decompress/file_decomp.h"
 
-#include "http_infractions.h"
-#include "http_event_gen.h"
+#include "http_event.h"
 
 class HttpTransaction;
 class HttpJsNorm;
index 3d9c142f668c38a92e0b261870865dcb8c604652..32d6a6a1336f3ec3d2942f46034cde03b11fe155 100644 (file)
@@ -21,7 +21,6 @@
 #define HTTP_HEADER_NORMALIZER_H
 
 #include "http_field.h"
-#include "http_infractions.h"
 #include "http_normalizers.h"
 
 //-------------------------------------------------------------------------
index 7088ff2b73069d9f151be99b57a08bb9f982d268..cbc3098dd92d2742ab4780cad8a7e7516eb53132 100644 (file)
@@ -25,8 +25,7 @@
 #include "search_engines/search_tool.h"
 
 #include "http_field.h"
-#include "http_event_gen.h"
-#include "http_infractions.h"
+#include "http_event.h"
 #include "http_module.h"
 
 //-------------------------------------------------------------------------
index 80f831dd7c4f063db1f0f8bc071f5b74b3ddf0a7..d241a6252189a2092e9f889c0dd2450723501efb 100644 (file)
@@ -20,8 +20,7 @@
 #ifndef HTTP_NORMALIZERS_H
 #define HTTP_NORMALIZERS_H
 
-#include "http_infractions.h"
-#include "http_event_gen.h"
+#include "http_event.h"
 #include "http_field.h"
 #include "http_str_to_code.h"
 
index 122fc0122a20e7ce32302c4ccabda611b86940a6..dff62b0076028250f0b069ddd25f9f00ddd97ee6 100644 (file)
@@ -23,8 +23,7 @@
 
 #include "http_transaction.h"
 
-#include "http_event_gen.h"
-#include "http_infractions.h"
+#include "http_event.h"
 #include "http_msg_body.h"
 #include "http_msg_header.h"
 #include "http_msg_request.h"
index 115581fe6da1aba4f71a3bc1ab7d3f0250bb97b4..7ddc70e41f1d0d5cfa5525fba86d13c5a36e8519 100644 (file)
@@ -30,8 +30,9 @@ class HttpMsgTrailer;
 class HttpMsgSection;
 class HttpMsgBody;
 class HttpMsgHeadShared;
-class HttpInfractions;
 class HttpEventGen;
+template <int MAX, int NONE> class Infractions;
+using HttpInfractions = Infractions<HttpEnums::INF__MAX_VALUE, HttpEnums::INF__NONE>;
 
 class HttpTransaction
 {
index 7bc5ec78b02e634ffcfb322dd0c925a295d61503..2834baa40da07fbd5716747848dae93410fb9181 100644 (file)
@@ -24,8 +24,7 @@
 #include "http_module.h"
 #include "http_uri_norm.h"
 #include "http_field.h"
-#include "http_infractions.h"
-#include "http_event_gen.h"
+#include "http_event.h"
 
 //-------------------------------------------------------------------------
 // HttpUri class
index f62f519cf39eed5ee5a1079503e6dbc3cb26bb73..47a66f95ed608ecc67382588a2a0ba30c366561b 100644 (file)
@@ -26,8 +26,7 @@
 #include "http_enum.h"
 #include "http_field.h"
 #include "http_module.h"
-#include "http_infractions.h"
-#include "http_event_gen.h"
+#include "http_event.h"
 
 class UriNormalizer
 {
index 806cb0c02c905262884c886cbf2586ec5d838293..ebe7046f6b7497bd48b892ac717141b51facc7dc 100644 (file)
@@ -3,6 +3,8 @@ set( UTIL_INCLUDES
     bitop.h
     cpp_macros.h
     endian.h
+    event_gen.h
+    infractions.h
     kmap.h
     primed_allocator.h
     safec.h
diff --git a/src/utils/event_gen.h b/src/utils/event_gen.h
new file mode 100644 (file)
index 0000000..b86e957
--- /dev/null
@@ -0,0 +1,61 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+// event_gen.h author Tom Peters <thopeter@cisco.com>
+
+#ifndef EVENT_GEN_H
+#define EVENT_GEN_H
+
+#include <bitset>
+#include <cassert>
+
+#include "detection/detection_engine.h"
+
+//-------------------------------------------------------------------------
+// Event generator class
+//-------------------------------------------------------------------------
+
+template <int EVENT_MAX, int EVENT_NONE, int GID>
+class EventGen
+{
+public:
+    virtual ~EventGen() = default;
+
+    virtual void create_event(int sid)
+    {
+        if (sid == EVENT_NONE)
+            return;
+        assert((sid > 0) && (sid <= EVENT_MAX));
+        if (!events_generated[sid-1])
+        {
+            snort::DetectionEngine::queue_event(GID, (uint32_t)sid);
+            events_generated[sid-1] = true;
+        }
+    }
+
+    bool none_found() const { return events_generated == 0; }
+
+    // The following method is for convenience of debug and test output only!
+    uint64_t get_raw() const { return
+        (events_generated & bitmask).to_ulong(); }
+
+protected:
+    std::bitset<EVENT_MAX> events_generated = 0;
+    const std::bitset<EVENT_MAX> bitmask = 0xFFFFFFFFFFFFFFFF;
+};
+
+#endif
similarity index 77%
rename from src/service_inspectors/http_inspect/http_infractions.h
rename to src/utils/infractions.h
index 5a63d7ced2e6222e4060eac8af143287612d862a..4d4a63d97e1b129dc44d66d693afcb0d1abe39a7 100644 (file)
 // with this program; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
-// http_infractions.h author Tom Peters <thopeter@cisco.com>
+// infractions.h author Tom Peters <thopeter@cisco.com>
 
-#ifndef HTTP_INFRACTIONS_H
-#define HTTP_INFRACTIONS_H
+#ifndef INFRACTIONS_H
+#define INFRACTIONS_H
 
 #include <bitset>
 #include <cassert>
 
-#include "http_enum.h"
-
 //-------------------------------------------------------------------------
 // Infractions class
 //-------------------------------------------------------------------------
 
-class HttpInfractions
+template <int MAX, int NONE>
+class Infractions
 {
 public:
-    HttpInfractions() = default;
-    HttpInfractions(int inf)
+    Infractions() = default;
+    Infractions(int inf)
     {
-        if (inf == HttpEnums::INF__NONE)
+        if (inf == NONE)
             return;
         assert((inf >= 0) && (inf < MAX));
         infractions[inf] = true;
     }
     bool none_found() const { return infractions == 0; }
-    HttpInfractions& operator+=(const HttpInfractions& rhs)
+    Infractions& operator+=(const Infractions& rhs)
         { infractions |= rhs.infractions; return *this; }
-    friend HttpInfractions operator+(HttpInfractions lhs, const HttpInfractions& rhs)
+    friend Infractions operator+(Infractions lhs, const Infractions& rhs)
         { lhs += rhs; return lhs; }
-    friend bool operator&(const HttpInfractions& lhs, const HttpInfractions& rhs)
+    friend bool operator&(const Infractions& lhs, const Infractions& rhs)
         { return (lhs.infractions & rhs.infractions) != 0; }
 
     // The following methods are for convenience of debug and test output only!
@@ -55,9 +54,7 @@ public:
         ((infractions >> 64) & std::bitset<MAX>(0xFFFFFFFFFFFFFFFF)).to_ulong(); }
 
 private:
-    static const int MAX = HttpEnums::INF__MAX_VALUE;
     std::bitset<MAX> infractions = 0;
 };
 
 #endif
-