]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4538: add content width and endian parameters
authorChris Morrison (chmorri2) <chmorri2@cisco.com>
Fri, 17 Jan 2025 08:22:09 +0000 (08:22 +0000)
committerOleksii Shumeiko -X (oshumeik - SOFTSERVE INC at Cisco) <oshumeik@cisco.com>
Fri, 17 Jan 2025 08:22:09 +0000 (08:22 +0000)
Merge in SNORT/snort3 from ~CHMORRI2/snort3:ips-option-content-wide to master

Squashed commit of the following:

commit 48b9e666c90626117be90c3218e4c08f1d482dcc
Author: Chris Morrison <chmorri2@cisco.com>
Date:   Tue Jan 14 13:42:03 2025 -0500

    ips_options: ips_content.cc given width and endian parameters for simpler multi-byte char matches

src/ips_options/ips_content.cc

index 1190d48b729a3fd68fbea8aa962413981b91a227..a6b0c6fbb6c7db82157a2b7969112087d22bf203 100644 (file)
@@ -70,6 +70,9 @@ public:
     unsigned match_delta;   /* Maximum distance we can jump to search for this pattern again. */
 
     bool depth_configured = true;
+
+    uint8_t char_width;  /* Byte width to expand to */
+    bool little_endian;  /* Endianness of multi-byte characters */
 };
 
 ContentData::ContentData()
@@ -78,6 +81,8 @@ ContentData::ContentData()
     offset_var = IPS_OPTIONS_NO_VAR;
     depth_var = IPS_OPTIONS_NO_VAR;
     match_delta = 0;
+    char_width = 1;
+    little_endian = false;
 }
 
 ContentData::~ContentData()
@@ -649,6 +654,12 @@ static const Parameter s_params[] =
     { "within", Parameter::PT_STRING, nullptr, nullptr,
       "var or maximum number of bytes to search from cursor" },
 
+    { "width", Parameter::PT_ENUM, "8|16|32", "8",
+      "char width to convert to" },
+
+    { "endian", Parameter::PT_ENUM, "big|little", "big",
+      "specify big/little endian for wide string conversions" },
+
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
@@ -702,6 +713,25 @@ bool ContentModule::begin(const char*, int, SnortConfig*)
 
 bool ContentModule::end(const char*, int, SnortConfig*)
 {
+    if ( cd->char_width > 1 )
+    {
+        // An endian flip of a single byte is just an offset
+        int endian_offset = cd->little_endian ? 0 : cd->char_width - 1;
+
+        char* temp = new char[cd->char_width * cd->pmd.pattern_size]();
+
+        for ( unsigned i = 0; i < cd->pmd.pattern_size; i++ )
+        {
+            temp[(i * cd->char_width) + endian_offset] = cd->pmd.pattern_buf[i];
+        }
+
+        delete[] cd->pmd.pattern_buf;
+        cd->pmd.pattern_buf = temp;
+        cd->pmd.pattern_size *= cd->char_width;
+        cd->pmd.fp_length *= cd->char_width;
+        cd->pmd.fp_offset *= cd->char_width;
+    }
+
     if ( (int)cd->pmd.pattern_size <= cd->pmd.fp_offset )
     {
         ParseError(
@@ -785,6 +815,26 @@ bool ContentModule::set(const char*, Value& v, SnortConfig*)
         cd->pmd.fp_length = v.get_uint16();
         cd->pmd.set_fast_pattern();
     }
+    else if ( v.is("width") )
+    {
+        switch ( v.get_uint8() )
+        {
+        case 0:  // "8"
+            cd->char_width = 1;
+            break;
+        case 1:  // "16"
+            cd->char_width = 2;
+            break;
+        case 2:  // "32"
+            cd->char_width = 4;
+            break;
+        }
+    }
+    else if ( v.is("endian") )
+    {
+        cd->little_endian = v.get_uint8() == 1;
+    }
+
     return true;
 }