]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
see change log for 88; mostly detection using Cursor
authorRuss Combs <rucombs@cisco.com>
Thu, 19 Jun 2014 02:36:35 +0000 (22:36 -0400)
committerRuss Combs <rucombs@cisco.com>
Thu, 19 Jun 2014 02:36:35 +0000 (22:36 -0400)
95 files changed:
ChangeLog
configure.ac
extra/README [new file with mode: 0644]
src/detection/detect.cc
src/detection/detect.h
src/detection/detection_options.cc
src/detection/detection_options.h
src/detection/detection_util.h
src/detection/fpcreate.cc
src/detection/fpdetect.cc
src/detection/rule_option_types.h
src/detection/treenodes.h
src/framework/CMakeLists.txt
src/framework/Makefile.am
src/framework/cursor.cc [new file with mode: 0644]
src/framework/cursor.h [new file with mode: 0644]
src/framework/inspector.h
src/framework/ips_option.h
src/ips_options/CMakeLists.txt
src/ips_options/Makefile.am
src/ips_options/ips_ack.cc
src/ips_options/ips_asn1.cc
src/ips_options/ips_base64_data.cc
src/ips_options/ips_base64_decode.cc
src/ips_options/ips_byte_extract.cc
src/ips_options/ips_byte_jump.cc
src/ips_options/ips_byte_test.cc
src/ips_options/ips_content.cc
src/ips_options/ips_content.h
src/ips_options/ips_cvs.cc
src/ips_options/ips_dsize.cc
src/ips_options/ips_file_data.cc
src/ips_options/ips_flags.cc
src/ips_options/ips_flow.cc
src/ips_options/ips_flowbits.cc
src/ips_options/ips_fragbits.cc
src/ips_options/ips_fragoffset.cc
src/ips_options/ips_icmp_id.cc
src/ips_options/ips_icmp_seq.cc
src/ips_options/ips_icode.cc
src/ips_options/ips_id.cc
src/ips_options/ips_ip_proto.cc
src/ips_options/ips_ipopts.cc
src/ips_options/ips_isdataat.cc
src/ips_options/ips_itype.cc
src/ips_options/ips_luajit.cc
src/ips_options/ips_luajit.h
src/ips_options/ips_options.cc
src/ips_options/ips_pcre.cc
src/ips_options/ips_pcre.h
src/ips_options/ips_pkt_data.cc
src/ips_options/ips_raw_data.cc [new file with mode: 0644]
src/ips_options/ips_replace.cc [moved from src/ips_options/replace.cc with 66% similarity]
src/ips_options/ips_replace.h [moved from src/ips_options/replace.h with 71% similarity]
src/ips_options/ips_rpc.cc
src/ips_options/ips_sameip.cc
src/ips_options/ips_seq.cc
src/ips_options/ips_session.cc
src/ips_options/ips_so.cc
src/ips_options/ips_tos.cc
src/ips_options/ips_ttl.cc
src/ips_options/ips_urilen.cc
src/ips_options/ips_window.cc
src/main/analyzer.cc
src/main/snort.cc
src/main/snort_config.h
src/managers/module_manager.cc
src/network_inspectors/arp_spoof/arp_spoof.cc
src/network_inspectors/normalize/normalize.cc
src/network_inspectors/perf_monitor/perf_monitor.cc
src/network_inspectors/port_scan/port_scan.cc
src/parser/mstring.cc
src/parser/mstring.h
src/parser/parse_rule.cc
src/service_inspectors/back_orifice/back_orifice.cc
src/service_inspectors/ftp_telnet/ftp.cc
src/service_inspectors/ftp_telnet/telnet.cc
src/service_inspectors/http_inspect/CMakeLists.txt
src/service_inspectors/http_inspect/Makefile.am
src/service_inspectors/http_inspect/hi_ips_options.cc [new file with mode: 0644]
src/service_inspectors/http_inspect/hi_norm.cc
src/service_inspectors/http_inspect/http_inspect.cc
src/service_inspectors/http_inspect/http_inspect.h [new file with mode: 0644]
src/service_inspectors/nhttp_inspect/nhttp_api.cc
src/service_inspectors/rpc_decode/rpc_decode.cc
src/service_inspectors/service_inspectors.cc
src/stream/base/stream_base.cc
src/stream/icmp/stream_icmp.cc
src/stream/ip/stream_ip.cc
src/stream/tcp/stream_tcp.cc
src/stream/udp/stream_udp.cc
src/utils/CMakeLists.txt
src/utils/Makefile.am
src/utils/boyer_moore.cc [new file with mode: 0644]
src/utils/boyer_moore.h [new file with mode: 0644]

index 64d12933097f2ba3790a07ec764ade228fa692f2..d347576a756b2f4711992f26e0b94f23911f8322 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 88
--- tweaked allocation of pmd.last_check
+-- overhauled content and pcre detection to use Cursor
+-- http_* are now first class rule options
+-- removed experimental contents and get_buf() from InspectApi
+-- changed call to acquire daq with count 0 (all)
+-- changed replace to be 1st class rule option
+-- split boyer-moore functions out of mstring module
 
 87
 -- renamed api function typedefs to camel case for consistency and to match
index 44d970cbd000594b2cb4f5a22291f2c1a5cdf64a..0573a312546e0438040bde475a63e4650ec0439d 100644 (file)
@@ -25,7 +25,7 @@
 # initialization
 #--------------------------------------------------------------------------
 
-AC_INIT([snort], [2.10.087])
+AC_INIT([snort], [2.10.088])
 AC_PREREQ([2.68])
 
 AC_CONFIG_SRCDIR([src/main.h])
diff --git a/extra/README b/extra/README
new file mode 100644 (file)
index 0000000..b5c743f
--- /dev/null
@@ -0,0 +1,30 @@
+0.  Given this variable:
+
+install_dir=/home/snorty/install
+
+1.  Build and install the Snort package first:
+
+./configure --prefix=$install_dir ...
+
+2.  Make sure that pkg-config is installed.  Then
+
+export PKG_CONFIG_PATH=$install_dir/lib/pkgconfig
+
+3.  Build and install the example plugins:
+
+./configure --prefix=$install_dir --with-snort-includes=$install_dir/include/snort
+make
+make install
+
+4.  Run Snort with the example plugins:
+
+snort --plugin-path $install_dir/lib/snort_examples ...
+
+5.  Now build your own plugins following the examples.
+    For inspiration, also look at:
+
+src/service_handlers/
+src/network_handlers/
+src/event_handlers/
+src/detection_plugins/ips_*
+
index 607e6fdb4bdb9dc54e52367eeb1ef2faf31ba120..4ea5821e53e80aea22aa87d648f4a0571ed76cba 100644 (file)
@@ -819,7 +819,7 @@ int RuleListEnd(Packet*, RuleTreeNode*, RuleFpList*, int)
     return 1;
 }
 
-int OptListEnd(void*, Packet*)
+int OptListEnd(void*, Cursor&, Packet*)
 {
     return DETECTION_OPTION_MATCH;
 }
index 07ba0f8f73578bb584d013b12645656712941911..69026f6727d585cc58cc0be828118d58ab78d843 100644 (file)
@@ -70,7 +70,7 @@ int CheckSrcPortNotEq(Packet *, RuleTreeNode *, RuleFpList *, int);
 int CheckDstPortNotEq(Packet *, RuleTreeNode *, RuleFpList *, int);
 
 int RuleListEnd(Packet *, RuleTreeNode *, RuleFpList *, int);
-int OptListEnd(void *option_data, Packet *p);
+int OptListEnd(void* option_data, struct Cursor&, Packet*);
 
 void snort_log(Packet*);
 void CallLogFuncs(Packet*, Event*, const char*);
index 2ef329908648ea51d66414d5d4124a06cd4c7041..e4e0ba02cf1763644d83a27b2e43d99dc43c3e17 100644 (file)
 #include "ips_options/ips_flowbits.h"
 #include "ips_options/ips_content.h"
 #include "ips_options/ips_pcre.h"
-#include "ips_options/replace.h"
+#include "ips_options/ips_replace.h"
 #include "fpdetect.h"
 #include "ppm.h"
 #include "profiler.h"
 #include "filters/detection_filter.h"
 #include "main/thread.h"
 #include "framework/ips_option.h"
+#include "framework/cursor.h"
 #include "managers/ips_manager.h"
 #include "managers/packet_manager.h"
 
@@ -388,15 +389,15 @@ int add_detection_option_tree(
 THREAD_LOCAL uint64_t rule_eval_pkt_count = 0;
 
 int detection_option_node_evaluate(
-    detection_option_tree_node_t *node, detection_option_eval_data_t *eval_data)
+    detection_option_tree_node_t *node, detection_option_eval_data_t *eval_data,
+    Cursor& orig_cursor)
 {
-    int i, result = 0, prior_result = 0;
+    int i, result = 0; //, prior_result = 0;
     int rval = DETECTION_OPTION_NO_MATCH;
-    const uint8_t *orig_doe_ptr;
     char tmp_noalert_flag = 0;
-    PatternMatchData dup_content_option_data;
-    PcreData dup_pcre_option_data;
-    const uint8_t *dp = NULL;
+    Cursor cursor = orig_cursor;
+    PatternMatchData* content_data;
+    PcreData* pcre_data;
     char continue_loop = 1;
     char flowbits_setoperation = 0;
     int loop_count = 0;
@@ -441,64 +442,14 @@ int detection_option_node_evaluate(
     state->last_check.flowbit_failed = 0;
 
     /* Save some stuff off for repeated pattern tests */
-    orig_doe_ptr = doe_ptr;
-
     if ((node->option_type == RULE_OPTION_TYPE_CONTENT) ||
             (node->option_type == RULE_OPTION_TYPE_CONTENT_URI))
     {
-        PatternMatchDuplicatePmd(node->option_data, &dup_content_option_data);
-
-        if (dup_content_option_data.buffer_func == CHECK_URI_PATTERN_MATCH)
-        {
-            const HttpBuffer* hb = GetHttpBuffer(dup_content_option_data.http_buffer);
-            dp = hb ? hb->buf : NULL;  // FIXTHIS set length too
-        }
-        else if (dup_content_option_data.rawbytes == 0)
-        {
-            /* If AltDetect is set by calling the rule options which set it,
-             * we should use the Alt Detect before checking for any other buffers.
-             * Alt Detect will take precedence over the Alt Decode and/or packet data.
-             */
-            if(Is_DetectFlag(FLAG_ALT_DETECT))
-                dp = (uint8_t *)DetectBuffer.data;
-            else if(Is_DetectFlag(FLAG_ALT_DECODE))
-                dp = (uint8_t *)DecodeBuffer.data;
-            else
-                dp = eval_data->p->data;
-        }
-        else
-        {
-            dp = eval_data->p->data;
-        }
+        content_data = content_get_data(node->option_data);
     }
     else if (node->option_type == RULE_OPTION_TYPE_PCRE)
     {
-        HTTP_BUFFER hb_type;
-        PcreDuplicatePcreData(node->option_data, &dup_pcre_option_data);
-        hb_type = (HTTP_BUFFER)(dup_pcre_option_data.options & SNORT_PCRE_HTTP_BUFS);
-
-        if ( hb_type )
-        {
-            const HttpBuffer* hb = GetHttpBuffer(hb_type);
-            dp = hb ? hb->buf : NULL;  // FIXTHIS set length too
-        }
-        else if (!(dup_pcre_option_data.options & SNORT_PCRE_RAWBYTES))
-        {
-            /* If AltDetect is set by calling the rule options which set it,
-             * we should use the Alt Detect before checking for any other buffers.
-             * Alt Detect will take precedence over the Alt Decode and/or packet data.
-             */
-            if(Is_DetectFlag(FLAG_ALT_DETECT))
-                dp = (uint8_t *)DetectBuffer.data;
-            else if(Is_DetectFlag(FLAG_ALT_DECODE))
-                dp = (uint8_t *)DecodeBuffer.data;
-            else
-                dp = eval_data->p->data;
-        }
-        else
-        {
-            dp = eval_data->p->data;
-        }
+        pcre_data = pcre_get_data(node->option_data);
     }
 
     /* No, haven't evaluated this one before... Check it. */
@@ -528,7 +479,8 @@ int detection_option_node_evaluate(
                         {
                             if (otn->sigInfo.services[svc_idx].service_ordinal != 0)
                             {
-                                if (eval_data->p->application_protocol_ordinal == otn->sigInfo.services[svc_idx].service_ordinal)
+                                if (eval_data->p->application_protocol_ordinal ==
+                                    otn->sigInfo.services[svc_idx].service_ordinal)
                                 {
                                     check_ports = 0;
                                     break; /* out of for */
@@ -574,16 +526,17 @@ int detection_option_node_evaluate(
             case RULE_OPTION_TYPE_CONTENT:
                 if (node->evaluate)
                 {
+#if 0
                     /* This will be set in the fast pattern matcher if we found
                      * a content and the rule option specifies not that
                      * content. Essentially we've already evaluated this rule
                      * option via the content option processing since only not
                      * contents that are not relative in any way will have this
                      * flag set */
-                    if (dup_content_option_data.last_check)
+                    if (content_data->last_check)
                     {
                         PmdLastCheck* last_check =
-                            dup_content_option_data.last_check + get_instance_id();
+                            content_data->last_check + get_instance_id();
 
                         if ((last_check->ts.tv_sec == eval_data->p->pkth->ts.tv_sec) &&
                             (last_check->ts.tv_usec == eval_data->p->pkth->ts.tv_usec) &&
@@ -594,23 +547,20 @@ int detection_option_node_evaluate(
                             break;
                         }
                     }
-
-                    rval = eval_dup_content(
-                        node->option_data, eval_data->p, &dup_content_option_data);
+#endif
+                    rval = node->evaluate(node->option_data, cursor, eval_data->p);
                 }
                 break;
             case RULE_OPTION_TYPE_CONTENT_URI:
                 if (node->evaluate)
                 {
-                    rval = eval_dup_content(
-                        node->option_data, eval_data->p, &dup_content_option_data);
+                    rval = node->evaluate(node->option_data, cursor, eval_data->p);
                 }
                 break;
             case RULE_OPTION_TYPE_PCRE:
                 if (node->evaluate)
                 {
-                    rval = eval_dup_pcre(
-                        node->option_data, eval_data->p, &dup_pcre_option_data);
+                    rval = node->evaluate(node->option_data, cursor, eval_data->p);
                 }
                 break;
             case RULE_OPTION_TYPE_PKT_DATA:
@@ -619,7 +569,7 @@ int detection_option_node_evaluate(
                 if (node->evaluate)
                 {
                     save_dflags = Get_DetectFlags();
-                    rval = node->evaluate(node->option_data, eval_data->p);
+                    rval = node->evaluate(node->option_data, cursor, eval_data->p);
                 }
                 break;
             case RULE_OPTION_TYPE_FLOWBIT:
@@ -628,7 +578,7 @@ int detection_option_node_evaluate(
                     flowbits_setoperation = FlowBits_SetOperation(node->option_data);
                     if (!flowbits_setoperation)
                     {
-                        rval = node->evaluate(node->option_data, eval_data->p);
+                        rval = node->evaluate(node->option_data, cursor, eval_data->p);
                     }
                     else
                     {
@@ -639,7 +589,7 @@ int detection_option_node_evaluate(
                 break;
             default:
                 if (node->evaluate)
-                    rval = node->evaluate(node->option_data, eval_data->p);
+                    rval = node->evaluate(node->option_data, cursor, eval_data->p);
                 break;
         }
 
@@ -700,18 +650,12 @@ int detection_option_node_evaluate(
         /* Passed, check the children. */
         if (node->num_children)
         {
-            const uint8_t *tmp_doe_ptr = doe_ptr;
-            const uint8_t tmp_doe_flags = doe_buf_flags;
-
             for (i=0;i<node->num_children; i++)
             {
                 int j = 0;
                 detection_option_tree_node_t *child_node = node->children[i];
                 dot_node_state_t* child_state = child_node->state + get_instance_id();
 
-                /* reset the DOE ptr for each child from here */
-                SetDoePtr(tmp_doe_ptr, tmp_doe_flags);
-
                 for (j = 0; j < NUM_BYTE_EXTRACT_VARS; j++)
                 {
                     SetByteExtractValue(tmp_byte_extract_vars[j], (int8_t)j);
@@ -762,7 +706,9 @@ int detection_option_node_evaluate(
                     }
                 }
 
-                child_state->result = detection_option_node_evaluate(node->children[i], eval_data);
+                child_state->result = detection_option_node_evaluate(
+                    node->children[i], eval_data, cursor);
+
                 if (child_node->option_type == RULE_OPTION_TYPE_LEAF_NODE)
                 {
                     /* Leaf node won't have any children but will return success
@@ -798,8 +744,6 @@ int detection_option_node_evaluate(
              * rule option */
             if (result == node->num_children)
                 continue_loop = 0;
-            else
-                SetDoePtr(tmp_doe_ptr, tmp_doe_flags);
 
             /* Don't need to reset since it's only checked after we've gone
              * through the loop at least once and the result will have
@@ -808,16 +752,19 @@ int detection_option_node_evaluate(
             //    node->children[i]->result;
         }
 
+#if 0
+        // FIXIT replace is broken now :(
         if (result - prior_result > 0
             && node->option_type == RULE_OPTION_TYPE_CONTENT
-            && Replace_OffsetStored(&dup_content_option_data) && ScInlineMode())
+            && Replace_OffsetStored(content_data) && ScInlineMode())
         {
             // FIXIT queuing replacements here is premature
             // should be done if / when rule actually fires
             // and at that point, the change can be applied
-            Replace_QueueChange(&dup_content_option_data);
+            Replace_QueueChange(content_data);
             prior_result = result;
         }
+#endif
 
         NODE_PROFILE_TMPSTART(node);
 
@@ -832,41 +779,11 @@ int detection_option_node_evaluate(
             if ((node->option_type == RULE_OPTION_TYPE_CONTENT) ||
                     (node->option_type == RULE_OPTION_TYPE_CONTENT_URI))
             {
-                if (dup_content_option_data.exception_flag)
-                {
-                    continue_loop = 0;
-                }
-                else
-                {
-                    const uint8_t *orig_ptr;
-
-                    if (dup_content_option_data.use_doe)
-                        orig_ptr = (orig_doe_ptr == NULL) ? dp : orig_doe_ptr;
-                    else
-                        orig_ptr = dp;
-
-                    continue_loop = PatternMatchAdjustRelativeOffsets(
-                        node->option_data, &dup_content_option_data,
-                        doe_ptr, orig_ptr);
-                }
+                continue_loop = content_next(content_data);
             }
             else if (node->option_type == RULE_OPTION_TYPE_PCRE)
             {
-                if (dup_pcre_option_data.options & SNORT_PCRE_INVERT)
-                {
-                    continue_loop = 0;
-                }
-                else
-                {
-                    const uint8_t *orig_ptr;
-
-                    if (dup_pcre_option_data.options & SNORT_PCRE_RELATIVE)
-                        orig_ptr = (orig_doe_ptr == NULL) ? dp : orig_doe_ptr;
-                    else
-                        orig_ptr = dp;
-
-                    continue_loop = PcreAdjustRelativeOffsets(&dup_pcre_option_data, doe_ptr - orig_ptr);
-                }
+                continue_loop = pcre_next(pcre_data);
             }
             else
             {
@@ -887,16 +804,13 @@ int detection_option_node_evaluate(
 
         loop_count++;
 
-        if (continue_loop)
-            UpdateDoePtr(orig_doe_ptr, 0);
-
     } while (continue_loop);
 
     if (flowbits_setoperation && (result == DETECTION_OPTION_MATCH))
     {
         /* Do any setting/clearing/resetting/toggling of flowbits here
          * given that other rule options matched. */
-        rval = node->evaluate(node->option_data, eval_data->p);
+        rval = node->evaluate(node->option_data, cursor, eval_data->p);
         if (rval != DETECTION_OPTION_MATCH)
         {
             result = rval;
index 59f3100ed0f1a68ebae4ea047debd63f0e18950b..cf92e37175459ea376eb36169be48b70a5bd0243 100644 (file)
@@ -45,7 +45,7 @@
 #include "detection/detection_defines.h"
 #include "hash/sfhashfcn.h"
 
-typedef int (*eval_func_t)(void *option_data, Packet *p);
+typedef int (*eval_func_t)(void* option_data, struct Cursor&, Packet*);
 
 struct dot_node_state_t
 {
@@ -117,7 +117,9 @@ int add_detection_option(
 int add_detection_option_tree(
     struct SnortConfig*, detection_option_tree_node_t *option_tree, void **existing_data);
 
-int detection_option_node_evaluate(detection_option_tree_node_t *node, detection_option_eval_data_t *eval_data);
+int detection_option_node_evaluate(
+    detection_option_tree_node_t *node, detection_option_eval_data_t *eval_data, struct Cursor&);
+
 void DetectionHashTableFree(SFXHASH *);
 void DetectionTreeHashTableFree(SFXHASH *);
 #ifdef DEBUG_OPTION_TREE
index 6713c45de146e6d7e4e82d04ca9ff6aae406b1fa..b68ffc53a6d8547d373c8b24625241962a4322b6 100644 (file)
@@ -63,43 +63,31 @@ typedef enum
 } HTTP_BUFFER;
 #endif
 
-typedef enum {
+enum DetectFlagType
+{
     FLAG_ALT_DECODE         = 0x0001,
     FLAG_ALT_DETECT         = 0x0002,
     FLAG_DETECT_ALL         = 0xffff
-} DetectFlagType;
-
-#define DOE_BUF_URI     0x01
-#define DOE_BUF_STD     0x02
-
-#define HTTPURI_PIPELINE_REQ 0x01
+};
 
-#define HTTP_ENCODE_TYPE__UTF8_UNICODE   0x00000001
-#define HTTP_ENCODE_TYPE__DOUBLE_ENCODE  0x00000002
-#define HTTP_ENCODE_TYPE__NONASCII       0x00000004
-#define HTTP_ENCODE_TYPE__BASE36         0x00000008
-#define HTTP_ENCODE_TYPE__UENCODE        0x00000010
-#define HTTP_ENCODE_TYPE__BARE_BYTE      0x00000020
-#define HTTP_ENCODE_TYPE__IIS_UNICODE    0x00000040
-#define HTTP_ENCODE_TYPE__ASCII          0x00000080
-
-typedef struct
+struct HttpBuffer
 {
     const uint8_t* buf;
     uint16_t length;
     uint32_t encode_type;
-} HttpBuffer;
+};
 
-typedef struct {
+struct DataPointer
+{
     uint8_t *data;
     uint16_t len;
-} DataPointer;
+};
 
-
-typedef struct {
+struct DataBuffer
+{
     uint8_t data[DECODE_BLEN];
     uint16_t len;
-} DataBuffer;
+};
 
 extern THREAD_LOCAL uint8_t base64_decode_buf[DECODE_BLEN];
 extern THREAD_LOCAL uint32_t base64_decode_size;
@@ -179,74 +167,6 @@ static inline void setFileDataPtr(uint8_t *ptr, uint16_t decode_size)
     file_data_ptr.len = decode_size;
 }
 
-/*
- * Function: IsBase64DecodeBuf
- *
- * Purpose: Checks if there is base64 decoded buffer.
- *
- * Arguments: p => doe_ptr
- *
- * Returns: Returns 1 if there is base64 decoded data
- *          and if the doe_ptr is within the buffer.
- *          Returns 0 otherwise.
- *
- */
-
-static inline int IsBase64DecodeBuf(const uint8_t *p)
-{
-    if( base64_decode_size && p )
-    {
-        if ((p >= base64_decode_buf) &&
-                (p < (base64_decode_buf + base64_decode_size)))
-        {
-            return 1;
-        }
-        else
-            return 0;
-    }
-    else
-        return 0;
-}
-
-/*
- * Function: SetDoePtr(const uint8_t *ptr, uint8_t type)
- *
- * Purpose: This function set the doe_ptr and sets the type of
- *          buffer to which doe_ptr points.
- *
- * Arguments: ptr       => pointer
- *            type      => type of buffer
- *
- * Returns: void
- *
-*/
-
-static inline void SetDoePtr(const uint8_t *ptr, uint8_t type)
-{
-    doe_ptr = ptr;
-    doe_buf_flags = type;
-}
-
-/*
- * Function: UpdateDoePtr(const uint8_t *ptr, uint8_t update)
- *
- * Purpose: This function updates the doe_ptr and resets the type of
- *          buffer to which doe_ptr points based on the update value.
- *
- * Arguments: ptr       => pointer
- *            update    => reset the buf flag if update is not zero.
- *
- * Returns: void
- *
-*/
-
-static inline void UpdateDoePtr(const uint8_t *ptr, uint8_t update)
-{
-    doe_ptr = ptr;
-    if(update)
-        doe_buf_flags = DOE_BUF_STD;
-}
-
 void EventTrace_Init(void);
 void EventTrace_Term(void);
 
index fe19a5d1cde66a1395d1e174aa55d7041b0b2fd2..1b47605f730e0a52d669fdbfc705dfe62ca25f90 100644 (file)
@@ -875,10 +875,6 @@ static inline int IsPmdFpEligible(PatternMatchData *content)
 
     if ((content->pattern_buf != NULL) && (content->pattern_size != 0))
     {
-        /* We don't add cookie and some other contents to fast pattern matcher */
-        if(content->http_buffer && !IsHttpBufFpEligible(content->http_buffer))
-            return 0;
-
         if (content->exception_flag)
         {
             /* Negative contents can only be considered if they are not relative
@@ -889,7 +885,7 @@ static inline int IsPmdFpEligible(PatternMatchData *content)
              * Also case sensitive patterns cannot be considered since patterns
              * are inserted into the pattern matcher without case which may
              * lead to false negatives */
-            if (content->use_doe || !content->nocase
+            if (content->use_doe || !content->no_case
                     || (content->offset != 0) || (content->depth != 0))
             {
                 return 0;
@@ -1061,7 +1057,7 @@ static int fpFinishPortGroupRule(
                 sc,
                 pattern,
                 pattern_length,
-                pmd->nocase,
+                pmd->no_case,
                 pmd->offset,
                 pmd->depth,
                 (unsigned)pmd->exception_flag,
@@ -1169,6 +1165,8 @@ static int fpAllocPms(
     return 0;
 }
 
+#if 0
+// FIXIT fast_pattern
 static PmType GetPmType (HTTP_BUFFER hb_type)
 {
     switch ( hb_type )
@@ -1187,12 +1185,12 @@ static PmType GetPmType (HTTP_BUFFER hb_type)
     }
     return PM_TYPE__CONTENT;
 }
+#endif
 
 static int fpAddPortGroupRule(
     SnortConfig *sc, PORT_GROUP *pg, OptTreeNode *otn, FastPatternConfig *fp)
 {
     PatternMatchData *pmd = NULL;
-    PatternMatchData *pmd_uri = NULL;
 
     if ((pg == NULL) || (otn == NULL))
         return -1;
@@ -1218,6 +1216,8 @@ static int fpAddPortGroupRule(
         }
     }
 
+#if 0
+    FIXIT need to select http_uri for fast_pattern
     /* http buffer contents take precedence over normal contents if
      * no normal contents have the fast_pattern option */
     pmd_uri = GetLongestPmdContent(otn, CONTENT_HTTP);
@@ -1233,6 +1233,7 @@ static int fpAddPortGroupRule(
             return 0;
         }
     }
+#endif
 
     /* If we get this far then no URI contents were added */
 
index e42699b6db0ba958f498f30d0d58e0ca7efdafce..685718bd2d1f9b23c7a365c9e7c947c38d715889 100644 (file)
@@ -51,6 +51,7 @@
 #include "treenodes.h"
 #include "pcrm.h"
 #include "fpcreate.h"
+#include "framework/cursor.h"
 #include "framework/mpse.h"
 #include "bitop.h"
 #include "perf_monitor/perf.h"
@@ -446,13 +447,12 @@ static int detection_option_tree_evaluate(
     }
 #endif
 
+    Cursor c(eval_data->p);
+
     for ( i = 0; i< root->num_children; i++)
     {
-        /* New tree, reset doe_ptr for safety */
-        UpdateDoePtr(NULL, 0);
-
         /* Increment number of events generated from that child */
-        rval += detection_option_node_evaluate(root->children[i], eval_data);
+        rval += detection_option_node_evaluate(root->children[i], eval_data, c);
     }
 
 #ifdef PPM_MGR
index 167bb140629488dc1e2b8c2f1ca86c14065a0017..10fd41c512a8a79f26188d407793fa0db0e8c1c6 100644 (file)
@@ -40,4 +40,5 @@ typedef enum _option_type_t
     RULE_OPTION_TYPE_OTHER
 } option_type_t;
 
-#endif /* RULE_OPTION_TYPES_H */
+#endif
+
index 21de6849d3e727e157de36db32047462bbe424d2..d408555505e8b26be1b67c255ef8034fba73634e 100644 (file)
@@ -43,7 +43,7 @@ struct OptFpList
     /* context data for this test */
     void *context;
     
-    int (*OptTestFunc)(void *option_data, Packet *p);
+    int (*OptTestFunc)(void* option_data, struct Cursor&, Packet*);
     
     OptFpList *next;
 
@@ -155,7 +155,7 @@ struct RuleTreeNode
     unsigned int otnRefCount;
 };
 
-typedef int (*RuleOptEvalFunc)(void *, Packet *);
+typedef int (*RuleOptEvalFunc)(void*, Cursor&, Packet*);
 OptFpList * AddOptFuncToList(RuleOptEvalFunc, OptTreeNode *);
         
 void* get_rule_type_data(OptTreeNode*, option_type_t);
index e289027a786b5f3db7f6e34c8e642e39fd86689b..5ea8a8149a620b417e9aeebf72edcf7e01329be9 100644 (file)
@@ -4,7 +4,7 @@ set (FRAMEWORK_INCLUDES
     base_api.h
     bits.h
     codec.h
-    content_buffer.h
+    cursor.h
     logger.h
     inspector.h
     ips_option.h
@@ -19,6 +19,7 @@ set (FRAMEWORK_INCLUDES
 
 add_library ( framework STATIC
     ${FRAMEWORK_INCLUDES}
+    cursor.cc
     inspector.cc
     ips_option.cc
     parameter.cc
index 23a697bb9e9d41dec70f46c4c345cfc9cba7d757..ee5871a60717fd03fd835c4973a6033982226b55 100644 (file)
@@ -8,7 +8,7 @@ x_include_HEADERS = \
 base_api.h \
 bits.h \
 codec.h \
-content_buffer.h \
+cursor.h \
 logger.h \
 inspector.h \
 ips_option.h \
@@ -21,6 +21,7 @@ so_rule.h \
 value.h
 
 libframework_a_SOURCES = \
+cursor.cc \
 inspector.cc \
 ips_option.cc \
 parameter.cc \
diff --git a/src/framework/cursor.cc b/src/framework/cursor.cc
new file mode 100644 (file)
index 0000000..74f6dbd
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+** Copyright (C) 2014 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.
+*/
+// cursor.cc author Russ Combs <rucombs@cisco.com>
+
+#include "cursor.h"
+#include "detection/detection_util.h"
+#include "protocols/packet.h"
+
+Cursor::Cursor(Packet* p)
+{
+    reset(p);
+}
+
+Cursor::Cursor(const Cursor& rhs)
+{
+    *this = rhs;
+    delta = 0;
+}
+
+void Cursor::reset(Packet* p)
+{
+    /* If AltDetect is set by calling the rule options which set it,
+     * we should use the Alt Detect before checking for any other buffers.
+     * Alt Detect will take precedence over the Alt Decode and/or packet data.
+     */
+    if ( Is_DetectFlag(FLAG_ALT_DETECT) )
+    {
+        set("pkt_data", (uint8_t *)DetectBuffer.data, DetectBuffer.len);
+    }
+    else if ( Is_DetectFlag(FLAG_ALT_DECODE) )
+    {
+        set("pkt_data", (uint8_t *)DecodeBuffer.data, DecodeBuffer.len);
+    }
+    else if( IsLimitedDetect(p) )
+    {
+        set("pkt_data", p->data, p->alt_dsize);
+    }
+    else
+    {
+        set("pkt_data", p->data, p->dsize);
+    }
+}
+
diff --git a/src/framework/cursor.h b/src/framework/cursor.h
new file mode 100644 (file)
index 0000000..1bb43de
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+** Copyright (C) 2014 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.
+*/
+// cursor.h author Russ Combs <rucombs@cisco.com>
+
+#ifndef CURSOR_H
+#define CURSOR_H
+
+#include <ctype.h>
+#include <stdint.h>
+#include <string.h>
+
+struct Packet;
+
+class Cursor
+{
+public:
+    Cursor(Packet*);
+    Cursor(const Cursor&);
+
+    bool is(const char* s)
+    { return !strcmp(name, s); };
+
+    void reset(Packet*);
+
+    void set(const char* s, const uint8_t* b, unsigned n)
+    { name = s; data = b; sz = n; pos = delta = 0; };
+
+    const uint8_t* buffer()
+    { return data; };
+
+    unsigned size()
+    { return sz; };
+
+    const uint8_t* start()
+    { return data + pos; };
+
+    unsigned length()
+    { return sz - pos; };
+
+    unsigned get_pos()
+    { return pos; };
+
+    unsigned get_delta()
+    { return delta; };
+
+    bool add_pos(unsigned n)
+    { 
+        if (pos + n > sz)
+            return false;
+        pos += n;
+        return true;
+    };
+
+    // pos and delta may go 1 byte after end
+    bool set_pos(unsigned n)
+    { 
+        if (n > sz)
+            return false;
+        pos = n;
+        return true;
+    };
+
+    bool set_delta(unsigned n)
+    {
+        if (n > sz)
+            return false;
+        delta = n;
+        return true;
+    };
+
+private:
+    const char* name;     // rule option name ("pkt_data", "http_uri", etc.)
+    const uint8_t* data;  // start of buffer
+    unsigned sz;          // size of buffer
+    unsigned pos;         // current pos
+    unsigned delta;       // loop offset
+
+};
+
+#endif
+
index 478df8c300f72fce61ba6fb3047c2af3799c3fa6..e397322bc8b4218a087e5bca950d353252be0883 100644 (file)
@@ -109,7 +109,6 @@ typedef Inspector* (*InspectNew)(Module*);
 typedef void (*InspectDelFunc)(Inspector*);
 typedef void (*InspectFunc)();
 typedef class Session* (*InspectSsnFunc)(class Flow*);
-typedef struct ContentBuffer* (*InspectBufFunc)(unsigned);
 
 // FIXIT ensure all provide stats
 struct InspectApi
@@ -121,9 +120,6 @@ struct InspectApi
     const char* service;   // nullptr when type != IT_SERVICE
     //ServiceTag tags;     // null terminated list of tags
 
-    // list of thread local detection buffers captured by inspector
-    const char* contents;  // space separated, eg "foo_a foo_b foo_c" 
-
     // main thread funcs - parse time data only
     InspectFunc init;      // allocate process static data
     InspectFunc term;      // release init() data
@@ -137,7 +133,6 @@ struct InspectApi
     InspectFunc sum;       // accumulate stats
     InspectFunc stats;     // output stats
     InspectFunc reset;     // clear stats
-    InspectBufFunc getbuf; // 0-based, eg getbuf(1) means foo_b above
 };
 
 #endif
index d02ec2be32f7b9224d84716b04341bb2e85bce56..56764223015dc3e44476232d4943bb807575fb53 100644 (file)
@@ -56,7 +56,7 @@ public:
     // packet threads
     virtual void config(SnortConfig*) { };
     virtual bool is_relative() { return false; };
-    virtual int eval(Packet*) { return true; };
+    virtual int eval(struct Cursor&, Packet*) { return true; };
     virtual void action(Packet*) { };
 
     option_type_t get_type() const { return type; };
@@ -103,10 +103,10 @@ struct IpsApi
     IpsChkFunc verify;
 };
 
-static inline int ips_option_eval(void* v, Packet* p)
+static inline int ips_option_eval(void* v, Cursor& c, Packet* p)
 {
     IpsOption* opt = (IpsOption*)v;
-    return opt->eval(p);
+    return opt->eval(c, p);
 }
 
 #endif
index 26b0e68cd007a5094fe34f2fdd77f5831c26d2a4..24fe711138385c295ea4c83f3e1f19156be45e97 100644 (file)
@@ -23,6 +23,7 @@ SET( PLUGIN_LIST
     ips_isdataat.cc 
     ips_itype.cc 
     ips_pkt_data.cc
+    ips_raw_data.cc
     ips_react.cc
     ips_resp.cc
     ips_rpc.cc
@@ -57,9 +58,9 @@ set (IPS_SOURCES
     ips_options.h
     ips_pcre.cc 
     ips_pcre.h
+    ips_replace.cc 
+    ips_replace.h
     ips_so.cc
-    replace.cc 
-    replace.h
 )
 
 
@@ -94,6 +95,7 @@ else (STATIC_IPS_OPTIONS)
     add_shared_library(ips_isdataat ips_options ips_isdataat.cc)
     add_shared_library(ips_itype ips_options ips_itype.cc)
     add_shared_library(ips_pkt_data ips_options ips_pkt_data.cc)
+    add_shared_library(ips_raw_data ips_options ips_raw_data.cc)
     add_shared_library(ips_react ips_options ips_react.cc)
     add_shared_library(ips_resp ips_options ips_resp.cc)
     add_shared_library(ips_rpc ips_options ips_rpc.cc)
index be835d84e37a9ef9288e94e945f41a8c74e992f2..2f50097ed1b9f9c3cb3a6c478f89688307ffc6a1 100644 (file)
@@ -24,6 +24,7 @@ ips_ipopts.cc \
 ips_isdataat.cc \
 ips_itype.cc \
 ips_pkt_data.cc \
+ips_raw_data.cc \
 ips_react.cc \
 ips_resp.cc \
 ips_rpc.cc \
@@ -46,8 +47,8 @@ ips_ip_proto.cc ips_ip_proto.h \
 ips_luajit.cc ips_luajit.h \
 ips_options.cc ips_options.h \
 ips_pcre.cc ips_pcre.h \
-ips_so.cc \
-replace.cc replace.h
+ips_replace.cc ips_replace.h \
+ips_so.cc
 
 if STATIC_IPS_OPTIONS
 libips_options_a_SOURCES += $(plugin_list)
@@ -149,6 +150,11 @@ libips_pkt_data_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
 libips_pkt_data_la_LDFLAGS = -export-dynamic -shared
 libips_pkt_data_la_SOURCES = ips_pkt_data.cc
 
+optlib_LTLIBRARIES += libips_raw_data.la
+libips_raw_data_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
+libips_raw_data_la_LDFLAGS = -export-dynamic -shared
+libips_raw_data_la_SOURCES = ips_raw_data.cc
+
 optlib_LTLIBRARIES += libips_react.la
 libips_react_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
 libips_react_la_LDFLAGS = -export-dynamic -shared
index d88f7e6387339d7de89d3fd0f2aab8aa218d631d..d9ef2a3676c6333e23b6491faf924025b01c4252 100644 (file)
@@ -69,7 +69,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     TcpAckCheckData config;
@@ -111,7 +111,7 @@ bool TcpAckOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int TcpAckOption::eval(Packet *p)
+int TcpAckOption::eval(Cursor&, Packet *p)
 {
     TcpAckCheckData *ackCheckData = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 191d13c62bacb56a5d71639d342fdb5424ee2192..758f7596768bae58a2ec0f9b0fa5c878c06c8a74 100644 (file)
@@ -115,7 +115,7 @@ public:
     bool is_relative()
     { return ( config.offset_type == REL_OFFSET ); };
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     ASN1_CTXT config;
@@ -174,7 +174,7 @@ bool Asn1Option::operator==(const IpsOption& rhs) const
     return false;
 }
 
-int Asn1Option::eval(Packet *p)
+int Asn1Option::eval(Cursor&, Packet *p)
 {
     PROFILE_VARS;
 
index a890ef244886db892161226ccb235fa4cd59dd91..0e4381c5a87a4e9d4239f892e080b3491e336110 100644 (file)
@@ -43,6 +43,7 @@
 #include "fpdetect.h"
 #include "detection/detection_defines.h"
 #include "detection/detection_util.h"
+#include "framework/cursor.h"
 #include "framework/ips_option.h"
 
 #ifdef PERF_PROFILING
@@ -64,10 +65,10 @@ class Base64DataOption : public IpsOption
 public:
     Base64DataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BASE64_DATA) { };
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 };
 
-int Base64DataOption::eval(Packet *p)
+int Base64DataOption::eval(Cursor& c, Packet *p)
 {
     int rval = DETECTION_OPTION_NO_MATCH;
     PROFILE_VARS;
@@ -80,8 +81,7 @@ int Base64DataOption::eval(Packet *p)
         return rval;
     }
 
-    SetDoePtr(base64_decode_buf, DOE_BUF_STD);
-    SetAltDetect(base64_decode_buf, (uint16_t)base64_decode_size);
+    c.set(s_name, base64_decode_buf, base64_decode_size);
     rval = DETECTION_OPTION_MATCH;
 
     PREPROC_PROFILE_END(base64DataPerfStats);
index f6b3183a4f5b8a9b75e52f2a7992910233d55280..82b9fc60bf58708aed0e0e670de9eb07b1d35e8e 100644 (file)
@@ -81,7 +81,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     Base64DecodeData config;
@@ -126,7 +126,7 @@ bool Base64DecodeOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int Base64DecodeOption::eval(Packet *p)
+int Base64DecodeOption::eval(Cursor&, Packet *p)
 {
     int rval = DETECTION_OPTION_NO_MATCH;
     const uint8_t *start_ptr = NULL;
index a385a79ef13fb80236f65418058705312f6b1205..f2b78ecae7e1e6e3128a20300fcb937ae9284c4b 100644 (file)
@@ -35,6 +35,7 @@
 #include "extract.h"
 #include "fpdetect.h"
 #include "framework/ips_option.h"
+#include "framework/cursor.h"
 
 #ifdef PERF_PROFILING
 static THREAD_LOCAL PreprocStats byteExtractPerfStats;
@@ -91,7 +92,7 @@ public:
     bool is_relative()
     { return (config.relative_flag == 1); };
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     ByteExtractData config;
@@ -152,15 +153,13 @@ bool ByteExtractOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int ByteExtractOption::eval(Packet *p)
+int ByteExtractOption::eval(Cursor& c, Packet *p)
 {
     ByteExtractData *data = &config;
-    int ret, bytes_read, dsize;
-    const uint8_t *ptr, *start, *end;
+    int ret, bytes_read;
     uint32_t *value;
-    uint8_t rst_doe_flags = 1;
-    PROFILE_VARS;
 
+    PROFILE_VARS;
     PREPROC_PROFILE_START(byteExtractPerfStats);
 
     if (data == NULL || p == NULL)
@@ -169,36 +168,13 @@ int ByteExtractOption::eval(Packet *p)
         return DETECTION_OPTION_NO_MATCH;
     }
 
-    /* setup our fun pointers */
-    if (Is_DetectFlag(FLAG_ALT_DETECT))
-    {
-        dsize = DetectBuffer.len;
-        start = DetectBuffer.data;
-    }
-    else if (Is_DetectFlag(FLAG_ALT_DECODE))
-    {
-        dsize = DecodeBuffer.len;
-        start = DecodeBuffer.data;
-    }
-    else
-    {
-        if(IsLimitedDetect(p))
-            dsize = p->alt_dsize;
-        else
-            dsize = p->dsize;
-        start = p->data;
-    }
-
-    if (data->relative_flag)
-    {
-        ptr = doe_ptr;
-        rst_doe_flags = 0;
-    }
-    else
-        ptr = start;
+    const uint8_t* start = c.buffer();
+    int dsize = c.size();
 
+    const uint8_t* ptr = data->relative_flag ? c.start() : c.buffer();
     ptr += data->offset;
-    end = start + dsize;
+
+    const uint8_t* end = start + dsize;
     value = &(extracted_values[data->var_number]);
 
     /* check bounds */
@@ -244,7 +220,7 @@ int ByteExtractOption::eval(Packet *p)
     }
 
     /* push doe_ptr */
-    UpdateDoePtr((ptr + bytes_read), rst_doe_flags);
+    c.add_pos(bytes_read);
 
     /* this rule option always "matches" if the read is performed correctly */
     PREPROC_PROFILE_END(byteExtractPerfStats);
index 93000ed5311086d56d9e3d0fc8a6e222eba17c16..5a63c750ec72ccf620c74823f8593b5857156776 100644 (file)
@@ -89,6 +89,7 @@
 #include "sfhashfcn.h"
 #include "detection/detection_defines.h"
 #include "detection/detection_util.h"
+#include "framework/cursor.h"
 #include "framework/ips_option.h"
 
 #ifdef PERF_PROFILING
@@ -135,7 +136,7 @@ public:
     bool is_relative()
     { return (config.relative_flag == 1); };
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     ByteJumpData config;
@@ -203,102 +204,52 @@ bool ByteJumpOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int ByteJumpOption::eval(Packet *p)
+int ByteJumpOption::eval(Cursor& c, Packet*)
 {
     ByteJumpData *bjd = (ByteJumpData *)&config;
     int rval = DETECTION_OPTION_NO_MATCH;
-    uint32_t value = 0;
-    uint32_t jump_value = 0;
+    uint32_t jump = 0;
     uint32_t payload_bytes_grabbed = 0;
     uint32_t extract_offset;
-    int32_t tmp = 0;
-    int dsize;
-    const uint8_t *base_ptr, *end_ptr, *start_ptr;
-    uint8_t rst_doe_flags = 1;
-    PROFILE_VARS;
+    int32_t offset;
 
+    PROFILE_VARS;
     PREPROC_PROFILE_START(byteJumpPerfStats);
 
-    if (Is_DetectFlag(FLAG_ALT_DETECT))
-    {
-        dsize = DetectBuffer.len;
-        start_ptr = DetectBuffer.data;
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                    "Using Alternative Detect buffer!\n"););
-    }
-    else if(Is_DetectFlag(FLAG_ALT_DECODE))
-    {
-        dsize = DecodeBuffer.len;
-        start_ptr = DecodeBuffer.data;
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                    "Using Alternative Decode buffer!\n"););
-    }
-    else
-    {
-        start_ptr = p->data;
-        if(IsLimitedDetect(p))
-            dsize = p->alt_dsize;
-        else
-            dsize = p->dsize;
-    }
-
-    DEBUG_WRAP(
-            DebugMessage(DEBUG_PATTERN_MATCH,"[*] byte jump firing...\n");
-            DebugMessage(DEBUG_PATTERN_MATCH,"payload starts at %p\n", start_ptr);
-            );  /* END DEBUG_WRAP */
-
-    /* save off whatever our ending pointer is */
-    end_ptr = start_ptr + dsize;
-    //base_ptr = start_ptr;
+    const uint8_t *base_ptr, *end_ptr, *start_ptr;
+    int dsize;
 
     /* Get values from byte_extract variables, if present. */
     if (bjd->offset_var >= 0 && bjd->offset_var < NUM_BYTE_EXTRACT_VARS)
     {
         GetByteExtractValue(&extract_offset, bjd->offset_var);
-        bjd->offset = (int32_t) extract_offset;
+        offset = (int32_t) extract_offset;
     }
+    else
+        offset = bjd->offset;
 
-    if(bjd->relative_flag && doe_ptr)
-    {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                "Checking relative offset!\n"););
-
-        /* @todo: possibly degrade to use the other buffer, seems non-intuitive
-         *  Because doe_ptr can be "end" in the last match,
-         *  use end + 1 for upper bound
-         *  Bound checked also after offset is applied
-         *  (see byte_extract() and string_extract())
-         */
-        if(!inBounds(start_ptr, end_ptr + 1, doe_ptr))
-        {
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                    "[*] byte jump bounds check failed..\n"););
-
-            PREPROC_PROFILE_END(byteJumpPerfStats);
-            return rval;
-        }
+    start_ptr = c.buffer();
+    dsize = c.size();
+    end_ptr = start_ptr + dsize;
 
-        base_ptr = doe_ptr + bjd->offset;
-        rst_doe_flags = 0;
+    if( bjd->relative_flag )
+    {
+        base_ptr = c.start() + offset;
     }
     else
     {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                "checking absolute offset %d\n", bjd->offset););
-        base_ptr = start_ptr + bjd->offset;
+        base_ptr = c.buffer() + offset;
     }
 
-    /* Both of the extraction functions contain checks to insure the data
+    /* Both of the extraction functions contain checks to ensure the data
      * is always inbounds */
 
-    if(!bjd->data_string_convert_flag)
+    if ( !bjd->data_string_convert_flag )
     {
-        if(byte_extract(bjd->endianess, bjd->bytes_to_grab,
-                        base_ptr, start_ptr, end_ptr, &value))
+        if ( byte_extract(
+                bjd->endianess, bjd->bytes_to_grab,
+                base_ptr, start_ptr, end_ptr, &jump) )
         {
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                    "Byte Extraction Failed\n"););
-
             PREPROC_PROFILE_END(byteJumpPerfStats);
             return rval;
         }
@@ -307,76 +258,39 @@ int ByteJumpOption::eval(Packet *p)
     }
     else
     {
-        payload_bytes_grabbed = tmp = string_extract(bjd->bytes_to_grab, bjd->base,
-                                               base_ptr, start_ptr, end_ptr, &value);
+        int32_t tmp = string_extract(
+            bjd->bytes_to_grab, bjd->base,
+            base_ptr, start_ptr, end_ptr, &jump);
+
         if (tmp < 0)
         {
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                    "Byte Extraction Failed\n"););
-
             PREPROC_PROFILE_END(byteJumpPerfStats);
             return rval;
         }
-
+        payload_bytes_grabbed = tmp;
     }
 
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                            "grabbed %d of %d bytes, value = %08X\n",
-                            payload_bytes_grabbed, bjd->bytes_to_grab, value););
-
-    /* Adjust the jump_value (# bytes to jump forward) with the multiplier. */
     if (bjd->multiplier)
-        jump_value = value * bjd->multiplier;
-    else
-        jump_value = value;
-
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                            "grabbed %d of %d bytes, after multiplier value = %08X\n",
-                            payload_bytes_grabbed, bjd->bytes_to_grab, jump_value););
-
+        jump *= bjd->multiplier;
 
     /* if we need to align on 32-bit boundries, round up to the next
      * 32-bit value
      */
     if(bjd->align_flag)
     {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                    "offset currently at %d\n", jump_value););
-        if ((jump_value % 4) != 0)
+        if ((jump % 4) != 0)
         {
-            jump_value += (4 - (jump_value % 4));
+            jump += (4 - (jump % 4));
         }
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                    "offset aligned to %d\n", jump_value););
     }
 
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                            "Grabbed %d bytes at offset %d, value = 0x%08X\n",
-                            payload_bytes_grabbed, bjd->offset, jump_value););
-
-    if(bjd->from_beginning_flag)
-    {
-        /* Reset base_ptr if from_beginning */
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                "jumping from beginning %d bytes\n", jump_value););
-        base_ptr = start_ptr;
-
-        /* from base, push doe_ptr ahead "value" number of bytes */
-        SetDoePtr((base_ptr + jump_value), DOE_BUF_STD);
-
-    }
-    else
-    {
-        UpdateDoePtr((base_ptr + payload_bytes_grabbed + jump_value), rst_doe_flags);
-    }
+    if ( !bjd->from_beginning_flag )
+        jump += payload_bytes_grabbed;
 
-    /* now adjust using post_offset -- before bounds checking */
-    doe_ptr += bjd->post_offset;
+    jump += bjd->post_offset;
 
-    if(!inBounds(start_ptr, end_ptr, doe_ptr))
+    if ( !c.set_pos(jump) )
     {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                "tmp ptr is not in bounds %p\n", doe_ptr););
         PREPROC_PROFILE_END(byteJumpPerfStats);
         return rval;
     }
index c196bb9c6e7347d5c2ad1b1e7676f77e21af2342..21d74c25e8f9a2bec43218c5df85f5e98fd5e664 100644 (file)
@@ -185,7 +185,7 @@ public:
     bool is_relative()
     { return ( config.relative_flag == 1 ); };
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     ByteTestData config;
@@ -252,7 +252,7 @@ bool ByteTestOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int ByteTestOption::eval(Packet *p)
+int ByteTestOption::eval(Cursor&, Packet *p)
 {
     ByteTestData *btd = (ByteTestData *)&config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 4ac446cc50ac8efb9555a507d0f78eea3f6b5f87..9b4ee7762efde965e6a26ba9efbf0f462e5e3d57 100644 (file)
 #endif
 
 #include "snort_types.h"
-#include "replace.h"
 #include "snort_bounds.h"
 #include "detection/treenodes.h"
 #include "snort_debug.h"
-#include "mstring.h"
+#include "parser/mstring.h"
+#include "utils/boyer_moore.h"
 #include "util.h"
-#include "parser.h"
+#include "parser/parser.h"
 #include "sfhashfcn.h"
+#include "framework/cursor.h"
 #include "framework/ips_option.h"
 #include "snort.h"
 #include "profiler.h"
 
 #ifdef PERF_PROFILING
 static THREAD_LOCAL PreprocStats contentPerfStats;
-static THREAD_LOCAL PreprocStats uricontentPerfStats;
 
 static PreprocStats* con_get_profile(const char* key)
 {
     if ( !strcmp(key, "content") )
         return &contentPerfStats;
 
-    if ( !strcmp(key, "uricontent") )
-        return &uricontentPerfStats;
-
     return nullptr;
 }
 #endif
 
-static int CheckANDPatternMatch(PatternMatchData*, Packet*);
-static int CheckUriPatternMatch(PatternMatchData*, Packet*);
+static int CheckANDPatternMatch(PatternMatchData*, Cursor&);
 
 class ContentOption : public IpsOption
 {
@@ -92,23 +88,13 @@ public:
     void set_data(PatternMatchData* pmd)
     { config = pmd; };
 
-    int eval(Packet* p)
-    { return CheckANDPatternMatch(config, p); };
+    int eval(Cursor& c, Packet*)
+    { return CheckANDPatternMatch(config, c); };
 
 protected:
     PatternMatchData* config;
 };
 
-class UriContentOption : public ContentOption
-{
-public:
-    UriContentOption(PatternMatchData* c) : 
-        ContentOption(c, "uricontent", RULE_OPTION_TYPE_CONTENT_URI) { };
-
-    int eval(Packet* p)
-    { return CheckUriPatternMatch(config, p); };
-};
-
 //-------------------------------------------------------------------------
 // class methods
 //-------------------------------------------------------------------------
@@ -127,11 +113,6 @@ ContentOption::~ContentOption()
     if(pmd->shift_stride)
         free(pmd->shift_stride);
 
-    if (pmd->replace_buf)
-        free(pmd->replace_buf);
-    if ( pmd->replace_depth )
-        free(pmd->replace_depth);
-
     free(pmd->last_check);
     free(pmd);
 }
@@ -147,30 +128,16 @@ uint32_t ContentOption::hash() const
 
     mix(a,b,c);
 
-    a += pmd->distance;
-    b += pmd->within;
-    c += pmd->rawbytes;
-
-    mix(a,b,c);
-
-    a += pmd->nocase;
-    b += pmd->use_doe;
-    c += pmd->http_buffer;
-
-    mix(a,b,c);
-
     a += pmd->pattern_size;
-    b += pmd->replace_size;
-    c += pmd->pattern_max_jump_size;
+    b += pmd->use_doe;
+    c += pmd->match_delta;
 
     mix(a,b,c);
 
     if ( pmd->pattern_size )
         mix_str(a,b,c,pmd->pattern_buf, pmd->pattern_size);
 
-    if ( pmd->replace_size )
-        mix_str(a,b,c,pmd->replace_buf, pmd->replace_size);
-
+    a += pmd->no_case;
     b += pmd->fp;
     c += pmd->fp_only;
 
@@ -184,8 +151,6 @@ uint32_t ContentOption::hash() const
     mix(a,b,c);
 
     a += pmd->depth_var;
-    b += pmd->distance_var;
-    c += pmd->within_var;
 
     final(a,b,c);
 
@@ -202,21 +167,17 @@ bool ContentOption::operator==(const IpsOption& ips) const
     PatternMatchData *right = rhs.config;
     unsigned int i;
 
-    if (left->buffer_func != right->buffer_func)
-        return false;
-
     /* Sizes will be most different, check that first */
     if ((left->pattern_size != right->pattern_size) ||
-        (left->replace_size != right->replace_size) ||
-        (left->nocase != right->nocase))
+        (left->no_case != right->no_case))
         return false;
 
     /* Next compare the patterns for uniqueness */
     if (left->pattern_size)
     {
-        if (left->nocase)
+        if (left->no_case)
         {
-            /* If nocase is set, do case insensitive compare on pattern */
+            /* If no_case is set, do case insensitive compare on pattern */
             for (i=0;i<left->pattern_size;i++)
             {
                 if (toupper(left->pattern_buf[i]) != toupper(right->pattern_buf[i]))
@@ -227,7 +188,7 @@ bool ContentOption::operator==(const IpsOption& ips) const
         }
         else
         {
-            /* If nocase is not set, do case sensitive compare on pattern */
+            /* If no_case is not set, do case sensitive compare on pattern */
             if (memcmp(left->pattern_buf, right->pattern_buf, left->pattern_size) != 0)
             {
                 return false;
@@ -235,34 +196,18 @@ bool ContentOption::operator==(const IpsOption& ips) const
         }
     }
 
-    /* Check the replace pattern if exists */
-    if (left->replace_size)
-    {
-        if (memcmp(left->replace_buf, right->replace_buf, left->replace_size) != 0)
-        {
-            return false;
-        }
-    }
-
     /* Now check the rest of the options */
     if ((left->exception_flag == right->exception_flag) &&
         (left->offset == right->offset) &&
         (left->depth == right->depth) &&
-        (left->distance == right->distance) &&
-        (left->within == right->within) &&
-        (left->rawbytes == right->rawbytes) &&
         (left->use_doe == right->use_doe) &&
-        (left->http_buffer == right->http_buffer) &&
-        (left->search == right->search) &&
-        (left->pattern_max_jump_size == right->pattern_max_jump_size) &&
+        (left->match_delta == right->match_delta) &&
         (left->fp == right->fp) &&
         (left->fp_only == right->fp_only) &&
         (left->fp_offset == right->fp_offset) &&
         (left->fp_length == right->fp_length) &&
         (left->offset_var == right->offset_var) &&
-        (left->depth_var == right->depth_var) &&
-        (left->distance_var == right->distance_var) &&
-        (left->within_var == right->within_var) )
+        (left->depth_var == right->depth_var) )
     {
         return true;
     }
@@ -281,8 +226,6 @@ static PatternMatchData* new_pmd()
     /* Set any non-zero default values here. */
     pmd->offset_var = BYTE_EXTRACT_NO_VAR;
     pmd->depth_var = BYTE_EXTRACT_NO_VAR;
-    pmd->distance_var = BYTE_EXTRACT_NO_VAR;
-    pmd->within_var = BYTE_EXTRACT_NO_VAR;
 
     return pmd;
 }
@@ -331,82 +274,17 @@ static int32_t ParseInt(const char* data, const char* tag)
     return value;
 }
 
-/* Options that can't be used with http content modifiers.  Additionally
- * http_inspect preprocessor needs to be enabled */
-static void ValidateHttpContentModifiers(
-    SnortConfig*, PatternMatchData *pmd)
-{
-    if (pmd == NULL)
-        ParseError("Please place 'content' rules before http content modifiers");
-
-#if 0
-    // FIXIT HI should make the content modifiers available and
-    // if not available parsing of the modifier should fail
-    if (!IsPreprocEnabled(sc, PP_HTTPINSPECT))
-    {
-        ParseError("Please enable the HTTP Inspect preprocessor "
-                "before using the http content modifiers");
-    }
-#endif
-
-    if (pmd->replace_buf != NULL)
-    {
-        ParseError("'replace' option is not supported in conjunction with "
-                "http content modifiers");
-    }
-
-    if (pmd->rawbytes == 1)
-    {
-        ParseError("Cannot use 'rawbytes' and http content as modifiers for "
-                "the same 'content'");
-    }
-}
-
-static void set_last_type(OptTreeNode *otn, option_type_t type)
-{
-    OptFpList* fpl = otn ? otn->opt_func : nullptr;
-    OptFpList* last = nullptr;
-
-    while ( fpl )
-    {
-        if ( (fpl->type == RULE_OPTION_TYPE_CONTENT) ||
-             (fpl->type == RULE_OPTION_TYPE_CONTENT_URI) )
-        {
-            last = fpl;
-        }
-        fpl = fpl->next;
-    }
-    if ( last )
-        last->type = type;
-}
-
-/* This is used if we get an http content modifier, since specifying "content"
- * defaults to the RULE_OPTION_TYPE_CONTENT list.  We need to move the pmd to the
- * RULE_OPTION_TYPE_CONTENT_URI list */
-static void MovePmdToUriDsList(OptTreeNode *otn, PatternMatchData *pmd)
-{
-    set_last_type(otn, RULE_OPTION_TYPE_CONTENT_URI);  // FIXIT make this unnecessary
-    pmd->buffer_func = CHECK_URI_PATTERN_MATCH;
-}
-
+// FIXIT the following comment is no longer true;
 /* Since each content modifier can be parsed as a rule option, do this check
  * after parsing the entire rule in FinalizeContentUniqueness() */
 static void ValidateContent(
-    SnortConfig* sc, PatternMatchData *pmd, int type){
+    SnortConfig*, PatternMatchData *pmd, int)
+{
     if (pmd == NULL)
         return;
 
     if (pmd->fp)
     {
-        if ((type == RULE_OPTION_TYPE_CONTENT_URI) && !IsHttpBufFpEligible(pmd->http_buffer))
-
-        {
-            ParseError(
-                "Cannot use the fast_pattern content modifier for a lone "
-                "http cookie/http raw uri /http raw header /http raw cookie "
-                "/status code / status msg /http method buffer content.");
-        }
-
         if (pmd->use_doe || (pmd->offset != 0) || (pmd->depth != 0))
         {
             if (pmd->exception_flag)
@@ -426,19 +304,10 @@ static void ValidateContent(
 
         if (pmd->fp_only)
         {
-            if (pmd->replace_buf != NULL)
-            {
-                ParseError(
-                    "Fast pattern only contents cannot use replace modifier.");
-            }
-
             if (pmd->exception_flag)
                 ParseError("Fast pattern only contents cannot be negated.");
         }
     }
-
-    if (type == RULE_OPTION_TYPE_CONTENT_URI)
-        ValidateHttpContentModifiers(sc, pmd);
 }
 
 static void make_precomp(PatternMatchData * idx)
@@ -528,8 +397,7 @@ static unsigned int GetMaxJumpSize(char *data, int data_len)
 
 PatternMatchData* get_pmd(OptFpList* ofl)
 {
-    if ( (ofl->type != RULE_OPTION_TYPE_CONTENT) &&
-         (ofl->type != RULE_OPTION_TYPE_CONTENT_URI) )
+    if ( ofl->type != RULE_OPTION_TYPE_CONTENT )
         return nullptr;
 
     ContentOption* opt = (ContentOption*)ofl->context;
@@ -550,7 +418,7 @@ bool is_unbounded(void* pv)
 {
     ContentOption* opt = (ContentOption*)pv;
     PatternMatchData* pmd = opt->get_data();
-    return ( pmd->within == 0 );
+    return ( pmd->depth == 0 );
 }
 
 //-------------------------------------------------------------------------
@@ -560,266 +428,99 @@ bool is_unbounded(void* pv)
 /*
  * single search function.
  *
- * data = ptr to buffer to search
- * dlen = distance to the back of the buffer being tested, validated
- *        against offset + depth before function entry (not distance/within)
- * pmd = pointer to pattern match data struct
- * nocase = 0 means case sensitve, 1 means case insensitive
- *
  * return  1 for found
  * return  0 for not found
  * return -1 for error (search out of bounds)
  */
-// FIXIT PMD
-static int uniSearchReal(const char *data, int dlen, PatternMatchData *pmd, int nocase)
+static int uniSearchReal(PatternMatchData* pmd, Cursor& c)
 {
-    /*
-     * in theory computeDepth doesn't need to be called because the
-     * depth + offset adjustments have been made by the calling function
-     */
-    int depth = dlen;
-    int success = 0;
-    const char *start_ptr = data;
-    const char *end_ptr = data + dlen;
-    const char *base_ptr;// = start_ptr;
-    uint32_t extract_offset, extract_depth, extract_distance, extract_within;
-
-    if(pmd->use_doe != 1)
-    {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "NOT Using Doe Ptr\n"););
-        UpdateDoePtr(NULL, 0); /* get rid of all our pattern match state */
-    }
+    int offset, depth;
 
     /* Get byte_extract variables */
-    // FIXIT these need to be thread local
     if (pmd->offset_var >= 0 && pmd->offset_var < NUM_BYTE_EXTRACT_VARS)
     {
-        GetByteExtractValue(&extract_offset, pmd->offset_var);
-        pmd->offset = (int) extract_offset;
+        uint32_t extract;
+        GetByteExtractValue(&extract, pmd->offset_var);
+        offset = (int) extract;
     }
+    else
+        offset = pmd->offset;
+
     if (pmd->depth_var >= 0 && pmd->depth_var < NUM_BYTE_EXTRACT_VARS)
     {
-        GetByteExtractValue(&extract_depth, pmd->depth_var);
-        pmd->depth = (int) extract_depth;
-    }
-    if (pmd->distance_var >= 0 && pmd->distance_var < NUM_BYTE_EXTRACT_VARS)
-    {
-        GetByteExtractValue(&extract_distance, pmd->distance_var);
-        pmd->distance = (int) extract_distance;
-    }
-    if (pmd->within_var >= 0 && pmd->within_var < NUM_BYTE_EXTRACT_VARS)
-    {
-        GetByteExtractValue(&extract_within, pmd->within_var);
-        pmd->within = (u_int) extract_within;
+        uint32_t extract;
+        GetByteExtractValue(&extract, pmd->depth_var);
+        depth = (int) extract;
     }
+    else
+        depth = pmd->depth;
 
-    // Set our initial starting point
-    if (doe_ptr)
-    {
-        // Sanity check to make sure the doe_ptr is within the buffer we're
-        // searching.  It could be at the very end of the buffer due to a
-        // previous match, but may have a negative distance here.
-        if (((char *)doe_ptr < start_ptr) || ((char *)doe_ptr > end_ptr))
-        {
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Returning because "
-                        "doe_ptr isn't within the buffer we're searching: "
-                        "start_ptr: %p, end_ptr: %p, doe_ptr: %p\n",
-                        start_ptr, end_ptr, doe_ptr););
-            return -1;
-        }
+    int pos = c.get_delta();
 
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                    "Setting base_ptr to doe_ptr (%p)\n", doe_ptr););
+    if ( !pos && pmd->use_doe )
+        pos = c.get_pos();
 
-        base_ptr = (const char *)doe_ptr;
-        depth = dlen - ((char *)doe_ptr - data);
-    }
-    else
-    {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                    "Setting base_ptr to start_ptr (%p)\n", start_ptr););
+    pos += offset;
 
-        base_ptr = start_ptr;
-        depth = dlen;
-    }
+    if ( pos < 0 )
+        pos = 0;
 
-    // Adjust base_ptr and depth based on distance/within
-    // or offset/depth parameters.
-    if ((pmd->distance != 0) || (pmd->within != 0))
-    {
-        if (pmd->distance != 0)
-        {
-            base_ptr += pmd->distance;
-            depth -= pmd->distance;
-        }
+    int len = c.size() - pos;
 
-        // If the distance is negative and puts us before start_ptr
-        // set base_ptr to start_ptr and adjust depth based on within.
-        if (base_ptr < start_ptr)
-        {
-            int delta = (int)pmd->within - (start_ptr - base_ptr);
-            base_ptr = start_ptr;
-            depth = ((pmd->within == 0) || (delta > dlen)) ? dlen : delta;
-        }
-        else if ((pmd->within != 0) && ((int)pmd->within < depth))
-        {
-            depth = (int)pmd->within;
-        }
-    }
-    else if ((pmd->offset != 0) || (pmd->depth != 0))
-    {
-        if (pmd->offset != 0)
-        {
-            base_ptr += pmd->offset;
-            depth -= pmd->offset;
-        }
+    if ( !depth || len < depth )
+        depth = len;
 
-        if ((pmd->depth != 0) && (pmd->depth < depth))
-            depth = pmd->depth;
-    }
+    unsigned end = pos + pmd->pattern_size;
 
     // If the pattern size is greater than the amount of data we have to
     // search, there's no way we can match, but return 0 here for the
     // case where the match is inverted and there is at least some data.
-    if ((int)pmd->pattern_size > depth)
+    if ( end > c.size() || (int)end > pos + depth )
     {
-        if (pmd->exception_flag && (depth > 0))
+        if ( pmd->exception_flag && (depth > 0) )
             return 0;
 
         return -1;
     }
 
-#ifdef DEBUG_MSGS
-    {
-        char *hexbuf;
-
-        assert(depth <= dlen);
-
-        DebugMessage(DEBUG_PATTERN_MATCH, "uniSearchReal:\n ");
-
-        hexbuf = hex((u_char *)pmd->pattern_buf, pmd->pattern_size);
-        DebugMessage(DEBUG_PATTERN_MATCH, "   p->data: %p\n   doe_ptr: %p\n   "
-                "base_ptr: %p\n   depth: %d\n   searching for: %s\n",
-                data, doe_ptr, base_ptr, depth, hexbuf);
-        free(hexbuf);
-    }
-#endif /* DEBUG_MSGS */
+    const uint8_t* base = c.buffer() + pos;
+    int found;
 
-    if(nocase)
+    if ( pmd->no_case )
     {
-        success = mSearchCI(base_ptr, depth,
-                            pmd->pattern_buf,
-                            pmd->pattern_size,
-                            pmd->skip_stride,
-                            pmd->shift_stride);
+        found = mSearchCI(
+            (const char*)base, depth, pmd->pattern_buf, pmd->pattern_size,
+            pmd->skip_stride, pmd->shift_stride);
     }
     else
     {
-        success = mSearch(base_ptr, depth,
-                          pmd->pattern_buf,
-                          pmd->pattern_size,
-                          pmd->skip_stride,
-                          pmd->shift_stride);
+        found = mSearch(
+            (const char*)base, depth, pmd->pattern_buf, pmd->pattern_size,
+            pmd->skip_stride, pmd->shift_stride);
     }
 
+    c.set_delta(pos + pmd->match_delta);
 
-#ifdef DEBUG_MSGS
-    if(success)
+    if ( found >= 0 )
     {
-        DebugMessage(DEBUG_PATTERN_MATCH, "matched, doe_ptr: %p (%d)\n",
-                     doe_ptr, ((char *)doe_ptr - data));
+        c.set_pos(pos + found + pmd->pattern_size);
+        return 1;
     }
-#endif
-
-    return success;
-}
 
-/*
- * case sensitive search
- *
- * data = ptr to buffer to search
- * dlen = distance to the back of the buffer being tested, validated
- *        against offset + depth before function entry (not distance/within)
- * pmd = pointer to pattern match data struct
- */
-
-static int uniSearch(const char *data, int dlen, PatternMatchData *pmd)
-{
-    return uniSearchReal(data, dlen, pmd, 0);
-}
-
-/*
- * case insensitive search
- *
- * data = ptr to buffer to search
- * dlen = distance to the back of the buffer being tested, validated
- *        against offset + depth before function entry (not distance/within)
- * pmd = pointer to pattern match data struct
- */
-static int uniSearchCI(const char *data, int dlen, PatternMatchData *pmd)
-{
-    return uniSearchReal(data, dlen, pmd, 1);
+    return 0;
 }
 
-static int CheckANDPatternMatch(PatternMatchData* idx, Packet *p)
+static int CheckANDPatternMatch(PatternMatchData* idx, Cursor& c)
 {
     int rval = DETECTION_OPTION_NO_MATCH;
     int found = 0;
-    int dsize;
-    char *dp;
-    PROFILE_VARS;
 
+    PROFILE_VARS;
     PREPROC_PROFILE_START(contentPerfStats);
 
     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "CheckPatternANDMatch: "););
 
-    if(idx->rawbytes == 0)
-    {
-        if(Is_DetectFlag(FLAG_ALT_DETECT))
-        {
-            dsize = DetectBuffer.len;
-            dp = (char *) DetectBuffer.data;
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                        "Using Alternative Detect buffer!\n"););
-        }
-        else if(Is_DetectFlag(FLAG_ALT_DECODE))
-        {
-            dsize = DecodeBuffer.len;
-            dp = (char *) DecodeBuffer.data;
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                        "Using Alternative Decode buffer!\n"););
-        }
-        else
-        {
-            if(IsLimitedDetect(p))
-            {
-                dsize = p->alt_dsize;
-                DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                    "Using Limited Packet Data!\n"););
-            }
-            else
-            {
-                dsize = p->dsize;
-                DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                    "Using Full Packet Data!\n"););
-            }
-            dp = (char *) p->data;
-        }
-    }
-    else
-    {
-        dsize = p->dsize;
-        dp = (char *) p->data;
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-            "Using Full Packet Data!\n"););
-    }
-
-    if(doe_buf_flags & DOE_BUF_URI)
-        UpdateDoePtr(NULL, 0);
-
-    doe_buf_flags = DOE_BUF_STD;
-
-    found = idx->search(dp, dsize, idx);
+    found = uniSearchReal(idx, c);
 
     if ( found == -1 )
     {
@@ -836,20 +537,6 @@ static int CheckANDPatternMatch(PatternMatchData* idx, Packet *p)
 
     if ( found )
     {
-        if ( idx->replace_buf && !PacketWasCooked(p) )
-        {
-            //fix the packet buffer to have the new string
-            int detect_depth = (char *)doe_ptr - idx->pattern_size - dp;
-
-            // this check should be redundant (never be true)
-            if (detect_depth < 0)
-            {
-                Replace_ResetOffset(idx);
-                PREPROC_PROFILE_END(contentPerfStats);
-                return rval;
-            }
-            Replace_StoreOffset(idx, detect_depth);
-        }
         rval = DETECTION_OPTION_MATCH;
         DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Pattern match found\n"););
     }
@@ -862,271 +549,26 @@ static int CheckANDPatternMatch(PatternMatchData* idx, Packet *p)
     return rval;
 }
 
-static int CheckUriPatternMatch(PatternMatchData* idx, Packet*)
+PatternMatchData* content_get_data(void* pv)
 {
-    int rval = DETECTION_OPTION_NO_MATCH;
-    int found = 0;
-    const HttpBuffer* hb = GetHttpBuffer(idx->http_buffer);
-    PROFILE_VARS;
-
-    if ( !hb )
-    {
-        DEBUG_WRAP(DebugMessage(DEBUG_HTTP_DECODE,"CheckUriPatternMatch: no "
-            "HTTP buffers set, retuning"););
-        return rval;
-    }
-
-    PREPROC_PROFILE_START(uricontentPerfStats);
-
-    /*
-    * have to reset the doe_ptr for each new UriBuf
-    */
-    if(idx->use_doe != 1)
-        UpdateDoePtr(NULL, 0);
-
-    else if(!(doe_buf_flags & DOE_BUF_URI))
-        SetDoePtr(hb->buf, DOE_BUF_URI);
-
-    /* this now takes care of all the special cases where we'd run
-     * over the buffer */
-    found = idx->search((const char *)hb->buf, hb->length, idx);
-
-    if (found == -1)
-        found = 0;
-    else
-        found ^= idx->exception_flag;
-
-    if(found > 0 )
-    {
-        doe_buf_flags = DOE_BUF_URI;
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern Match successful!\n"););
-
-        /* call the next function in the OTN */
-        PREPROC_PROFILE_END(uricontentPerfStats);
-        return DETECTION_OPTION_MATCH;
-    }
-
-    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Pattern match failed\n"););
-    PREPROC_PROFILE_END(uricontentPerfStats);
-    return rval;
-}
-
-void PatternMatchDuplicatePmd(void *src, PatternMatchData *pmd_dup)
-{
-    ContentOption* opt = (ContentOption*)src;
-    PatternMatchData *pmd_src = opt->get_data();
-    *pmd_dup = *pmd_src;
-    Replace_ResetOffset(pmd_dup);
+    ContentOption* opt = (ContentOption*)pv;
+    return opt->get_data();
 }
 
-// FIXIT this kinda hurts ...
-int eval_dup_content(void* v, Packet* p, PatternMatchData* dup)
+/* current should be the doe_ptr after this content rule option matched
+ * orig is the place from where we first did evaluation of this content */
+bool content_next(PatternMatchData* pmd)
 {
-    ContentOption* opt = (ContentOption*)v;
-
-    if ( opt->get_type() == RULE_OPTION_TYPE_CONTENT )
-    {
-        ContentOption tmp(dup, "content");
-        int rval = tmp.eval(p);
-        tmp.set_data(nullptr);
-        return rval;
-    }
-    UriContentOption tmp(dup);
-    int rval = tmp.eval(p);
-    tmp.set_data(nullptr);
-    return rval;
-}   
-
-/* current_cursor should be the doe_ptr after this content rule option matched
- * orig_cursor is the place from where we first did evaluation of this content */
-int PatternMatchAdjustRelativeOffsets(
-    void* pv, PatternMatchData *dup_pmd,
-    const uint8_t *current_cursor, const uint8_t *orig_cursor)
-{
-    ContentOption* opt = (ContentOption*)pv;
-    PatternMatchData* orig_pmd = opt->get_data();
-
-    /* Adjust for repeating patterns, e.g. ABAB
-     * This is where the new search for this content should start */
-    const uint8_t *start_cursor =
-        (current_cursor - dup_pmd->pattern_size) + dup_pmd->pattern_max_jump_size;
-
-    if (orig_pmd->depth != 0)
-    {
-        /* This was relative to a previously found pattern.  No space left to
-         * search, we're done */
-        if ((start_cursor + dup_pmd->pattern_size)
-                > (orig_cursor + dup_pmd->offset + dup_pmd->depth))
-        {
-            return 0;
-        }
-
-        /* Adjust offset and depth to reflect new position */
-        /* Lop off what we used */
-        dup_pmd->depth -= start_cursor - (orig_cursor + dup_pmd->offset);
-        /* Make offset where we will start the next search */
-        dup_pmd->offset = start_cursor - orig_cursor;
-    }
-    else if (orig_pmd->within != 0)
-    {
-        /* This was relative to a previously found pattern.  No space left to
-         * search, we're done */
-        if ((start_cursor + dup_pmd->pattern_size)
-                > (orig_cursor + dup_pmd->distance + dup_pmd->within))
-        {
-            return 0;
-        }
-
-        /* Adjust distance and within to reflect new position */
-        /* Lop off what we used */
-        dup_pmd->within -= start_cursor - (orig_cursor + dup_pmd->distance);
-        /* Make distance where we will start the next search */
-        dup_pmd->distance = start_cursor - orig_cursor;
-    }
-    else if (orig_pmd->use_doe)
-    {
-        dup_pmd->distance = start_cursor - orig_cursor;
-    }
-    else
-    {
-        dup_pmd->offset = start_cursor - orig_cursor;
-    }
+    if ( pmd->exception_flag )
+        return false;
 
-    return 1;
+    return true;
 }
-// FIXIT PMD
 
 //-------------------------------------------------------------------------
 // suboption handlers
 //-------------------------------------------------------------------------
 
-static void PayloadSearchHttpMethod(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_method' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_METHOD;
-    MovePmdToUriDsList(otn, pmd);
-}
-
-static void PayloadSearchHttpUri(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_uri' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_URI;
-    MovePmdToUriDsList(otn, pmd);
-}
-
-static void PayloadSearchHttpHeader(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_header' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_HEADER;
-    MovePmdToUriDsList(otn, pmd);
-}
-
-static void PayloadSearchHttpCookie(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_cookie' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_COOKIE;
-    MovePmdToUriDsList(otn, pmd);
-}
-
-static void PayloadSearchHttpBody(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_client_body' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_CLIENT_BODY;
-    MovePmdToUriDsList(otn, pmd);
-}
-
-static void PayloadSearchHttpRawUri(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_raw_uri' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_RAW_URI;
-    MovePmdToUriDsList(otn, pmd);
-}
-
-static void PayloadSearchHttpRawHeader(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_raw_header' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_RAW_HEADER;
-    MovePmdToUriDsList(otn, pmd);
-}
-static void PayloadSearchHttpRawCookie(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_raw_cookie' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_RAW_COOKIE;
-    MovePmdToUriDsList(otn, pmd);
-}
-static void PayloadSearchHttpStatCode(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_stat_code' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_STAT_CODE;
-    MovePmdToUriDsList(otn, pmd);
-}
-static void PayloadSearchHttpStatMsg(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
-{
-    if (data != NULL)
-        ParseError("'http_stat_msg' does not take an argument");
-
-    if ( pmd->http_buffer )
-        ParseWarning("at most one http buffer can be specified per content option");
-
-    pmd->http_buffer = HTTP_BUFFER_STAT_MSG;
-    MovePmdToUriDsList(otn, pmd);
-}
-
 typedef enum {
     CMF_DISTANCE = 0x1, CMF_WITHIN = 0x2, CMF_OFFSET = 0x4, CMF_DEPTH = 0x8
 } ContentModifierFlags;
@@ -1134,8 +576,6 @@ typedef enum {
 static unsigned GetCMF (PatternMatchData* pmd)
 {
     unsigned cmf = 0;
-    if ( (pmd->distance != 0) || (pmd->distance_var != -1) ) cmf |= CMF_DISTANCE;
-    if ( (pmd->within != 0) || (pmd->within_var != -1) ) cmf |= CMF_WITHIN;
     if ( (pmd->offset != 0) || (pmd->offset_var != -1) ) cmf |= CMF_OFFSET;
     if ( (pmd->depth != 0) || (pmd->depth_var != -1) ) cmf |= CMF_DEPTH;
     return cmf;
@@ -1149,7 +589,7 @@ static unsigned GetCMF (PatternMatchData* pmd)
 static void PayloadSearchOffset(
     PatternMatchData* pmd, char *data, OptTreeNode*)
 {
-    if ( GetCMF(pmd) & BAD_OFFSET )
+    if ( GetCMF(pmd) & BAD_OFFSET && pmd->use_doe )
         ParseError("offset can't be used with itself, distance, or within");
 
     if (data == NULL)
@@ -1175,7 +615,7 @@ static void PayloadSearchOffset(
 static void PayloadSearchDepth(
     PatternMatchData* pmd, char *data, OptTreeNode*)
 {
-    if ( GetCMF(pmd) & BAD_DEPTH )
+    if ( GetCMF(pmd) & BAD_DEPTH && pmd->use_doe )
         ParseError("depth can't be used with itself, distance, or within");
 
     if (data == NULL)
@@ -1208,7 +648,7 @@ static void PayloadSearchDepth(
 static void PayloadSearchDistance(
     PatternMatchData* pmd, char *data, OptTreeNode*)
 {
-    if ( GetCMF(pmd) & BAD_DISTANCE )
+    if ( GetCMF(pmd) & BAD_DISTANCE && !pmd->use_doe )
         ParseError("distance can't be used with itself, offset, or depth");
 
     if (data == NULL)
@@ -1216,27 +656,24 @@ static void PayloadSearchDistance(
 
     if (isdigit(data[0]) || data[0] == '-')
     {
-        pmd->distance = ParseInt(data, "distance");
+        pmd->offset = ParseInt(data, "distance");
     }
     else
     {
-        pmd->distance_var = GetVarByName(data);
-        if (pmd->distance_var == BYTE_EXTRACT_NO_VAR)
+        pmd->offset_var = GetVarByName(data);
+        if (pmd->offset_var == BYTE_EXTRACT_NO_VAR)
         {
             ParseError(BYTE_EXTRACT_INVALID_ERR_STR);
         }
     }
 
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern distance = %d\n",
-                pmd->distance););
-
     pmd->use_doe = 1;
 }
 
 static void PayloadSearchWithin(
     PatternMatchData* pmd, char *data, OptTreeNode*)
 {
-    if ( GetCMF(pmd) & BAD_WITHIN )
+    if ( GetCMF(pmd) & BAD_WITHIN && !pmd->use_doe )
         ParseError("within can't be used with itself, offset, or depth");
 
     if (data == NULL)
@@ -1244,22 +681,22 @@ static void PayloadSearchWithin(
 
     if (isdigit(data[0]) || data[0] == '-')
     {
-        pmd->within = ParseInt(data, "within");
+        pmd->depth = ParseInt(data, "within");
 
-        if (pmd->within < pmd->pattern_size)
-            ParseError("within (%d) is smaller than size of pattern", pmd->within);
+        if (pmd->depth < (int)pmd->pattern_size)
+            ParseError("within (%d) is smaller than size of pattern", pmd->depth);
     }
     else
     {
-        pmd->within_var = GetVarByName(data);
-        if (pmd->within_var == BYTE_EXTRACT_NO_VAR)
+        pmd->depth_var = GetVarByName(data);
+        if (pmd->depth_var == BYTE_EXTRACT_NO_VAR)
         {
             ParseError(BYTE_EXTRACT_INVALID_ERR_STR);
         }
     }
 
     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern within = %d\n",
-                pmd->within););
+                pmd->depth););
 
     pmd->use_doe = 1;
 }
@@ -1270,28 +707,15 @@ static void PayloadSearchNocase(
     unsigned int i;
 
     if (data != NULL)
-        ParseError("'nocase' does not take an argument");
+        ParseError("'no_case' does not take an argument");
 
     for (i = 0; i < pmd->pattern_size; i++)
         pmd->pattern_buf[i] = toupper((int)pmd->pattern_buf[i]);
 
-    pmd->nocase = 1;
-
-    pmd->search = uniSearchCI;
+    pmd->no_case = 1;
     make_precomp(pmd);
 }
 
-static void PayloadSearchRawbytes(
-    PatternMatchData* pmd, char *data, OptTreeNode*)
-{
-    if (data != NULL)
-        ParseError("'rawbytes' does not take an argument");
-
-    /* mark this as inspecting a raw pattern match rather than a
-     * decoded application buffer */
-    pmd->rawbytes = 1;
-}
-
 static void PayloadSearchFastPattern(
     PatternMatchData* pmd, char *data, OptTreeNode *otn)
 {
@@ -1305,8 +729,6 @@ static void PayloadSearchFastPattern(
 
     if (HasFastPattern(otn, RULE_OPTION_TYPE_CONTENT))
         ParseError("Can only use the fast_pattern modifier once in a rule.");
-    if (HasFastPattern(otn, RULE_OPTION_TYPE_CONTENT_URI))
-        ParseError("Can only use the fast_pattern modifier once in a rule.");
 
     pmd->fp = 1;
 
@@ -1649,12 +1071,11 @@ static void content_parse(char *rule, PatternMatchData* ds_idx)
     memcpy(ds_idx->pattern_buf, tmp_buf, dummy_size);
 
     ds_idx->pattern_size = dummy_size;
-    ds_idx->search = uniSearch;
 
     make_precomp(ds_idx);
     ds_idx->exception_flag = exception_flag;
 
-    ds_idx->pattern_max_jump_size = GetMaxJumpSize(ds_idx->pattern_buf, ds_idx->pattern_size);
+    ds_idx->match_delta = GetMaxJumpSize(ds_idx->pattern_buf, ds_idx->pattern_size);
 }
 
 static IpsOption* content_ctor(
@@ -1679,9 +1100,6 @@ static IpsOption* content_ctor(
     update_pmd(pmd);
     next_opt = opt_data + opt_len;
 
-    pmd->http_buffer = HTTP_BUFFER_NONE;
-    pmd->buffer_func = CHECK_AND_PATTERN_MATCH;
-
     while (next_opt < data_end)
     {
         char **opts;        /* dbl ptr for mSplit call, holds rule tokens */
@@ -1717,50 +1135,6 @@ static IpsOption* content_ctor(
         {
             PayloadSearchNocase(pmd, opt1, otn);
         }
-        else if (!strcasecmp(opts[0], "rawbytes"))
-        {
-            PayloadSearchRawbytes(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_uri"))
-        {
-            PayloadSearchHttpUri(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_client_body"))
-        {
-            PayloadSearchHttpBody(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_header"))
-        {
-            PayloadSearchHttpHeader(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_method"))
-        {
-            PayloadSearchHttpMethod(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_cookie"))
-        {
-            PayloadSearchHttpCookie(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_raw_uri"))
-        {
-            PayloadSearchHttpRawUri(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_raw_header"))
-        {
-            PayloadSearchHttpRawHeader(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_raw_cookie"))
-        {
-            PayloadSearchHttpRawCookie(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_stat_code"))
-        {
-            PayloadSearchHttpStatCode(pmd, opt1, otn);
-        }
-        else if (!strcasecmp(opts[0], "http_stat_msg"))
-        {
-            PayloadSearchHttpStatMsg(pmd, opt1, otn);
-        }
         else if (!strcasecmp(opts[0], "fast_pattern"))
         {
             PayloadSearchFastPattern(pmd, opt1, otn);
@@ -1773,10 +1147,6 @@ static IpsOption* content_ctor(
         {
             PayloadSearchWithin(pmd, opt1, otn);
         }
-        else if (!strcasecmp(opts[0], "replace"))
-        {
-            PayloadReplaceInit(pmd, opt1, otn);
-        }
         else
         {
             ParseError("Invalid content parameter specified: %s", opts[0]);
@@ -1787,9 +1157,6 @@ static IpsOption* content_ctor(
     free(data_dup);
     ValidateContent(sc, pmd, RULE_OPTION_TYPE_CONTENT);
 
-    if ( pmd->buffer_func == CHECK_URI_PATTERN_MATCH )
-        return new UriContentOption(pmd);
-
     return new ContentOption(pmd, "content");
 }
 
index 5d537fec8290d796087a12a2909da72fd57584e7..93a18ab80503faa717954be7a86004cdf77ea384 100644 (file)
@@ -29,6 +29,7 @@
 #include "detection/rules.h"
 #include "detection/treenodes.h"
 #include "detection/detection_util.h"
+#include "framework/content_buffer.h"
 
 extern THREAD_LOCAL int lastType;
 
@@ -44,38 +45,27 @@ struct PmdLastCheck
 
 typedef struct _PatternMatchData
 {
-    // FIXIT below must be thread local or the cloned instance must be
-    // thread local because they are updated :(
     int offset;             /* pattern search start offset */
     int depth;              /* pattern search depth */
 
-    int distance;           /* offset to start from based on last match */
-    unsigned within;           /* this pattern must be found
-                               within X bytes of last match*/
-    // FIXIT above must be thread local or the cloned instance must be
-    // thread local because they are updated :(
-
     int8_t offset_var;      /* byte_extract variable indices for offset, */
     int8_t depth_var;       /* depth, distance, within */
     int8_t distance_var;
     int8_t within_var;
 
-    int rawbytes;           /* Search the raw bytes rather than any decoded app
-                               buffer */
-
-    int nocase;             /* Toggle case insensitity */
+    int no_case;            /* Toggle case sensitivity */
     int use_doe;            /* Use the doe_ptr for relative pattern searching */
-    HTTP_BUFFER http_buffer;/* Index of the URI buffer */
-    int buffer_func;        /* buffer function CheckAND or CheckUri */
-    unsigned pattern_size;     /* size of app layer pattern */
-    unsigned replace_size;     /* size of app layer replace pattern */
+
+    unsigned pattern_size;  /* size of app layer pattern */
+    unsigned replace_size;  /* size of app layer replace pattern */
+
     char *replace_buf;      /* app layer pattern to replace with */
     char *pattern_buf;      /* app layer pattern to match on */
-    int (*search)(const char *, int, struct _PatternMatchData *);  /* search function */
-    int *skip_stride; /* B-M skip array */
-    int *shift_stride; /* B-M shift array */
-    unsigned pattern_max_jump_size; /* Maximum distance we can jump to search for
-                                  * this pattern again. */
+
+    int *skip_stride;       /* B-M skip array */
+    int *shift_stride;      /* B-M shift array */
+    unsigned match_delta;   /* Maximum distance we can jump to search for
+                             * this pattern again. */
 
     /* For fast_pattern arguments */
     uint8_t fp;
@@ -85,8 +75,6 @@ typedef struct _PatternMatchData
 
     uint8_t exception_flag; /* search for "not this pattern" */
 
-    int* replace_depth;      /* >=0 is offset to start of replace */
-
     // FIXIT wasting some memory here:
     // - this is not used by content option logic directly
     // - and only used on current eval (not across packets)
@@ -99,8 +87,8 @@ typedef struct _PatternMatchData
 
 } PatternMatchData;
 
-void PatternMatchDuplicatePmd(void *, PatternMatchData *);
-int eval_dup_content(void* v, struct Packet* p, PatternMatchData* alt);
+PatternMatchData* content_get_data(void* pv);
+bool content_next(PatternMatchData*);
 
 int PatternMatchAdjustRelativeOffsets(
     void*, PatternMatchData *dup_pmd,
@@ -112,6 +100,8 @@ PatternMatchData* get_pmd(OptFpList*);
 bool is_fast_pattern_only(OptFpList*);
 bool is_unbounded(void*);
 
+// FIXIT must add same fast_pattern options from content to these
+// rule options:
 static inline bool IsHttpBufFpEligible (HTTP_BUFFER http_buffer)
 {
     switch ( http_buffer )
index 8de2e2a3b8e023a7ca8098d63b412785ea18576c..e9569bf9491a4ba72d059e49f5c23823b3104e64 100644 (file)
@@ -130,7 +130,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     CvsRuleOption config;
@@ -172,7 +172,7 @@ bool CvsOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int CvsOption::eval(Packet *p)
+int CvsOption::eval(Cursor&, Packet *p)
 {
     int ret;
     int rval = DETECTION_OPTION_NO_MATCH;
index 28c123b84d6b5943c736181dc77472ed76ebe4ea..b55b541ffd992300f0b32757b679d91c3c27c71f 100644 (file)
@@ -79,7 +79,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     DsizeCheckData config;
@@ -125,7 +125,7 @@ bool DsizeOption::operator==(const IpsOption& ips) const
 }
 
 // Test the packet's payload size against the rule payload size value
-int DsizeOption::eval(Packet *p)
+int DsizeOption::eval(Cursor&, Packet *p)
 {
     DsizeCheckData *ds_ptr = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 44fc1cf819970f67b4947b4fb4482ce98ee408fb..11c785de9a96c2998b732da04adf2fd08f81051a 100644 (file)
@@ -41,6 +41,7 @@
 #include "fpdetect.h"
 #include "detection/detection_defines.h"
 #include "detection/detection_util.h"
+#include "framework/cursor.h"
 #include "framework/ips_option.h"
 
 static const char* s_name = "file_data";
@@ -74,7 +75,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
     FileData* get_data()
     { return &config; };
@@ -117,7 +118,7 @@ bool FileDataOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int FileDataOption::eval(Packet *p)
+int FileDataOption::eval(Cursor& c, Packet *p)
 {
     int rval = DETECTION_OPTION_NO_MATCH;
     uint8_t *data;
@@ -142,8 +143,7 @@ int FileDataOption::eval(Packet *p)
     else
         mime_present = 0;
 
-    SetDoePtr(data,  DOE_BUF_STD);
-    SetAltDetect(data, len);
+    c.set(s_name, data, len);
     rval = DETECTION_OPTION_MATCH;
 
     PREPROC_PROFILE_END(fileDataPerfStats);
index d90c5341d7a66427aa0e69c0d2ccde6e3f743407..d85076a8117c43d91ae5b72f5965142c8ed6cc7d 100644 (file)
@@ -86,7 +86,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     TcpFlagCheckData config;
@@ -130,7 +130,7 @@ bool TcpFlagOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int TcpFlagOption::eval(Packet *p)
+int TcpFlagOption::eval(Cursor&, Packet *p)
 {
     TcpFlagCheckData *flagptr = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 050277b8c1d840b11cb50519e05e585d76fe88c9..47e5a9293f0bce1a0b7d2ffbd5abf29f5ca89989 100644 (file)
@@ -84,7 +84,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     FlowCheckData config;
@@ -135,7 +135,7 @@ bool FlowCheckOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int FlowCheckOption::eval(Packet *p)
+int FlowCheckOption::eval(Cursor&, Packet *p)
 {
     FlowCheckData *fcd = &config;
     PROFILE_VARS;
index 53307f8798a39c7e427d52523290ccf90a9209d9..0228589d9410d03d7b5c35336f0d4548e96e7e56 100644 (file)
@@ -174,7 +174,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
     bool is_set(uint8_t bits)
     { return (config.type & bits) != 0; };
@@ -269,7 +269,7 @@ bool FlowBitsOption::operator==(const IpsOption& ips) const
     return true;
 }
 
-int FlowBitsOption::eval(Packet *p)
+int FlowBitsOption::eval(Cursor&, Packet *p)
 {
     FLOWBITS_OP *flowbits = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 9fd828e29be1c2be6b91832bd7624f43fde1383c..703cbb0ef88e5112b509eb9918bd44eb6dea0343 100644 (file)
@@ -108,7 +108,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     FragBitsData config;
@@ -153,7 +153,7 @@ bool FragBitsOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int FragBitsOption::eval(Packet *p)
+int FragBitsOption::eval(Cursor&, Packet *p)
 {
     FragBitsData *fb = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 576b31b23235a0a098fd186bfa373c5d1aeda64b..072048f9900a6f45278536be4db7ba8deecfbdbb 100644 (file)
@@ -85,7 +85,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     FragOffsetData config;
@@ -129,7 +129,7 @@ bool FragOffsetOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int FragOffsetOption::eval(Packet *p)
+int FragOffsetOption::eval(Cursor&, Packet *p)
 {
     FragOffsetData *ipd = &config;
     int p_offset = p->frag_offset * 8;
index 108f88d7b6e75566f51ad5bfb4ce64e1ef824ef4..b71a6c42a40b5802c1028ace61e91dfa7eb5f8de 100644 (file)
@@ -92,7 +92,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     IcmpIdCheckData config;
@@ -134,7 +134,7 @@ bool IcmpIdOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int IcmpIdOption::eval(Packet *p)
+int IcmpIdOption::eval(Cursor&, Packet *p)
 {
     IcmpIdCheckData *icmpId = &config;
     PROFILE_VARS;
index d8552922b3f5b75450f357b72dbbe9329e4b43ec..a98ef56c1e636259bc0058dfc4235b5c78f099a5 100644 (file)
@@ -91,7 +91,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     IcmpSeqCheckData config;
@@ -133,7 +133,7 @@ bool IcmpSeqOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int IcmpSeqOption::eval(Packet *p)
+int IcmpSeqOption::eval(Cursor&, Packet *p)
 {
     IcmpSeqCheckData *icmpSeq = &config;
     PROFILE_VARS;
index 366eeae1a159259fa678c55cdc43b6853a49c010..5b7fc82284ebe897ab621b1a47252930f0df1c2a 100644 (file)
@@ -78,7 +78,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     IcmpCodeCheckData config;
@@ -123,7 +123,7 @@ bool IcmpCodeOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int IcmpCodeOption::eval(Packet *p)
+int IcmpCodeOption::eval(Cursor&, Packet *p)
 {
     IcmpCodeCheckData *ds_ptr = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 95587e574af5cf2240bc68ec7eb3a7b89ccce82e..ebb66ec6ebf8c30440e25bf378636b59e0466a66 100644 (file)
@@ -70,7 +70,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     IpIdCheckData config;
@@ -112,7 +112,7 @@ bool IpIdOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int IpIdOption::eval(Packet *p)
+int IpIdOption::eval(Cursor&, Packet *p)
 {
     IpIdCheckData *ipIdCheckData = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 880a84c510383a1ee4c8d3c3bf1769714fe24325..d8018317cccba4df10951f63195d097fa4088174 100644 (file)
@@ -80,7 +80,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
     IpProtoData* get_data() 
     { return &config; };
@@ -126,7 +126,7 @@ bool IpProtoOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int IpProtoOption::eval(Packet *p)
+int IpProtoOption::eval(Cursor&, Packet *p)
 {
     IpProtoData *ipd = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index fc47f5e060e59f87f59076fe24ae3e191302f0b7..3a847d9289b14190b4d9e0d202253838aa59be39 100644 (file)
@@ -72,7 +72,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
     IpOptionData* get_data() 
     { return &config; };
@@ -118,7 +118,7 @@ bool IpOptOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int IpOptOption::eval(Packet *p)
+int IpOptOption::eval(Cursor&, Packet *p)
 {
     IpOptionData *ipOptionData = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 5e6a0e67f67f30b5805763885a9ae5a08a118528..47ddc7b4fb50027059a34b2f9797503061e5b8c1 100644 (file)
@@ -97,7 +97,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
     IsDataAtData* get_data() 
     { return &config; };
@@ -148,7 +148,7 @@ bool IsDataAtOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int IsDataAtOption::eval(Packet *p)
+int IsDataAtOption::eval(Cursor&, Packet *p)
 {
     IsDataAtData *isdata = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index b4a80dc4277a28625fa4d12870a64bd60ff948f7..1fd9c0804707f67541297dbe8b2595d164d4c342 100644 (file)
@@ -78,7 +78,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     IcmpTypeCheckData config;
@@ -123,7 +123,7 @@ bool IcmpTypeOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int IcmpTypeOption::eval(Packet *p)
+int IcmpTypeOption::eval(Cursor&, Packet *p)
 {
     IcmpTypeCheckData *ds_ptr = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 9ffc6c65ff548231878ea6b645b1707cebf6bb2c..b004d053a3841b04623acce89c9cd80ad6dce460 100644 (file)
@@ -232,7 +232,7 @@ bool LuaJITOption::operator==(const IpsOption& ips) const
     return true;
 }
 
-int LuaJITOption::eval(Packet* p)
+int LuaJITOption::eval(Cursor&, Packet* p)
 {
     packet = p;
 
index dc34a65eb3c543dd4a7dcbf232efde7e26addfbf..a9bd30c75807fa3ab254cc6d485501c5f24057f5 100644 (file)
@@ -33,7 +33,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     void init(const char*, const char*);
index 0ef496384ae50fe903d77ce784a0f5620987ffb8..08d7500486178d2d9e902db3ab1464ac978a872d 100644 (file)
@@ -54,6 +54,7 @@ extern const BaseApi* ips_ipopts;
 extern const BaseApi* ips_isdataat;
 extern const BaseApi* ips_itype;
 extern const BaseApi* ips_pkt_data;
+extern const BaseApi* ips_raw_data;
 extern const BaseApi* ips_react;
 extern const BaseApi* ips_resp;
 extern const BaseApi* ips_rpc;
@@ -96,6 +97,7 @@ const BaseApi* ips_options[] =
     ips_isdataat,
     ips_itype,
     ips_pkt_data,
+    ips_raw_data,
     ips_react,
     ips_resp,
     ips_rpc,
index 63cff4396e65e93752d88105b56abfa8c953e6bf..277b53110eee729dd55443d2483a292ee6563cd7 100644 (file)
 #include "sfhashfcn.h"
 #include "detection/detection_defines.h"
 #include "detection_util.h"
+#include "framework/cursor.h"
 #include "framework/ips_option.h"
 
 static const char* s_name = "pcre";
 
-#ifdef PERF_PROFILING
-static THREAD_LOCAL PreprocStats pcrePerfStats;
-
-static PreprocStats* pcre_get_profile(const char* key)
-{
-    if ( !strcmp(key, s_name) )
-        return &pcrePerfStats;
-
-    return nullptr;
-}
-#endif
-
 /*
  * we need to specify the vector length for our pcre_exec call.  we only care
  * about the first vector, which if the match is successful will include the
@@ -74,410 +63,22 @@ static PreprocStats* pcre_get_profile(const char* key)
  * configuraton, we won't pcre_capture count again, so save the max.  */
 static int s_ovector_max = 0;
 
-class PcreOption : public IpsOption
-{
-public:
-    PcreOption(PcreData* c) :
-        IpsOption(s_name, RULE_OPTION_TYPE_PCRE)
-    { config = c; };
-
-    ~PcreOption();
-
-    uint32_t hash() const;
-    bool operator==(const IpsOption&) const;
-
-    bool is_relative()
-    { return (config->options & SNORT_PCRE_RELATIVE) != 0; };
-
-    int eval(Packet*);
-
-    PcreData* get_data()
-    { return config; };
-
-    void set_data(PcreData* pcre)
-    { config = pcre; };
-
-private:
-    PcreData* config;
-};
-
-static int pcre_search(
-    const PcreData*, const char*, int len, int start_offset, int* found_offset);
-
-//-------------------------------------------------------------------------
-// class methods
-//-------------------------------------------------------------------------
-
-PcreOption::~PcreOption()
-{
-    if ( !config )
-        return;
-
-    if (config->expression)
-        free(config->expression);
-    if (config->pe)
-        free(config->pe);
-    if (config->re)
-        free(config->re);
-
-    free(config);
-}
-
-uint32_t PcreOption::hash() const
-{
-    int i,j,k,l,expression_len;
-    uint32_t a,b,c,tmp;
-    const PcreData *data = config;
-
-    expression_len = strlen(data->expression);
-    a = b = c = 0;
-
-    for (i=0,j=0;i<expression_len;i+=4)
-    {
-        tmp = 0;
-        k = expression_len - i;
-        if (k > 4)
-            k=4;
-
-        for (l=0;l<k;l++)
-        {
-            tmp |= *(data->expression + i + l) << l*8;
-        }
-
-        switch (j)
-        {
-            case 0:
-                a += tmp;
-                break;
-            case 1:
-                b += tmp;
-                break;
-            case 2:
-                c += tmp;
-                break;
-        }
-        j++;
-
-        if (j == 3)
-        {
-            mix(a,b,c);
-            j=0;
-        }
-    }
-
-    if (j != 0)
-    {
-        mix(a,b,c);
-    }
-
-    a += data->options;
-
-    mix_str(a,b,c,get_name());
-    final(a,b,c);
-
-    return c;
-}
-
-bool PcreOption::operator==(const IpsOption& ips) const
-{
-    if ( strcmp(get_name(), ips.get_name()) )
-        return false;
-
-    PcreOption& rhs = (PcreOption&)ips;
-    PcreData *left = config;
-    PcreData *right = rhs.config;
-
-    if (( strcmp(left->expression, right->expression) == 0) &&
-        ( left->options == right->options))
-    {
-        return true;
-    }
-
-    return false;
-}
-
-int PcreOption::eval(Packet *p)
-{
-    PcreData *pcre_data = config;
-    int found_offset = -1;  /* where is the ending location of the pattern */
-    const uint8_t *base_ptr, *end_ptr, *start_ptr;
-    int dsize;
-    int length; /* length of the buffer pointed to by base_ptr  */
-    int matched = 0;
-    uint8_t rst_doe_flags = 1;
-    HTTP_BUFFER hb_type;
-    DEBUG_WRAP(char *hexbuf;)
-
-    PROFILE_VARS;
-    PREPROC_PROFILE_START(pcrePerfStats);
-
-    //short circuit this for testing pcre performance impact
-    if (ScNoPcre())
-    {
-        PREPROC_PROFILE_END(pcrePerfStats);
-        return DETECTION_OPTION_NO_MATCH;
-    }
-
-    /* This is the HTTP case */
-    if ( (hb_type = (HTTP_BUFFER)(pcre_data->options & SNORT_PCRE_HTTP_BUFS)) )
-    {
-        const HttpBuffer* hb = GetHttpBuffer(hb_type);
-
-        if ( hb )
-        {
-            matched = pcre_search(
-                pcre_data, (const char*)hb->buf, hb->length, 0, &found_offset);
-
-            if ( matched )
-            {
-                /* don't touch doe_ptr on URI contents */
-                PREPROC_PROFILE_END(pcrePerfStats);
-                return DETECTION_OPTION_MATCH;
-            }
-        }
-        PREPROC_PROFILE_END(pcrePerfStats);
-        return DETECTION_OPTION_NO_MATCH;
-    }
-    /* end of the HTTP case */
-
-    if( !(pcre_data->options & SNORT_PCRE_RAWBYTES))
-    {
-        if(Is_DetectFlag(FLAG_ALT_DETECT))
-        {
-            dsize = DetectBuffer.len;
-            start_ptr = DetectBuffer.data;
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                "using alternative detect buffer in pcre!\n"););
-        }
-        else if(Is_DetectFlag(FLAG_ALT_DECODE))
-        {
-            dsize = DecodeBuffer.len;
-            start_ptr = DecodeBuffer.data;
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                "using alternative decode buffer in pcre!\n"););
-        }
-        else
-        {
-            if(IsLimitedDetect(p))
-                dsize = p->alt_dsize;
-            else
-                dsize = p->dsize;
-            start_ptr = p->data;
-        }
-    }
-    else
-    {
-        dsize = p->dsize;
-        start_ptr = p->data;
-    }
-
-    //base_ptr = start_ptr;
-    end_ptr = start_ptr + dsize;
-
-    /* doe_ptr's would be set by the previous content option */
-    if(pcre_data->options & SNORT_PCRE_RELATIVE && doe_ptr)
-    {
-        if(!inBounds(start_ptr, end_ptr, doe_ptr))
-        {
-            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                    "pcre bounds check failed on a relative content match\n"););
-            PREPROC_PROFILE_END(pcrePerfStats);
-            return DETECTION_OPTION_NO_MATCH;
-        }
-
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                "pcre ... checking relative offset\n"););
-        base_ptr = doe_ptr;
-        rst_doe_flags = 0;
-    }
-    else
-    {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                "pcre ... checking absolute offset\n"););
-        base_ptr = start_ptr;
-    }
-
-    length = end_ptr - base_ptr;
-
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                            "pcre ... base: %p start: %p end: %p doe: %p length: %d\n",
-                            base_ptr, start_ptr, end_ptr, doe_ptr, length););
-
-    DEBUG_WRAP(hexbuf = hex(base_ptr, length);
-               DebugMessage(DEBUG_PATTERN_MATCH, "pcre payload: %s\n", hexbuf);
-               free(hexbuf);
-               );
-
-    matched = pcre_search(pcre_data, (const char *)base_ptr, length, pcre_data->search_offset, &found_offset);
-
-    /* set the doe_ptr if we have a valid offset */
-    if(found_offset > 0)
-    {
-        UpdateDoePtr(((uint8_t *) base_ptr + found_offset), rst_doe_flags);
-    }
-
-    if (matched)
-    {
-        PREPROC_PROFILE_END(pcrePerfStats);
-        return DETECTION_OPTION_MATCH;
-    }
-
-    /* finally return 0 */
-    PREPROC_PROFILE_END(pcrePerfStats);
-    return DETECTION_OPTION_NO_MATCH;
-}
-
-//-------------------------------------------------------------------------
-// public methods
-//-------------------------------------------------------------------------
-
-void PcreDuplicatePcreData(void *src, PcreData *pcre_dup)
-{
-    PcreOption* opt = (PcreOption*)src;
-    PcreData* pcre_src = opt->get_data();
-    *pcre_dup = *pcre_src;
-    pcre_dup->search_offset = 0;
-}
-
-// FIXIT this kinda hurts ...
-int eval_dup_pcre(void*, Packet* p, PcreData* dup)
-{
-    PcreOption tmp(dup);
-    int rval = tmp.eval(p);
-    tmp.set_data(nullptr);
-    return rval;
-}
+#ifdef PERF_PROFILING
+static THREAD_LOCAL PreprocStats pcrePerfStats;
 
-int PcreAdjustRelativeOffsets(PcreData *pcre, uint32_t search_offset)
+static PreprocStats* pcre_get_profile(const char* key)
 {
-    if ((pcre->options & (SNORT_PCRE_INVERT | SNORT_PCRE_ANCHORED)))
-    {
-        return 0; /* Don't search again */
-    }
-
-    if (pcre->options & ( SNORT_PCRE_HTTP_BUFS ))
-    {
-        return 0;
-    }
-
-    /* What's coming in has the absolute offset */
-    pcre->search_offset += search_offset;
+    if ( !strcmp(key, s_name) )
+        return &pcrePerfStats;
 
-    return 1; /* Continue searcing */
+    return nullptr;
 }
+#endif
 
 //-------------------------------------------------------------------------
 // implementation foo
 //-------------------------------------------------------------------------
 
-/**
- * Perform a search of the PCRE data.
- *
- * @param pcre_data structure that options and patterns are passed in
- * @param buf buffer to search
- * @param len size of buffer
- * @param start_offset initial offset into the buffer
- * @param found_offset pointer to an integer so that we know where the search ended
- *
- * *found_offset will be set to -1 when the find is unsucessful OR the routine is inverted
- *
- * @return 1 when we find the string, 0 when we don't (unless we've been passed a flag to invert)
- */
-static int pcre_search(
-    const PcreData *pcre_data,
-    const char *buf,
-    int len,
-    int start_offset,
-    int *found_offset)
-{
-    int matched;
-    int result;
-
-    if(pcre_data == NULL
-       || buf == NULL
-       || len <= 0
-       || start_offset < 0
-       || start_offset >= len
-       || found_offset == NULL)
-    {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-            "Returning 0 because we didn't have the required parameters!\n"););
-        return 0;
-    }
-
-    *found_offset = -1;
-
-    SnortState* ss = snort_conf->state + get_instance_id();
-
-    result = pcre_exec(
-        pcre_data->re,  /* result of pcre_compile() */
-        pcre_data->pe,  /* result of pcre_study()   */
-        buf,            /* the subject string */
-        len,            /* the length of the subject string */
-        start_offset,   /* start at offset 0 in the subject */
-        0,              /* options(handled at compile time */
-        ss->pcre_ovector,      /* vector for substring information */
-        snort_conf->pcre_ovector_size);/* number of elements in the vector */
-
-    if(result >= 0)
-    {
-        matched = 1;
-
-        /* From the PCRE man page: When a match is successful, information
-         * about captured substrings is returned in pairs of integers,
-         * starting at the beginning of ovector, and continuing up to
-         * two-thirds of its length at the most.  The first element of a
-         * pair is set to the offset of the first character in a substring,
-         * and the second is set to the offset of the first character after
-         * the end of a substring. The first pair, ovector[0] and
-         * ovector[1], identify the portion of the subject string matched
-         * by the entire pattern.  The next pair is used for the first
-         * capturing subpattern, and so on. The value returned by
-         * pcre_exec() is the number of pairs that have been set. If there
-         * are no capturing subpatterns, the return value from a successful
-         * match is 1, indicating that just the first pair of offsets has
-         * been set.
-         *
-         * In Snort's case, the ovector size only allows for the first pair
-         * and a single int for scratch space.
-         */
-
-        *found_offset = ss->pcre_ovector[1];
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-            "Setting Doe_ptr and found_offset: %p %d\n", doe_ptr, found_offset););
-    }
-    else if(result == PCRE_ERROR_NOMATCH)
-    {
-        matched = 0;
-    }
-    else
-    {
-        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre_exec error : %d \n", result););
-        return 0;
-    }
-
-    /* invert sense of match */
-    if(pcre_data->options & SNORT_PCRE_INVERT)
-    {
-        matched = !matched;
-    }
-
-    return matched;
-}
-
-//-------------------------------------------------------------------------
-// api methods
-//-------------------------------------------------------------------------
-
-static void ValidatePcreHttpContentModifiers(PcreData *pcre_data)
-{
-    if( pcre_data->options & SNORT_PCRE_RELATIVE )
-        ParseError("PCRE unsupported configuration : both relative & uri options specified");
-
-    if( pcre_data->options & SNORT_PCRE_RAWBYTES )
-        ParseError("PCRE unsupported configuration : both rawbytes & uri options specified");
-}
-
 static void pcre_capture(
     SnortConfig* sc, const void *code, const void *extra)
 {
@@ -546,7 +147,6 @@ static void pcre_parse(
     char delimit = '/';
     int erroffset;
     int compile_flags = 0;
-    unsigned http = 0;
 
     if(data == NULL)
     {
@@ -631,18 +231,7 @@ static void pcre_parse(
              * these are snort specific don't work with pcre or perl
              */
         case 'R':  pcre_data->options |= SNORT_PCRE_RELATIVE; break;
-        case 'B':  pcre_data->options |= SNORT_PCRE_RAWBYTES; break;
         case 'O':  pcre_data->options |= SNORT_OVERRIDE_MATCH_LIMIT; break;
-        case 'U':  pcre_data->options |= SNORT_PCRE_HTTP_URI; http++; break;
-        case 'P':  pcre_data->options |= SNORT_PCRE_HTTP_BODY;  http++; break;
-        case 'H':  pcre_data->options |= SNORT_PCRE_HTTP_HEADER;  http++; break;
-        case 'M':  pcre_data->options |= SNORT_PCRE_HTTP_METHOD;  http++; break;
-        case 'C':  pcre_data->options |= SNORT_PCRE_HTTP_COOKIE;  http++; break;
-        case 'I':  pcre_data->options |= SNORT_PCRE_HTTP_RAW_URI; http++; break;
-        case 'D':  pcre_data->options |= SNORT_PCRE_HTTP_RAW_HEADER; http++; break;
-        case 'K':  pcre_data->options |= SNORT_PCRE_HTTP_RAW_COOKIE; http++; break;
-        case 'S':  pcre_data->options |= SNORT_PCRE_HTTP_STAT_CODE; http++; break;
-        case 'Y':  pcre_data->options |= SNORT_PCRE_HTTP_STAT_MSG; http++; break;
 
         default:
             ParseError("unknown/extra pcre option encountered");
@@ -650,12 +239,6 @@ static void pcre_parse(
         opts++;
     }
 
-    if ( http > 1 )
-        ParseWarning("at most one HTTP buffer may be indicated with pcre");
-
-    if(pcre_data->options & (SNORT_PCRE_HTTP_BUFS))
-        ValidatePcreHttpContentModifiers(pcre_data);
-
     /* now compile the re */
     DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre: compiling %s\n", re););
     pcre_data->re = pcre_compile(re, compile_flags, &error, &erroffset, NULL);
@@ -666,7 +249,6 @@ static void pcre_parse(
                    "%d : %s", re, erroffset, error);
     }
 
-
     /* now study it... */
     pcre_data->pe = pcre_study(pcre_data->re, 0, &error);
 
@@ -739,6 +321,293 @@ static void pcre_parse(
     ParseError("unable to parse pcre regex %s", data);
 }
 
+/**
+ * Perform a search of the PCRE data.
+ *
+ * @param pcre_data structure that options and patterns are passed in
+ * @param buf buffer to search
+ * @param len size of buffer
+ * @param found_offset pointer to an integer so that we know where the search ended
+ *
+ * *found_offset will be set to -1 when the find is unsucessful OR the routine is inverted
+ *
+ * @return 1 when we find the string, 0 when we don't (unless we've been passed a flag to invert)
+ */
+static bool pcre_search(
+    const PcreData *pcre_data,
+    const uint8_t *buf,
+    int len,
+    int start_offset,
+    int *found_offset)
+{
+    bool matched;
+    int result;
+
+    if(pcre_data == NULL
+       || buf == NULL
+       || len <= 0
+       || found_offset == NULL)
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
+            "Returning 0 because we didn't have the required parameters!\n"););
+        return false;
+    }
+
+    *found_offset = -1;
+
+    SnortState* ss = snort_conf->state + get_instance_id();
+
+    result = pcre_exec(
+        pcre_data->re,  /* result of pcre_compile() */
+        pcre_data->pe,  /* result of pcre_study()   */
+        (const char*)buf, /* the subject string */
+        len,            /* the length of the subject string */
+        start_offset,   /* start at offset 0 in the subject */
+        0,              /* options(handled at compile time */
+        ss->pcre_ovector,      /* vector for substring information */
+        snort_conf->pcre_ovector_size);/* number of elements in the vector */
+
+    if(result >= 0)
+    {
+        matched = true;
+
+        /* From the PCRE man page: When a match is successful, information
+         * about captured substrings is returned in pairs of integers,
+         * starting at the beginning of ovector, and continuing up to
+         * two-thirds of its length at the most.  The first element of a
+         * pair is set to the offset of the first character in a substring,
+         * and the second is set to the offset of the first character after
+         * the end of a substring. The first pair, ovector[0] and
+         * ovector[1], identify the portion of the subject string matched
+         * by the entire pattern.  The next pair is used for the first
+         * capturing subpattern, and so on. The value returned by
+         * pcre_exec() is the number of pairs that have been set. If there
+         * are no capturing subpatterns, the return value from a successful
+         * match is 1, indicating that just the first pair of offsets has
+         * been set.
+         *
+         * In Snort's case, the ovector size only allows for the first pair
+         * and a single int for scratch space.
+         */
+
+        *found_offset = ss->pcre_ovector[1];
+        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
+            "Setting Doe_ptr and found_offset: %p %d\n", doe_ptr, found_offset););
+    }
+    else if(result == PCRE_ERROR_NOMATCH)
+    {
+        matched = false;
+    }
+    else
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre_exec error : %d \n", result););
+        return false;
+    }
+
+    /* invert sense of match */
+    if(pcre_data->options & SNORT_PCRE_INVERT)
+    {
+        matched = !matched;
+    }
+
+    return matched;
+}
+
+//-------------------------------------------------------------------------
+// class methods
+//-------------------------------------------------------------------------
+
+class PcreOption : public IpsOption
+{
+public:
+    PcreOption(PcreData* c) :
+        IpsOption(s_name, RULE_OPTION_TYPE_PCRE)
+    { config = c; };
+
+    ~PcreOption();
+
+    uint32_t hash() const;
+    bool operator==(const IpsOption&) const;
+
+    bool is_relative()
+    { return (config->options & SNORT_PCRE_RELATIVE) != 0; };
+
+    int eval(Cursor&, Packet*);
+
+    PcreData* get_data()
+    { return config; };
+
+    void set_data(PcreData* pcre)
+    { config = pcre; };
+
+private:
+    PcreData* config;
+};
+
+PcreOption::~PcreOption()
+{
+    if ( !config )
+        return;
+
+    if (config->expression)
+        free(config->expression);
+    if (config->pe)
+        free(config->pe);
+    if (config->re)
+        free(config->re);
+
+    free(config);
+}
+
+uint32_t PcreOption::hash() const
+{
+    int i,j,k,l,expression_len;
+    uint32_t a,b,c,tmp;
+    const PcreData *data = config;
+
+    expression_len = strlen(data->expression);
+    a = b = c = 0;
+
+    for (i=0,j=0;i<expression_len;i+=4)
+    {
+        tmp = 0;
+        k = expression_len - i;
+        if (k > 4)
+            k=4;
+
+        for (l=0;l<k;l++)
+        {
+            tmp |= *(data->expression + i + l) << l*8;
+        }
+
+        switch (j)
+        {
+            case 0:
+                a += tmp;
+                break;
+            case 1:
+                b += tmp;
+                break;
+            case 2:
+                c += tmp;
+                break;
+        }
+        j++;
+
+        if (j == 3)
+        {
+            mix(a,b,c);
+            j=0;
+        }
+    }
+
+    if (j != 0)
+    {
+        mix(a,b,c);
+    }
+
+    a += data->options;
+
+    mix_str(a,b,c,get_name());
+    final(a,b,c);
+
+    return c;
+}
+
+bool PcreOption::operator==(const IpsOption& ips) const
+{
+    if ( strcmp(get_name(), ips.get_name()) )
+        return false;
+
+    PcreOption& rhs = (PcreOption&)ips;
+    PcreData *left = config;
+    PcreData *right = rhs.config;
+
+    if (( strcmp(left->expression, right->expression) == 0) &&
+        ( left->options == right->options))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+int PcreOption::eval(Cursor& c, Packet*)
+{
+    PcreData *pcre_data = config;
+    int found_offset = -1;  /* where is the ending location of the pattern */
+    bool matched = false;
+
+    PROFILE_VARS;
+    PREPROC_PROFILE_START(pcrePerfStats);
+
+    //short circuit this for testing pcre performance impact
+    if (ScNoPcre())
+    {
+        PREPROC_PROFILE_END(pcrePerfStats);
+        return DETECTION_OPTION_NO_MATCH;
+    }
+
+    unsigned pos = c.get_delta();
+
+    if ( !pos && (pcre_data->options & SNORT_PCRE_RELATIVE) )
+        pos = c.get_pos();
+
+    if ( pos > c.size() )
+        return 0;
+
+    matched = pcre_search(pcre_data, c.buffer(), c.size(), pos, &found_offset);
+
+    if (matched)
+    {
+        if ( found_offset > 0 )
+        {
+            c.set_pos(found_offset);
+            c.set_delta(found_offset);
+        }
+        PREPROC_PROFILE_END(pcrePerfStats);
+        return DETECTION_OPTION_MATCH;
+    }
+
+    PREPROC_PROFILE_END(pcrePerfStats);
+    return DETECTION_OPTION_NO_MATCH;
+}
+
+//-------------------------------------------------------------------------
+// public methods
+//-------------------------------------------------------------------------
+
+PcreData* pcre_get_data(void* pv)
+{
+    PcreOption* opt = (PcreOption*)pv;
+    return opt->get_data();
+}
+
+// we always advance by found_offset so no adjustments to cursor are done
+// here; note also that this means relative pcre matches on overlapping
+// patterns won't work.  given the test pattern "ABABACD":
+//
+// ( sid:1; content:"ABA"; content:"C"; within:1; )
+// ( sid:2; pcre:"/ABA/"; content:"C"; within:1; )
+//
+// sid 1 will fire but sid 2 will NOT.  this example is easily fixed by
+// using content, but more advanced pcre won't work for the relative /
+// overlap case.
+
+bool pcre_next(PcreData* pcre)
+{
+    if ((pcre->options & (SNORT_PCRE_INVERT | SNORT_PCRE_ANCHORED)))
+    {
+        return false; // no go
+    }
+
+    return true;  // continue
+}
+
+//-------------------------------------------------------------------------
+// api methods
+//-------------------------------------------------------------------------
+
 static IpsOption* pcre_ctor(
     SnortConfig* sc, char *data, OptTreeNode *otn)
 {
index 4ee16d1af73ac49437ce5281fe236d950b8b4dfa..af0f76c3eee251d002fab03c2defc53d13123c87 100644 (file)
 
 #include <stdint.h>
 
-// low nibble must be same as HTTP_BUFFER_*
-// see detection_util.h for enum
-#define SNORT_PCRE_HTTP_URI         0x00001 // check URI buffers
-#define SNORT_PCRE_HTTP_HEADER      0x00002 // Check HTTP header buffer
-#define SNORT_PCRE_HTTP_BODY        0x00003 // Check HTTP body buffer
-#define SNORT_PCRE_HTTP_METHOD      0x00004 // Check HTTP method buffer
-#define SNORT_PCRE_HTTP_COOKIE      0x00005 // Check HTTP cookie buffer
-#define SNORT_PCRE_HTTP_STAT_CODE   0x00006
-#define SNORT_PCRE_HTTP_STAT_MSG    0x00007
-#define SNORT_PCRE_HTTP_RAW_URI     0x00008
-#define SNORT_PCRE_HTTP_RAW_HEADER  0x00009
-#define SNORT_PCRE_HTTP_RAW_COOKIE  0x0000A
-#define SNORT_PCRE_HTTP_BUFS        0x0000F
+// FIXTHIS poor encapsulation
 #define SNORT_PCRE_RELATIVE         0x00010 // relative to the end of the last match
 #define SNORT_PCRE_INVERT           0x00020 // invert detect
 #define SNORT_PCRE_RAWBYTES         0x00040 // Don't use decoded buffer (if available)
 #define SNORT_OVERRIDE_MATCH_LIMIT  0x00100 // Override default limits on match & match recursion
 
 #include <pcre.h>
-typedef struct _PcreData
+
+struct PcreData
 {
     pcre *re;           /* compiled regex */
     pcre_extra *pe;     /* studied regex foo */
     int options;        /* sp_pcre specfic options (relative & inverse) */
     char *expression;
+};
 
-    // FIXIT this doesn't need to be thread local but should be split off of this
-    // struct - used only at runtime for dup pcre data???
-    uint32_t search_offset;
-} PcreData;
-
-void PcreDuplicatePcreData(void *src, PcreData *pcre_dup);
-int eval_dup_pcre(void* v, struct Packet* p, PcreData* alt);
-int PcreAdjustRelativeOffsets(PcreData *pcre, uint32_t search_offset);
+PcreData* pcre_get_data(void*);
+bool pcre_next(PcreData*);
 
 #endif
 
index 44d51484ca2abab29d1f24ef7e563373ddf8879c..19ca6200e6dad7ae877a52459f54e374209fb877 100644 (file)
@@ -37,8 +37,7 @@
 #include "snort.h"
 #include "profiler.h"
 #include "fpdetect.h"
-#include "detection/detection_defines.h"
-#include "detection_util.h"
+#include "framework/cursor.h"
 #include "framework/ips_option.h"
 
 static const char* s_name = "pkt_data";
@@ -59,22 +58,18 @@ class PktDataOption : public IpsOption
 {
 public:
     PktDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_PKT_DATA) { };
-
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 };
 
-int PktDataOption::eval(Packet*)
+int PktDataOption::eval(Cursor& c, Packet* p)
 {
-    int rval = DETECTION_OPTION_MATCH;
     PROFILE_VARS;
-
     PREPROC_PROFILE_START(pktDataPerfStats);
 
-    SetDoePtr(NULL, DOE_BUF_STD);
-    DetectFlag_Disable(FLAG_ALT_DETECT);
+    c.reset(p);
 
     PREPROC_PROFILE_END(pktDataPerfStats);
-    return rval;
+    return DETECTION_OPTION_MATCH;
 }
 
 static IpsOption* pkt_data_ctor(
diff --git a/src/ips_options/ips_raw_data.cc b/src/ips_options/ips_raw_data.cc
new file mode 100644 (file)
index 0000000..58392ac
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+ ** Copyright (C) 1998-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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "snort_types.h"
+#include "snort_bounds.h"
+#include "protocols/packet.h"
+#include "parser.h"
+#include "snort_debug.h"
+#include "util.h"
+#include "mstring.h"
+#include "snort.h"
+#include "profiler.h"
+#include "fpdetect.h"
+#include "detection/detection_defines.h"
+#include "detection_util.h"
+#include "framework/cursor.h"
+#include "framework/ips_option.h"
+
+static const char* s_name = "raw_data";
+
+#ifdef PERF_PROFILING
+static THREAD_LOCAL PreprocStats rawDataPerfStats;
+
+static PreprocStats* pd_get_profile(const char* key)
+{
+    if ( !strcmp(key, s_name) )
+        return &rawDataPerfStats;
+
+    return nullptr;
+}
+#endif
+
+class RawDataOption : public IpsOption
+{
+public:
+    RawDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_OTHER) { };
+    int eval(Cursor&, Packet*);
+};
+
+int RawDataOption::eval(Cursor& c, Packet* p)
+{
+    PROFILE_VARS;
+    PREPROC_PROFILE_START(rawDataPerfStats);
+
+    c.set(s_name, p->data, p->dsize);
+
+    PREPROC_PROFILE_END(rawDataPerfStats);
+    return DETECTION_OPTION_MATCH;
+}
+
+static IpsOption* raw_data_ctor(
+    SnortConfig*, char *data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("raw_data takes no arguments");
+
+    return new RawDataOption;
+}
+
+static void raw_data_dtor(IpsOption* p)
+{
+    delete p;
+}
+
+static void raw_data_ginit(SnortConfig*)
+{
+#ifdef PERF_PROFILING
+    RegisterOtnProfile(s_name, &rawDataPerfStats, pd_get_profile);
+#endif
+}
+
+static const IpsApi raw_data_api =
+{
+    {
+        PT_IPS_OPTION,
+        s_name,
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    0, 0,
+    raw_data_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    raw_data_ctor,
+    raw_data_dtor,
+    nullptr
+};
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+    &raw_data_api.base,
+    nullptr
+};
+#else
+const BaseApi* ips_raw_data = &raw_data_api.base;
+#endif
+
similarity index 66%
rename from src/ips_options/replace.cc
rename to src/ips_options/ips_replace.cc
index 55fba27d4375da8bbb3481aa6bab01ade11a6bb6..b45489eb7e75ca8ba9ec693b6ed9b117c73e7e91 100644 (file)
 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 
-#include "replace.h"
+#include "ips_replace.h"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include <assert.h>
+#include <string>
+using namespace std;
 
 #include "snort_types.h"
 #include "snort_bounds.h"
 #include "ips_content.h"
 #include "snort.h"
 #include "packet_io/sfdaq.h"
+#include "framework/cursor.h"
+#include "framework/ips_option.h"
 
 #define MAX_PATTERN_SIZE 2048
 
-static void Replace_Parse(
-    char *rule, OptTreeNode*, PatternMatchData* pmd)
+static void replace_parse(char* args, string& s)
 {
     char tmp_buf[MAX_PATTERN_SIZE];
 
@@ -57,20 +60,19 @@ static void Replace_Parse(
     int pending = 0;
     int cnt = 0;
     int literal = 0;
-    int ret;
 
-    if ( !rule )
+    if ( !args )
     {
         ParseError("missing argument to 'replace' option");
     }
     /* clear out the temp buffer */
     memset(tmp_buf, 0, MAX_PATTERN_SIZE);
 
-    while(isspace((int)*rule))
-        rule++;
+    while(isspace((int)*args))
+        args++;
 
     /* find the start of the data */
-    start_ptr = strchr(rule, '"');
+    start_ptr = strchr(args, '"');
 
     if(start_ptr == NULL)
     {
@@ -297,36 +299,15 @@ static void Replace_Parse(
         ParseError("Replace hexmode is not completed");
     }
 
-    if((pmd->replace_buf = (char *) calloc(dummy_size+1,
-                                                  sizeof(char))) == NULL)
-    {
-        ParseError("Replace pattern_buf malloc failed");
-            
-    }
-
-    ret = SafeMemcpy(pmd->replace_buf, tmp_buf, dummy_size,
-                     pmd->replace_buf, (pmd->replace_buf+dummy_size));
-
-    if (ret == SAFEMEM_ERROR)
-    {
-        ParseError("Replace SafeMemcpy failed");
-    }
-
-    pmd->replace_size = dummy_size;
-    pmd->replace_depth = (int*)SnortAlloc(get_instance_max() * sizeof(int));
-
-    DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
-        "pmd (%p) replace_size(%d) replace_buf(%s)\n", pmd,
-        pmd->replace_size, pmd->replace_buf););
+    s.assign(tmp_buf, dummy_size);
 }
 
-void PayloadReplaceInit(
-    PatternMatchData* pmd, char *data, OptTreeNode * otn)
+static bool replace_ok()
 {
     static int warned = 0;
 
-    if( !ScInlineMode() )
-        return;
+    if ( !ScInlineMode() )
+        return false;
 
     if ( !DAQ_CanReplace() )
     {
@@ -336,20 +317,23 @@ void PayloadReplaceInit(
                 " can't replace packets.\n");
             warned = 1;
         }
-        return;
+        return false;
     }
-
-    Replace_Parse(data, otn, pmd);
+    return true;
 }
 
-typedef struct {
-    const char* data;
-    int size;
-    int depth;
-} Replacement;
+//--------------------------------------------------------------------------
+// queue foo
+//--------------------------------------------------------------------------
+
+struct Replacement
+{
+    string data;
+    int offset;
+};
 
 #define MAX_REPLACEMENTS 32
-static THREAD_LOCAL Replacement rpl[MAX_REPLACEMENTS];
+static THREAD_LOCAL Replacement* rpl;
 static THREAD_LOCAL int num_rpl = 0;
 
 void Replace_ResetQueue(void)
@@ -357,7 +341,7 @@ void Replace_ResetQueue(void)
     num_rpl = 0;
 }
 
-void Replace_QueueChange(PatternMatchData* pmd)
+void Replace_QueueChange(string& s, int off)
 {
     Replacement* r;
 
@@ -366,23 +350,22 @@ void Replace_QueueChange(PatternMatchData* pmd)
 
     r = rpl + num_rpl++;
 
-    r->data = pmd->replace_buf;
-    r->size = pmd->replace_size;
-    r->depth = pmd->replace_depth[get_instance_id()];
+    r->data = s;
+    r->offset = off;
 }
 
 static inline void Replace_ApplyChange(Packet *p, Replacement* r)
 {
-    uint8_t* start = (uint8_t*)p->data + r->depth;
+    uint8_t* start = (uint8_t*)p->data + r->offset;
     const uint8_t* end = p->data + p->dsize;
     unsigned len;
 
-    if ( (start + r->size) >= end )
-        len = p->dsize - r->depth;
+    if ( (start + r->data.size()) >= end )
+        len = p->dsize - r->offset;
     else
-        len = r->size;
+        len = r->data.size();
 
-    memcpy(start, r->data, len);
+    memcpy(start, r->data.c_str(), len);
 }
 
 // FIXIT this could be ContentOption::action()
@@ -400,3 +383,200 @@ void Replace_ModifyPacket(Packet *p)
     num_rpl = 0;
 }
 
+//-------------------------------------------------------------------------
+// replace rule option
+//-------------------------------------------------------------------------
+
+static const char* s_name = "replace";
+
+#ifdef PERF_PROFILING
+static THREAD_LOCAL PreprocStats replacePerfStats;
+
+static PreprocStats* pd_get_profile(const char* key)
+{
+    if ( !strcmp(key, s_name) )
+        return &replacePerfStats;
+
+    return nullptr;
+}
+#endif
+
+class ReplaceOption : public IpsOption
+{
+public:
+    ReplaceOption(string&);
+    ~ReplaceOption();
+
+    int eval(Cursor&, Packet*);
+    void action(Packet*);
+
+    uint32_t hash() const;
+    bool operator==(const IpsOption&) const;
+
+    void store(int off)
+    { offset[get_instance_id()] = off; };
+
+    bool pending()
+    { return offset[get_instance_id()] >= 0; };
+
+    int pos()
+    { return offset[get_instance_id()]; };
+private:
+    string repl;
+    int* offset; /* >=0 is offset to start of replace */
+};
+
+ReplaceOption::ReplaceOption(string& s) : IpsOption(s_name, RULE_OPTION_TYPE_OTHER)
+{
+    unsigned n = get_instance_max();
+    offset = new int[n];
+
+    for ( unsigned i = 0; i < n; i++ )
+        offset[i] = -1;
+
+    repl = s;
+}
+
+ReplaceOption::~ReplaceOption() 
+{
+    delete[] offset;
+}
+
+uint32_t ReplaceOption::hash() const
+{
+    uint32_t a,b,c;
+
+    const char* s = repl.c_str();
+    unsigned n = repl.size();
+
+    a = 0;
+    b = n;
+    c = 0;
+
+    mix(a,b,c);
+    mix_str(a,b,c,s,n);
+    mix_str(a,b,c,get_name());
+    final(a,b,c);
+
+    return c;
+}
+
+bool ReplaceOption::operator==(const IpsOption& ips) const
+{
+    if ( strcmp(get_name(), ips.get_name()) )
+        return false;
+
+    ReplaceOption& rhs = (ReplaceOption&)ips;
+
+    if ( repl != rhs.repl )
+        return false;
+
+    return true;
+}
+
+int ReplaceOption::eval(Cursor& c, Packet* p)
+{
+    PROFILE_VARS;
+    PREPROC_PROFILE_START(replacePerfStats);
+
+    if ( PacketWasCooked(p) )
+        return false;
+
+    if ( !c.is("pkt_data") )
+        return DETECTION_OPTION_NO_MATCH;
+
+    if ( c.length() < repl.size() )
+        return DETECTION_OPTION_NO_MATCH;
+
+    store(c.get_pos());
+
+    PREPROC_PROFILE_END(replacePerfStats);
+    return DETECTION_OPTION_MATCH;
+}
+
+// FIXIT this may need to be apply change here
+// and queue change from some other point
+// (almost certainly broke)
+void ReplaceOption::action(Packet*)
+{
+    PROFILE_VARS;
+    PREPROC_PROFILE_START(replacePerfStats);
+
+    if ( pending() )
+        Replace_QueueChange(repl, pos());
+
+    PREPROC_PROFILE_END(replacePerfStats);
+}
+
+static IpsOption* replace_ctor(
+    SnortConfig*, char *data, OptTreeNode* otn)
+{
+    if ( !replace_ok() )
+        return nullptr;
+
+    string s;
+    replace_parse(data, s);
+
+    ReplaceOption* opt = new ReplaceOption(s);
+
+    if ( otn_set_agent(otn, opt) )
+        return opt;
+
+    delete opt;
+    ParseError("At most one action per rule is allowed");
+    return nullptr;
+}
+
+static void replace_dtor(IpsOption* p)
+{
+    delete p;
+}
+
+static void replace_ginit(SnortConfig*)
+{
+#ifdef PERF_PROFILING
+    RegisterOtnProfile(s_name, &replacePerfStats, pd_get_profile);
+#endif
+}
+
+static void replace_tinit(SnortConfig*)
+{
+    rpl = new Replacement[MAX_REPLACEMENTS];
+}
+
+static void replace_tterm(SnortConfig*)
+{
+    delete[] rpl;
+}
+
+static const IpsApi replace_api =
+{
+    {
+        PT_IPS_OPTION,
+        s_name,
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    0, 0,
+    replace_ginit,
+    nullptr,
+    replace_tinit,
+    replace_tterm,
+    replace_ctor,
+    replace_dtor,
+    nullptr
+};
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+    &replace_api.base,
+    nullptr
+};
+#else
+const BaseApi* ips_replace = &replace_api.base;
+#endif
+
similarity index 71%
rename from src/ips_options/replace.h
rename to src/ips_options/ips_replace.h
index 9961304acd0ed28dcdcad48401f5072f8f6730a6..045918dc3a76b25ef3aec7df20c3770242a79b94 100644 (file)
@@ -32,25 +32,5 @@ void Replace_ResetQueue(void);
 void Replace_QueueChange(PatternMatchData*);
 void Replace_ModifyPacket(Packet*);
 
-static inline void Replace_ResetOffset(PatternMatchData* pmd)
-{
-    if ( pmd->replace_depth )
-        pmd->replace_depth[get_instance_id()] = -1;
-}
-
-static inline void Replace_StoreOffset(PatternMatchData* pmd, int detect_depth)
-{
-    if ( pmd->replace_depth )
-        pmd->replace_depth[get_instance_id()] = detect_depth;
-}
-
-static inline int Replace_OffsetStored(PatternMatchData* pmd)
-{
-    if ( pmd->replace_depth )
-        return pmd->replace_depth[get_instance_id()] >= 0;
-
-    return 0;
-}
-
 #endif
 
index 44df9474fc1fcdedfd3b00da5d2740bfefdde32c..407e2c358bc049ceda0e6667424fb0d1ea4e2146 100644 (file)
@@ -83,7 +83,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     RpcCheckData config;
@@ -132,7 +132,7 @@ bool RpcOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int RpcOption::eval(Packet *p)
+int RpcOption::eval(Cursor&, Packet *p)
 {
     RpcCheckData *ds_ptr = &config;
     unsigned char* c=(unsigned char*)p->data;
index ba78eb1ad30f3d6d087eb2644c0d849acc866838..eae1dc3299b72b7fc7e076f40224022b07c69a41 100644 (file)
@@ -59,14 +59,14 @@ class SameIpOption : public IpsOption
 public:
     SameIpOption() : IpsOption(s_name) { };
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 };
 
 //-------------------------------------------------------------------------
 // class methods
 //-------------------------------------------------------------------------
 
-int SameIpOption::eval(Packet *p)
+int SameIpOption::eval(Cursor&, Packet *p)
 {
     int rval = DETECTION_OPTION_NO_MATCH;
     PROFILE_VARS;
index 409a4a3a8efc9bd5386aa238ac9a15bff6e43811..b64b3d8c6515d86064e22708faa595ea791dc781 100644 (file)
@@ -70,7 +70,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     TcpSeqCheckData config;
@@ -112,7 +112,7 @@ bool TcpSeqOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int TcpSeqOption::eval(Packet *p)
+int TcpSeqOption::eval(Cursor&, Packet *p)
 {
     TcpSeqCheckData *tcpSeqCheckData = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 041c95fd307b542bd5070f1d5046a08989cfa0a8..1b7e7a8e31b9b269cf2154d7044b00f76bc6b0c1 100644 (file)
@@ -105,7 +105,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     SessionData config;
@@ -150,7 +150,7 @@ bool SessionOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int SessionOption::eval(Packet *p)
+int SessionOption::eval(Cursor&, Packet *p)
 {
     SessionData *session_data = &config;
     FILE *session;         /* session file ptr */
index 4533f7b07629e58d0c9de2307c3b764e1528ba54..1075c70d0db92c726810818437f0a88d83b1e775 100644 (file)
@@ -35,7 +35,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet* p)
+    int eval(Cursor&, Packet* p)
     { return func(data, p); };
 
 private:
index 86927cc6893c988278fd58d2de66e85db9541460..7641d48fc83c6eaf8721e5bbda1bac5798cbde26 100644 (file)
@@ -70,7 +70,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
     IpTosData* get_data() 
     { return &config; };
@@ -120,7 +120,7 @@ bool IpTosOption::operator==(const IpsOption& ips) const
  * value in the rule.  This is useful to detect things like the "bubonic" DoS tool.
  */
  
-int IpTosOption::eval(Packet *p)
+int IpTosOption::eval(Cursor&, Packet *p)
 {
     IpTosData *ipTosData = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 76e20cd045e7dbf900e88c4dd66c8e1efb7fa1b4..c78cf5473968ae17094bf749b7d94ebfa5d5e4d0 100644 (file)
@@ -78,7 +78,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     TtlCheckData config;
@@ -123,7 +123,7 @@ bool TtlOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int TtlOption::eval(Packet *p)
+int TtlOption::eval(Cursor&, Packet *p)
 {
     TtlCheckData *ttlCheckData = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 9ec6e809bd8d841cb549cc9c833520bbec83d9dc..fdd35b41a651755933090cff3f48e08ccbb64f99 100644 (file)
@@ -77,7 +77,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     UriLenCheckData config;
@@ -127,7 +127,7 @@ bool UriLenOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int UriLenOption::eval(Packet*)
+int UriLenOption::eval(Cursor&, Packet*)
 {
     UriLenCheckData *udata = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index 73918390060055ec91555fc53b24364efabfa169..749d788a03457bdad5f0868ddfa58a795b698cdc 100644 (file)
@@ -72,7 +72,7 @@ public:
     uint32_t hash() const;
     bool operator==(const IpsOption&) const;
 
-    int eval(Packet*);
+    int eval(Cursor&, Packet*);
 
 private:
     TcpWinCheckData config;
@@ -115,7 +115,7 @@ bool TcpWinOption::operator==(const IpsOption& ips) const
     return false;
 }
 
-int TcpWinOption::eval(Packet *p)
+int TcpWinOption::eval(Cursor&, Packet *p)
 {
     TcpWinCheckData *tcpWinCheckData = &config;
     int rval = DETECTION_OPTION_NO_MATCH;
index abc2d4e975998ebe50389b05ed7c7deeb6389218..656eed3f29823a7715cff28fa50d457f7483f5d6 100644 (file)
@@ -114,7 +114,7 @@ void Analyzer::analyze()
 
             command = AC_NONE;
         }
-        if ( DAQ_Acquire(1, main_func, NULL) )
+        if ( DAQ_Acquire(0, main_func, NULL) )
             break;
 
         ++count;
index 1aecb21f1160e180d3f33bf2a6088a0469d86873..99480ffc37cca392b429fbb6bb409690ac7620de 100644 (file)
@@ -108,7 +108,7 @@ using namespace std;
 #include "target_based/sftarget_reader.h"
 #include "stream/stream_api.h"
 #include "stream/stream.h"
-#include "ips_options/replace.h"
+#include "ips_options/ips_replace.h"
 
 #ifdef INTEL_SOFT_CPM
 #include "search/intel_soft_cpm.h"
index d64667e356462901897a49cefa1ab7625dab642c..a849a122cf4fe701670885b907837173738b7698 100644 (file)
@@ -227,10 +227,9 @@ struct SnortConfig
      * and for Icmp we map the dst port to the Icmp type. This
      * allows us to use the decode packet information to in O(1)
      * select a group of rules to apply to the packet.  These
-     * rules may have uricontent, content, or they may be no content
-     * rules, or any combination. We process the uricontent 1st,
-     * then the content, and then the no content rules for udp/tcp
-     * and icmp, than we process the ip rules. */
+     * rules may or may not have content.  We process the content
+     * 1st and then the no content rules for udp/tcp and icmp, and
+     * then we process the ip rules. */
     PORT_RULE_MAP *prmIpRTNX;
     PORT_RULE_MAP *prmTcpRTNX;
     PORT_RULE_MAP *prmUdpRTNX;
index 73aef49f964fb09338867b75e059536e27191dd0..62341e6feb10e7f87e4290abf0d8e671adad83f2 100644 (file)
@@ -209,7 +209,7 @@ static void dump_field(string& key, const char* pfx, const Parameter* p, bool li
         cout << ": " << p->help;
 
         if ( p->range )
-            cout << " { " << p->range << " }";
+            cout << " { " << (char*)p->range << " }";
 #else
         cout << item();
         cout << p->get_type();
index 1ae9192621d2b4c472a8e125d8c8342b4648efe9..ea2a83e41d085d83bcbaba86d0b2963727ac52ac 100644 (file)
@@ -339,7 +339,6 @@ static const InspectApi as_api =
     IT_PROTOCOL, 
     PROTO_BIT__ARP,
     nullptr, // service
-    nullptr, // contents
     as_init,
     nullptr, // term
     as_ctor,
@@ -349,8 +348,7 @@ static const InspectApi as_api =
     nullptr, // ssn
     as_sum,
     as_stats,
-    as_reset,
-    nullptr  // getbuf
+    as_reset
 };
 
 #ifdef BUILDING_SO
index 4fe211b9c2a5fbb151ae43ef1517a65df900f5ad..18ec902265aaf89cc8e15dee9420fea55f36b385 100644 (file)
@@ -296,7 +296,6 @@ static const InspectApi no_api =
     IT_PACKET,
     PROTO_BITS,
     nullptr, // service
-    nullptr, // contents
     no_init,
     nullptr, // term
     no_ctor,
@@ -306,8 +305,7 @@ static const InspectApi no_api =
     nullptr, // ssn
     no_sum,
     no_stats,
-    no_reset,
-    nullptr  // getbuf
+    no_reset
 };
 
 const BaseApi* nin_normalize = &no_api.base;
index 921154ad2e7f32949321848399d2b5915371ed44..154fdbd491308f6caf7ff806939c1f467b0cd486 100644 (file)
@@ -407,7 +407,6 @@ static const InspectApi pm_api =
     IT_PACKET,
     PROTO_BIT__ALL,
     nullptr, // service
-    nullptr, // contents
     pm_init,
     nullptr, // term
     pm_ctor,
@@ -417,8 +416,7 @@ static const InspectApi pm_api =
     nullptr, // ssn
     pm_sum,
     pm_stats,
-    pm_reset,
-    nullptr  // getbuf
+    pm_reset
 };
 
 const BaseApi* nin_perf_monitor = &pm_api.base;
index e89a5c6c43ded831245f5d61aaa535de4f16a820..8e365537f94b92835a617a4f5b34ab008eb26740 100644 (file)
@@ -1032,7 +1032,6 @@ static const InspectApi sp_api =
     IT_PROTOCOL,
     PROTO_BIT__IP|PROTO_BIT__ICMP|PROTO_BIT__TCP|PROTO_BIT__UDP,  // FIXIT dynamic assign
     nullptr, // service
-    nullptr, // contents
     sp_init,
     nullptr, // term
     sp_ctor,
@@ -1042,8 +1041,7 @@ static const InspectApi sp_api =
     nullptr, // ssn
     sp_sum,
     sp_stats,
-    sp_reset,
-    nullptr  // getbuf
+    sp_reset
 };
 
 #ifdef BUILDING_SO
index 2d13d65de0bf1fd2066e8d59f01c9b04838d6b0d..a3c750a7154c1435e12c3a4b7aae591c30da4d87 100644 (file)
@@ -564,344 +564,3 @@ SO_PUBLIC int mContainsSubstr(const char *buf, int b_len, const char *pat, int p
     return 0;
 }
 
-
-
-
-/****************************************************************
- *
- *  Function: make_skip(char *, int)
- *
- *  Purpose: Create a Boyer-Moore skip table for a given pattern
- *
- *  Parameters:
- *      ptrn => pattern
- *      plen => length of the data in the pattern buffer
- *
- *  Returns:
- *      int * - the skip table
- *
- ****************************************************************/
-int *make_skip(char *ptrn, int plen)
-{
-    int  i;
-    int *skip = (int *) SnortAlloc(256* sizeof(int));
-
-    for ( i = 0; i < 256; i++ )
-        skip[i] = plen + 1;
-
-    while(plen != 0)
-        skip[(unsigned char) *ptrn++] = plen--;
-
-    return skip;
-}
-
-
-
-/****************************************************************
- *
- *  Function: make_shift(char *, int)
- *
- *  Purpose: Create a Boyer-Moore shift table for a given pattern
- *
- *  Parameters:
- *      ptrn => pattern
- *      plen => length of the data in the pattern buffer
- *
- *  Returns:
- *      int * - the shift table
- *
- ****************************************************************/
-int *make_shift(char *ptrn, int plen)
-{
-    int *shift = (int *) SnortAlloc(plen * sizeof(int));
-    int *sptr = shift + plen - 1;
-    char *pptr = ptrn + plen - 1;
-    char c;
-
-     c = ptrn[plen - 1];
-
-    *sptr = 1;
-
-    while(sptr-- != shift)
-    {
-        char *p1 = ptrn + plen - 2, *p2, *p3;
-
-        do
-        {
-            while(p1 >= ptrn && *p1-- != c);
-
-            p2 = ptrn + plen - 2;
-            p3 = p1;
-
-            while(p3 >= ptrn && *p3-- == *p2-- && p2 >= pptr);
-        }
-        while(p3 >= ptrn && p2 >= pptr);
-
-        *sptr = shift + plen - sptr + p2 - p3;
-
-        pptr--;
-    }
-
-    return shift;
-}
-
-
-
-/****************************************************************
- *
- *  Function: mSearch(char *, int, char *, int)
- *
- *  Purpose: Determines if a string contains a (non-regex)
- *           substring.
- *
- *  Parameters:
- *      buf => data buffer we want to find the data in
- *      blen => data buffer length
- *      ptrn => pattern to find
- *      plen => length of the data in the pattern buffer
- *      skip => the B-M skip array
- *      shift => the B-M shift array
- *
- *  Returns:
- *      Integer value, 1 on success (str constains substr), 0 on
- *      failure (substr not in str)
- *
- ****************************************************************/
-SO_PUBLIC int mSearch(const char *buf, int blen, const char *ptrn, int plen, int *skip, int *shift)
-{
-    int b_idx = plen;
-
-#ifdef DEBUG_MSGS
-    char *hexbuf;
-    int cmpcnt = 0;
-#endif
-
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,"buf: %p  blen: %d  ptrn: %p  "
-                "plen: %d\n", buf, blen, ptrn, plen););
-
-#ifdef DEBUG_MSGS
-    hexbuf = fasthex((const u_char *)buf, blen);
-    DebugMessage(DEBUG_PATTERN_MATCH,"buf: %s\n", hexbuf);
-    free(hexbuf);
-    hexbuf = fasthex((const u_char *)ptrn, plen);
-    DebugMessage(DEBUG_PATTERN_MATCH,"ptrn: %s\n", hexbuf);
-    free(hexbuf);
-    DebugMessage(DEBUG_PATTERN_MATCH,"buf: %p  blen: %d  ptrn: %p  "
-                 "plen: %d\n", buf, blen, ptrn, plen);
-#endif /* DEBUG_MSGS */
-    if(plen == 0)
-        return 1;
-
-    while(b_idx <= blen)
-    {
-        int p_idx = plen, skip_stride, shift_stride;
-
-        while(buf[--b_idx] == ptrn[--p_idx])
-        {
-#ifdef DEBUG_MSGS
-            cmpcnt++;
-#endif
-            if(b_idx < 0)
-                return 0;
-
-            if(p_idx == 0)
-            {
-                DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                            "match: compares = %d.\n", cmpcnt););
-                UpdateDoePtr(((const uint8_t *)&(buf[b_idx]) + plen), 0);
-                return 1;
-            }
-        }
-
-        skip_stride = skip[(unsigned char) buf[b_idx]];
-        shift_stride = shift[p_idx];
-
-        b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;
-    }
-
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                "no match: compares = %d.\n", cmpcnt););
-
-    return 0;
-}
-
-
-
-/****************************************************************
- *
- *  Function: mSearchCI(char *, int, char *, int)
- *
- *  Purpose: Determines if a string contains a (non-regex)
- *           substring matching is case insensitive
- *
- *  Parameters:
- *      buf => data buffer we want to find the data in
- *      blen => data buffer length
- *      ptrn => pattern to find
- *      plen => length of the data in the pattern buffer
- *      skip => the B-M skip array
- *      shift => the B-M shift array
- *
- *  Returns:
- *      Integer value, 1 on success (str constains substr), 0 on
- *      failure (substr not in str)
- *
- ****************************************************************/
-SO_PUBLIC int mSearchCI(const char *buf, int blen, const char *ptrn, int plen, int *skip, int *shift)
-{
-    int b_idx = plen;
-#ifdef DEBUG_MSGS
-    int cmpcnt = 0;
-#endif
-
-    if(plen == 0)
-        return 1;
-
-    while(b_idx <= blen)
-    {
-        int p_idx = plen, skip_stride, shift_stride;
-
-        while((unsigned char) ptrn[--p_idx] ==
-                toupper((unsigned char) buf[--b_idx]))
-        {
-#ifdef DEBUG_MSGS
-            cmpcnt++;
-#endif
-            if(p_idx == 0)
-            {
-                DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                            "match: compares = %d.\n",
-                            cmpcnt););
-                UpdateDoePtr(((const uint8_t *)&(buf[b_idx]) + plen), 0);
-                return 1;
-            }
-        }
-
-        skip_stride = skip[toupper((unsigned char) buf[b_idx])];
-        shift_stride = shift[p_idx];
-
-        b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;
-    }
-
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "no match: compares = %d.\n", cmpcnt););
-
-    return 0;
-}
-
-
-/****************************************************************
- *
- *  Function: mSearchREG(char *, int, char *, int)
- *
- *  Purpose: Determines if a string contains a (regex)
- *           substring.
- *
- *  Parameters:
- *      buf => data buffer we want to find the data in
- *      blen => data buffer length
- *      ptrn => pattern to find
- *      plen => length of the data in the pattern buffer
- *      skip => the B-M skip array
- *      shift => the B-M shift array
- *
- *  Returns:
- *      Integer value, 1 on success (str constains substr), 0 on
- *      failure (substr not in str)
- *
- ****************************************************************/
-SO_PUBLIC int mSearchREG(
-    const char *buf, int blen, const char *ptrn, int plen, int *skip, int *shift)
-{
-    int b_idx = plen;
-    int literal = 0;
-    int regexcomp = 0;
-#ifdef DEBUG_MSGS
-    int cmpcnt = 0;
-#endif /* DEBUG_MSGS */
-
-    DEBUG_WRAP(
-              DebugMessage(DEBUG_PATTERN_MATCH, "buf: %p  blen: %d  ptrn: %p "
-                           " plen: %d b_idx: %d\n", buf, blen, ptrn, plen, b_idx);
-              DebugMessage(DEBUG_PATTERN_MATCH, "packet data: \"%s\"\n", buf);
-              DebugMessage(DEBUG_PATTERN_MATCH, "matching for \"%s\"\n", ptrn);
-              );
-
-    if(plen == 0)
-        return 1;
-
-    while(b_idx <= blen)
-    {
-        int p_idx = plen, skip_stride, shift_stride;
-
-       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Looping... "
-                               "([%d]0x%X (%c) -> [%d]0x%X(%c))\n",
-                               b_idx, buf[b_idx-1],
-                               buf[b_idx-1],
-                               p_idx, ptrn[p_idx-1], ptrn[p_idx-1]););
-
-        while(buf[--b_idx] == ptrn[--p_idx]
-              || (ptrn[p_idx] == '?' && !literal)
-              || (ptrn[p_idx] == '*' && !literal)
-              || (ptrn[p_idx] == '\\' && !literal))
-        {
-           DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "comparing: b:%c -> p:%c\n",
-                                   buf[b_idx], ptrn[p_idx]););
-#ifdef DEBUG_MSGS
-            cmpcnt++;
-#endif
-
-            if(literal)
-                literal = 0;
-            if(!literal && ptrn[p_idx] == '\\')
-                literal = 1;
-            if(ptrn[p_idx] == '*')
-            {
-               DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,"Checking wildcard matching...\n"););
-                while(p_idx != 0 && ptrn[--p_idx] == '*'); /* fool-proof */
-
-                while(buf[--b_idx] != ptrn[p_idx])
-                {
-                   DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "comparing: b[%d]:%c -> p[%d]:%c\n",
-                                           b_idx, buf[b_idx], p_idx, ptrn[p_idx]););
-
-                   regexcomp++;
-                    if(b_idx == 0)
-                    {
-                       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                                               "b_idx went to 0, returning 0\n");)
-                        return 0;
-                    }
-                }
-
-               DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "got wildcard final char match! (b[%d]: %c -> p[%d]: %c\n", b_idx, buf[b_idx], p_idx, ptrn[p_idx]););
-            }
-
-            if(p_idx == 0)
-            {
-               DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "match: compares = %d.\n",
-                                       cmpcnt););
-                return 1;
-            }
-
-            if(b_idx == 0)
-                break;
-        }
-
-       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "skip-shifting...\n"););
-       skip_stride = skip[(unsigned char) buf[b_idx]];
-       shift_stride = shift[p_idx];
-
-       b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;
-       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "b_idx skip-shifted to %d\n", b_idx););
-       b_idx += regexcomp;
-       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
-                               "b_idx regex compensated %d steps, to %d\n", regexcomp, b_idx););
-       regexcomp = 0;
-    }
-
-    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "no match: compares = %d, b_idx = %d, "
-                           "blen = %d\n", cmpcnt, b_idx, blen););
-
-    return 0;
-}
-
index 3ea5389ac6a2933bb0710d60e5ab12eb339305b6..c3de46db81d6232d66049057673cb35bb3d868fe 100644 (file)
 char ** mSplit(const char *, const char *, const int, int *, const char);
 void mSplitFree(char ***toks, int numtoks);
 int mContainsSubstr(const char *, int, const char *, int);
-int mSearch(const char *, int, const char *, int, int *, int *);
-int mSearchCI(const char *, int, const char *, int, int *, int *);
-int mSearchREG(const char *, int, const char *, int, int *, int *);
-int *make_skip(char *, int);
-int *make_shift(char *, int);
 
 #endif  /* MSTRING_H */
index 9719f80db0a1f12eb22e8d47f9d864408f8e727c..8063575f1785959b0abe8a0001dad4c8417ab3e3 100644 (file)
@@ -96,7 +96,6 @@ typedef struct
     unsigned int sid;
     int dir;
     char content;
-    char uricontent;
 
 } port_entry_t;
 
@@ -199,8 +198,6 @@ static void port_list_print( port_list_t * plist)
                 plist->pl_array[i].dst_port );
         LogMessage(" content %d",
                 plist->pl_array[i].content);
-        LogMessage(" uricontent %d",
-                plist->pl_array[i].uricontent);
         LogMessage(" }\n");
     }
 }
@@ -294,7 +291,7 @@ static int FinishPortListRule(rule_port_tables_t *port_tables, RuleTreeNode *rtn
     rim_index = otn->ruleIndex;
 
     /* Add up the nocontent rules */
-    if (!pe->content && !pe->uricontent)
+    if ( !pe->content )
         prc->nc++;
 
     /* If not an any-any rule test for port bleedover, if we are using a
@@ -1640,29 +1637,7 @@ void parse_rule(
 
     /* See what kind of content is going in the fast pattern matcher */
     {
-        /* Since http_cookie content is not used in fast pattern matcher,
-         * need to iterate the entire list */
-        if ( otn_has_plugin(otn, RULE_OPTION_TYPE_CONTENT_URI) )
-        {
-            OptFpList* fpl = otn->opt_func;
-
-            while ( fpl )
-            {
-                if ( fpl->type == RULE_OPTION_TYPE_CONTENT_URI )
-                {
-                    PatternMatchData* pmd = get_pmd(fpl);
-
-                    if ( IsHttpBufFpEligible(pmd->http_buffer) )
-                    {
-                        pe.uricontent = 1;
-                        break;
-                    }
-                }
-                fpl = fpl->next;
-            }
-        }
-
-        if (!pe.uricontent && otn_has_plugin(otn, RULE_OPTION_TYPE_CONTENT) )
+        if ( otn_has_plugin(otn, RULE_OPTION_TYPE_CONTENT) )
         {
             pe.content = 1;
         }
index 09f1c3b2e8a9c57f558cff3805b4c170515592c1..0907100c461a2490db6896f535c90dbfde6b9bdb 100644 (file)
@@ -628,7 +628,6 @@ static const InspectApi bo_api =
     IT_PROTOCOL, 
     PROTO_BIT__UDP,
     nullptr, // service
-    nullptr, // contents
     bo_init,
     nullptr, // term
     bo_ctor,
@@ -638,8 +637,7 @@ static const InspectApi bo_api =
     nullptr, // ssn
     bo_sum,
     bo_stats,
-    bo_reset,
-    nullptr  // getbuf
+    bo_reset
 };
 
 #ifdef BUILDING_SO
index 1e3d2eba112c61a9a51170d3be9e450c6b354f73..16beec8ae8ae387a99fcad2f6403824da2d196cd 100644 (file)
@@ -718,7 +718,6 @@ static const InspectApi fs_api =
     IT_SERVICE,
     PROTO_BIT__TCP,
     "ftp",   // FIXIT add ftp-data inspector
-    nullptr, // contents
     fs_init,
     nullptr, // term
     fs_ctor,
@@ -728,8 +727,7 @@ static const InspectApi fs_api =
     nullptr, // ssn
     fs_sum,
     fs_stats,
-    fs_reset,
-    nullptr  // getbuf
+    fs_reset
 };
 
 #ifdef BUILDING_SO
index 096340f37162fa0b0cd5738d75947a1ac55380a1..1d0ec2f8ff4436866b59b520c3080b0424556c3e 100644 (file)
@@ -346,7 +346,6 @@ const InspectApi tn_api =
     IT_SERVICE,
     PROTO_BIT__TCP,
     "telnet",
-    nullptr, // contents
     tn_init,
     nullptr, // term
     tn_ctor,
@@ -357,6 +356,5 @@ const InspectApi tn_api =
     tn_sum,
     tn_stats,
     tn_reset,
-    nullptr  // getbuf
 };
 
index c427ea22c78d362a23713d63d8ef9972a0506194..fe2368e297f2748563d715d3a4d8374aa64f5643 100644 (file)
@@ -2,6 +2,7 @@
 
 set (FILE_LIST
     http_inspect.cc
+    http_inspect.h
     hi_main.cc
     hi_main.h
     hi_ad.cc 
@@ -14,6 +15,7 @@ set (FILE_LIST
     hi_cmd_lookup.cc 
     hi_cmd_lookup.h
     hi_include.h
+    hi_ips_options.cc
     hi_mi.cc 
     hi_mi.h
     hi_norm.cc 
index 0b78f41d353a056723ed8344a70e026ba6590dcf..a43f8e0cdaf1bfd31f4b6798c86da0a74e2c6358 100644 (file)
@@ -1,7 +1,7 @@
 AUTOMAKE_OPTIONS=foreign no-dependencies
 
 file_list = \
-http_inspect.cc \
+http_inspect.cc http_inspect.h \
 hi_main.cc hi_main.h \
 hi_ad.cc hi_ad.h \
 hi_client.cc hi_client.h \
@@ -10,6 +10,7 @@ hi_client_stateful.h \
 hi_cmd_lookup.cc hi_cmd_lookup.h \
 hi_events.h \
 hi_include.h \
+hi_ips_options.cc \
 hi_mi.cc hi_mi.h \
 hi_module.cc hi_module.h \
 hi_norm.cc hi_norm.h \
diff --git a/src/service_inspectors/http_inspect/hi_ips_options.cc b/src/service_inspectors/http_inspect/hi_ips_options.cc
new file mode 100644 (file)
index 0000000..619e446
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+** Copyright (C) 2014 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "snort_types.h"
+#include "treenodes.h"
+#include "protocols/packet.h"
+#include "parser.h"
+#include "util.h"
+#include "snort_debug.h"
+#include "snort.h"
+#include "profiler.h"
+#include "fpdetect.h"
+#include "detection/detection_defines.h"
+#include "detection/detection_util.h"
+#include "framework/ips_option.h"
+#include "framework/cursor.h"
+
+//-------------------------------------------------------------------------
+// api methods
+//-------------------------------------------------------------------------
+
+static const char* s_name = "http_ips";
+
+#ifdef PERF_PROFILING
+static THREAD_LOCAL PreprocStats httpIpsPerfStats;
+
+static PreprocStats* hi_ips_get_profile(const char* key)
+{
+    if ( !strcmp(key, s_name) )
+        return &httpIpsPerfStats;
+
+    return nullptr;
+}
+#endif
+
+static void hi_ips_dtor(IpsOption* p)
+{
+    delete p;
+}
+
+static void hi_ips_ginit(SnortConfig*)
+{
+#ifdef PERF_PROFILING
+    RegisterOtnProfile(s_name, &httpIpsPerfStats, hi_ips_get_profile);
+#endif
+}
+
+//-------------------------------------------------------------------------
+// generic buffer stuffer
+//-------------------------------------------------------------------------
+
+class HttpIpsOption : public IpsOption
+{
+public:
+    HttpIpsOption(const char* s, HTTP_BUFFER b) : IpsOption(s)
+    { key = s; type = b; };
+
+    int eval(Cursor&, Packet*);
+private:
+    const char* key;
+    HTTP_BUFFER type;
+};
+
+int HttpIpsOption::eval(Cursor& c, Packet*)
+{
+    PROFILE_VARS;
+    PREPROC_PROFILE_START(httpIpsPerfStats);
+
+    int rval;
+    const HttpBuffer* hb = GetHttpBuffer(type);
+
+    if ( !hb )
+        rval = DETECTION_OPTION_MATCH;
+    else
+    {
+        c.set(key, hb->buf, hb->length);
+        rval = DETECTION_OPTION_MATCH;
+    }
+
+    PREPROC_PROFILE_END(httpIpsPerfStats);
+    return rval;
+}
+
+//-------------------------------------------------------------------------
+// http_uri
+//-------------------------------------------------------------------------
+
+static IpsOption* http_uri_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_uri");
+
+    return new HttpIpsOption("http_uri", HTTP_BUFFER_URI);
+}
+
+static const IpsApi http_uri_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_uri",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_uri_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_header
+//-------------------------------------------------------------------------
+
+static IpsOption* http_header_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_header");
+
+    return new HttpIpsOption("http_header", HTTP_BUFFER_HEADER);
+}
+
+static const IpsApi http_header_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_header",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_header_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_client_body
+//-------------------------------------------------------------------------
+
+static IpsOption* http_client_body_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_client_body");
+
+    return new HttpIpsOption("http_client_body", HTTP_BUFFER_CLIENT_BODY);
+}
+
+static const IpsApi http_client_body_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_client_body",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_client_body_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_method
+//-------------------------------------------------------------------------
+
+static IpsOption* http_method_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_method");
+
+    return new HttpIpsOption("http_method", HTTP_BUFFER_METHOD);
+}
+
+static const IpsApi http_method_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_method",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_method_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_cookie
+//-------------------------------------------------------------------------
+
+static IpsOption* http_cookie_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_cookie");
+
+    return new HttpIpsOption("http_cookie", HTTP_BUFFER_COOKIE);
+}
+
+static const IpsApi http_cookie_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_cookie",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_cookie_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_stat_code
+//-------------------------------------------------------------------------
+
+static IpsOption* http_stat_code_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_stat_code");
+
+    return new HttpIpsOption("http_stat_code", HTTP_BUFFER_STAT_CODE);
+}
+
+static const IpsApi http_stat_code_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_stat_code",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_stat_code_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_stat_msg
+//-------------------------------------------------------------------------
+
+static IpsOption* http_stat_msg_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_stat_msg");
+
+    return new HttpIpsOption("http_stat_msg", HTTP_BUFFER_STAT_MSG);
+}
+
+static const IpsApi http_stat_msg_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_stat_msg",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_stat_msg_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_uri
+//-------------------------------------------------------------------------
+
+static IpsOption* http_raw_uri_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_raw_uri");
+
+    return new HttpIpsOption("http_raw_uri", HTTP_BUFFER_RAW_URI);
+}
+
+static const IpsApi http_raw_uri_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_raw_uri",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_raw_uri_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_header
+//-------------------------------------------------------------------------
+
+static IpsOption* http_raw_header_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_raw_header");
+
+    return new HttpIpsOption("http_raw_header", HTTP_BUFFER_RAW_HEADER);
+}
+
+static const IpsApi http_raw_header_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_raw_header",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_raw_header_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_cookie
+//-------------------------------------------------------------------------
+
+static IpsOption* http_raw_cookie_ctor(
+    SnortConfig*, char* data, OptTreeNode*)
+{
+    if (!IsEmptyStr(data))
+        ParseError("%s takes no arguments", "http_raw_cookie");
+
+    return new HttpIpsOption("http_raw_cookie", HTTP_BUFFER_RAW_COOKIE);
+}
+
+static const IpsApi http_raw_cookie_api =
+{
+    {
+        PT_IPS_OPTION,
+        "http_raw_cookie",
+        IPSAPI_PLUGIN_V0,
+        0,
+        nullptr,
+        nullptr
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    hi_ips_ginit,
+    nullptr,
+    nullptr,
+    nullptr,
+    http_raw_cookie_ctor,
+    hi_ips_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// plugins
+//-------------------------------------------------------------------------
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+    &http_uri_api.base,
+    &http_header_api.base,
+    &http_client_body_api.base,
+    &http_method_api.base,
+    &http_cookie_api.base,
+    &http_stat_code_api.base,
+    &http_stat_msg_api.base,
+    &http_raw_uri_api.base,
+    &http_raw_header_api.base,
+    &http_raw_cookie_api.base,
+    nullptr
+};
+#else
+const BaseApi* ips_http_uri = &http_uri_api.base;
+const BaseApi* ips_http_header = &http_header_api.base;
+const BaseApi* ips_http_client_body = &http_client_body_api.base;
+const BaseApi* ips_http_method = &http_method_api.base;
+const BaseApi* ips_http_cookie = &http_cookie_api.base;
+const BaseApi* ips_http_stat_code = &http_stat_code_api.base;
+const BaseApi* ips_http_stat_msg = &http_stat_msg_api.base;
+const BaseApi* ips_http_raw_uri = &http_raw_uri_api.base;
+const BaseApi* ips_http_raw_header = &http_raw_header_api.base;
+const BaseApi* ips_http_raw_cookie = &http_raw_cookie_api.base;
+#endif
+
index 7fa65806e092df4fc034762ca3999f4adde91661..967ee7b0bd4ea35484f1531f0483299c3027f086 100644 (file)
 
 #define NON_ASCII_CHAR  0xff
 
+#define HTTP_ENCODE_TYPE__UTF8_UNICODE   0x00000001
+#define HTTP_ENCODE_TYPE__DOUBLE_ENCODE  0x00000002
+#define HTTP_ENCODE_TYPE__NONASCII       0x00000004
+#define HTTP_ENCODE_TYPE__BASE36         0x00000008
+#define HTTP_ENCODE_TYPE__UENCODE        0x00000010
+#define HTTP_ENCODE_TYPE__BARE_BYTE      0x00000020
+#define HTTP_ENCODE_TYPE__IIS_UNICODE    0x00000040
+#define HTTP_ENCODE_TYPE__ASCII          0x00000080
+
 typedef struct s_URI_NORM_STATE
 {
     u_char *abs_uri;
index 1d9eaf4d62d7f235333e895c3e1151202a289fa5..70d1628f48058e25ba7a230021a45f69bdbe3a87 100644 (file)
@@ -507,7 +507,6 @@ static const InspectApi hs_api =
     IT_SERVICE,
     PROTO_BIT__TCP,
     "http",
-    contents,
     hs_init,
     hs_term,
     hs_ctor,
@@ -517,8 +516,7 @@ static const InspectApi hs_api =
     nullptr, // ssn
     hs_sum,
     hs_stats,
-    hs_reset,
-    nullptr  // getbuf
+    hs_reset
 };
 
 #ifdef BUILDING_SO
diff --git a/src/service_inspectors/http_inspect/http_inspect.h b/src/service_inspectors/http_inspect/http_inspect.h
new file mode 100644 (file)
index 0000000..16b093a
--- /dev/null
@@ -0,0 +1,43 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2014 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.
+ *
+ ****************************************************************************/
+
+#ifndef HTTP_INSPECT_H
+#define HTTP_INSPECT_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+struct BaseApi;
+
+extern const BaseApi* ips_http_uri;
+extern const BaseApi* ips_http_header;
+extern const BaseApi* ips_http_client_body;
+extern const BaseApi* ips_http_method;
+extern const BaseApi* ips_http_cookie;
+extern const BaseApi* ips_http_stat_code;
+extern const BaseApi* ips_http_stat_msg;
+extern const BaseApi* ips_http_raw_uri;
+extern const BaseApi* ips_http_raw_header;
+extern const BaseApi* ips_http_raw_cookie;
+
+#endif
+
index 99e77933a73b825fe5dc28ba6cb96de5570ebf75..9c6944b426fda512b71e66359d42ced3bf560fd7 100644 (file)
@@ -108,7 +108,6 @@ const InspectApi NHttpApi::nhttp_api =
     IT_SERVICE,
     PROTO_BIT__TCP,
     "http",
-    nullptr, // contents
     NHttpApi::nhttp_init,
     NHttpApi::nhttp_term,
     NHttpApi::nhttp_ctor,
@@ -118,8 +117,7 @@ const InspectApi NHttpApi::nhttp_api =
     nullptr,
     NHttpApi::nhttp_sum,
     NHttpApi::nhttp_stats,
-    NHttpApi::nhttp_reset,
-    nullptr  // getbuf
+    NHttpApi::nhttp_reset
 };
 
 #ifdef BUILDING_SO
index 67711fbfa7161dd7211d73cc853cf55fa6c741c1..b131b6c8e159c5b00bedd351c923f0197a4100f0 100644 (file)
@@ -1166,7 +1166,6 @@ static const InspectApi rd_api =
     IT_SERVICE,
     PROTO_BIT__TCP,
     "sunrpc",
-    nullptr, // contents
     rd_init,
     nullptr, // term
     rd_ctor,
@@ -1176,8 +1175,7 @@ static const InspectApi rd_api =
     nullptr, // ssn
     rd_sum,
     rd_stats,
-    rd_reset,
-    nullptr  // getbuf
+    rd_reset
 };
 
 #ifdef BUILDING_SO
index 4ef91c57bbfa37349eb028a51f93212cc1e2e2c3..22be9a0703674022590206ca0409210e1c4f7864 100644 (file)
@@ -24,6 +24,7 @@
 #include "config.h"
 #endif
 #include "framework/inspector.h"
+#include "http_inspect/http_inspect.h"
 
 extern const BaseApi* sin_http_global;
 extern const BaseApi* sin_http_server;
@@ -41,6 +42,18 @@ const BaseApi* service_inspectors[] =
 {
     sin_http_global,
     sin_http_server,
+
+    ips_http_uri,
+    ips_http_header,
+    ips_http_client_body,
+    ips_http_method,
+    ips_http_cookie,
+    ips_http_stat_code,
+    ips_http_stat_msg,
+    ips_http_raw_uri,
+    ips_http_raw_header,
+    ips_http_raw_cookie,
+
 #ifdef STATIC_INSPECTORS
     sin_bo,
     sin_ftp_client,
index a5bc47fe8bc589b7acf2262591063c5594066382..8f10a6ed797a86cb4d5e2f4e0b28dea1ac6822f5 100644 (file)
@@ -299,7 +299,6 @@ static const InspectApi base_api =
     IT_STREAM,
     PROTO_BIT__IP,
     nullptr, // service
-    nullptr, // contents
     base_init,
     nullptr, // term
     base_ctor,
@@ -309,8 +308,7 @@ static const InspectApi base_api =
     nullptr, // ssn
     base_sum,
     base_stats,
-    base_reset,
-    nullptr  // getbuf
+    base_reset
 };
 
 const BaseApi* nin_stream_base = &base_api.base;
index 26bb1eac49398c45be0e46e11a0a9610eeeb4236..a26f05de5b1e1efb24def8c42f30a0f70f36aa46 100644 (file)
@@ -123,7 +123,6 @@ static const InspectApi icmp_api =
     IT_STREAM,
     PROTO_BIT__ICMP,
     nullptr, // service
-    nullptr, // contents
     icmp_init,
     nullptr, // term
     icmp_ctor,
@@ -133,8 +132,7 @@ static const InspectApi icmp_api =
     icmp_ssn,
     icmp_sum,
     icmp_stats,
-    icmp_reset,
-    nullptr  // getbuf
+    icmp_reset
 };
 
 const BaseApi* nin_stream_icmp = &icmp_api.base;
index 3e0cc376aec0d396425a84a3d5f307f68c532366..bc70714072687ac397ee3dac2823574e6e4513bb 100644 (file)
@@ -170,7 +170,6 @@ static const InspectApi ip_api =
     IT_STREAM,
     PROTO_BIT__IP,
     nullptr, // service
-    nullptr, // contents
     ip_init,
     nullptr, // term
     ip_ctor,
@@ -180,8 +179,7 @@ static const InspectApi ip_api =
     ip_ssn,
     ip_sum,
     ip_stats,
-    ip_reset,
-    nullptr  // getbuf
+    ip_reset
 };
 
 const BaseApi* nin_stream_ip = &ip_api.base;
index b731523b61ead7be7544d2ac0d0b87a4081f5b2e..d96a9710e66ba0e6d60b8c9d1c4530b3ab440d6a 100644 (file)
@@ -138,7 +138,6 @@ static const InspectApi tcp_api =
     IT_STREAM,
     PROTO_BIT__TCP,
     nullptr, // service
-    nullptr, // contents
     tcp_init,
     nullptr, // term
     tcp_ctor,
@@ -148,8 +147,7 @@ static const InspectApi tcp_api =
     tcp_ssn,
     tcp_sum,
     tcp_stats,
-    tcp_reset,
-    nullptr  // getbuf
+    tcp_reset
 };
 
 const BaseApi* nin_stream_tcp = &tcp_api.base;
index 28bb4acac04699d58d751c12f4bac420c755999f..86e59057af0898488a2ffe25c6106b62cf6e26ad 100644 (file)
@@ -138,7 +138,6 @@ static const InspectApi udp_api =
     IT_STREAM,
     PROTO_BIT__UDP,
     nullptr, // service
-    nullptr, // contents
     udp_init,
     nullptr, // term
     udp_ctor,
@@ -148,8 +147,7 @@ static const InspectApi udp_api =
     udp_ssn,
     udp_sum,
     udp_stats,
-    udp_reset,
-    nullptr  // getbuf
+    udp_reset
 };
 
 const BaseApi* nin_stream_udp = &udp_api.base;
index b4db534851555243c58501bc8e04b6022ef6d9f2..7c31d1580e020cf0d23402bb14c27bbb7f3772a9 100644 (file)
@@ -28,6 +28,8 @@ ADD_LIBRARY( utils STATIC
     ${SNPRINTF_SOURCES}
     asn1.cc 
     asn1.h
+    boyer_moore.cc 
+    boyer_moore.h
     dyn_array.cc
     dyn_array.h
     ring.h 
index ef24e8f9bf68cb8aaef216a4d46378f794e59a66..35d114fbbb5326096f504c6652fa5a7055c32c05 100644 (file)
@@ -16,6 +16,7 @@ stats.h
 
 libutils_a_SOURCES = \
 asn1.cc asn1.h \
+boyer_moore.cc boyer_moore.h \
 dyn_array.cc dyn_array.h \
 ring.h ring_logic.h \
 segment_mem.cc \
diff --git a/src/utils/boyer_moore.cc b/src/utils/boyer_moore.cc
new file mode 100644 (file)
index 0000000..bdece9e
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+** Copyright (C) 2014 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.
+*/
+
+// boyer_moore.cc was split out of mstring.cc which had these comments:
+
+/***************************************************************************
+ *
+ * File: MSTRING.C
+ *
+ * Purpose: Provide a variety of string functions not included in libc.  Makes
+ *          up for the fact that the libstdc++ is hard to get reference
+ *          material on and I don't want to write any more non-portable c++
+ *          code until I have solid references and libraries to use.
+ *
+ * History:
+ *
+ * Date:      Author:  Notes:
+ * ---------- ------- ----------------------------------------------
+ *  08/19/98    MFR    Initial coding begun
+ *  03/06/99    MFR    Added Boyer-Moore pattern match routine, don't use
+ *                     mContainsSubstr() any more if you don't have to
+ *  12/31/99   JGW    Added a full Boyer-Moore implementation to increase
+ *                     performance. Added a case insensitive version of mSearch
+ *  07/24/01    MFR    Fixed Regex pattern matcher introduced by Fyodor
+ *
+ **************************************************************************/
+#include "boyer_moore.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#include "snort_types.h"
+#include "snort_debug.h"
+#include "util.h"
+
+#ifdef TEST_MSTRING
+int main()
+{
+    char test[] = "\0\0\0\0\0\0\0\0\0CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\0\0";
+    char find[] = "CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\0\0";
+
+/*   char test[] = "\x90\x90\x90\x90\x90\x90\xe8\xc0\xff\xff\xff/bin/sh\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";
+     char find[] = "\xe8\xc0\xff\xff\xff/bin/sh";  */
+    int i;
+    int toks;
+    int *shift;
+    int *skip;
+
+/*   shift=make_shift(find,sizeof(find)-1);
+     skip=make_skip(find,sizeof(find)-1); */
+
+    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,"%d\n",
+                           mSearch(test, sizeof(test) - 1, find,
+                                   sizeof(find) - 1, shift, skip)););
+
+    return 0;
+}
+
+#endif
+
+/****************************************************************
+ *
+ *  Function: make_skip(char *, int)
+ *
+ *  Purpose: Create a Boyer-Moore skip table for a given pattern
+ *
+ *  Parameters:
+ *      ptrn => pattern
+ *      plen => length of the data in the pattern buffer
+ *
+ *  Returns:
+ *      int * - the skip table
+ *
+ ****************************************************************/
+int *make_skip(char *ptrn, int plen)
+{
+    int  i;
+    int *skip = (int *) SnortAlloc(256* sizeof(int));
+
+    for ( i = 0; i < 256; i++ )
+        skip[i] = plen + 1;
+
+    while(plen != 0)
+        skip[(unsigned char) *ptrn++] = plen--;
+
+    return skip;
+}
+
+/****************************************************************
+ *
+ *  Function: make_shift(char *, int)
+ *
+ *  Purpose: Create a Boyer-Moore shift table for a given pattern
+ *
+ *  Parameters:
+ *      ptrn => pattern
+ *      plen => length of the data in the pattern buffer
+ *
+ *  Returns:
+ *      int * - the shift table
+ *
+ ****************************************************************/
+int *make_shift(char *ptrn, int plen)
+{
+    int *shift = (int *) SnortAlloc(plen * sizeof(int));
+    int *sptr = shift + plen - 1;
+    char *pptr = ptrn + plen - 1;
+    char c;
+
+     c = ptrn[plen - 1];
+
+    *sptr = 1;
+
+    while(sptr-- != shift)
+    {
+        char *p1 = ptrn + plen - 2, *p2, *p3;
+
+        do
+        {
+            while(p1 >= ptrn && *p1-- != c);
+
+            p2 = ptrn + plen - 2;
+            p3 = p1;
+
+            while(p3 >= ptrn && *p3-- == *p2-- && p2 >= pptr);
+        }
+        while(p3 >= ptrn && p2 >= pptr);
+
+        *sptr = shift + plen - sptr + p2 - p3;
+
+        pptr--;
+    }
+
+    return shift;
+}
+
+/****************************************************************
+ *
+ *  Function: mSearch(char *, int, char *, int)
+ *
+ *  Purpose: Determines if a string contains a (non-regex)
+ *           substring.
+ *
+ *  Parameters:
+ *      buf => data buffer we want to find the data in
+ *      blen => data buffer length
+ *      ptrn => pattern to find
+ *      plen => length of the data in the pattern buffer
+ *      skip => the B-M skip array
+ *      shift => the B-M shift array
+ *
+ *  Returns:
+ *      -1 if not found or offset >= 0 if found
+ *
+ ****************************************************************/
+SO_PUBLIC int mSearch(
+    const char *buf, int blen, const char *ptrn, int plen, int *skip, int *shift)
+{
+    int b_idx = plen;
+
+#ifdef DEBUG_MSGS
+    char *hexbuf;
+    int cmpcnt = 0;
+#endif
+
+    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,"buf: %p  blen: %d  ptrn: %p  "
+                "plen: %d\n", buf, blen, ptrn, plen););
+
+#ifdef DEBUG_MSGS
+    hexbuf = fasthex((const u_char *)buf, blen);
+    DebugMessage(DEBUG_PATTERN_MATCH,"buf: %s\n", hexbuf);
+    free(hexbuf);
+    hexbuf = fasthex((const u_char *)ptrn, plen);
+    DebugMessage(DEBUG_PATTERN_MATCH,"ptrn: %s\n", hexbuf);
+    free(hexbuf);
+    DebugMessage(DEBUG_PATTERN_MATCH,"buf: %p  blen: %d  ptrn: %p  "
+                 "plen: %d\n", buf, blen, ptrn, plen);
+#endif /* DEBUG_MSGS */
+    if(plen == 0)
+        return -1;
+
+    while(b_idx <= blen)
+    {
+        int p_idx = plen, skip_stride, shift_stride;
+
+        while(buf[--b_idx] == ptrn[--p_idx])
+        {
+#ifdef DEBUG_MSGS
+            cmpcnt++;
+#endif
+            if(b_idx < 0)
+                return -1;
+
+            if(p_idx == 0)
+            {
+                DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
+                            "match: compares = %d.\n", cmpcnt););
+                return b_idx;
+            }
+        }
+
+        skip_stride = skip[(unsigned char) buf[b_idx]];
+        shift_stride = shift[p_idx];
+
+        b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;
+    }
+
+    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
+                "no match: compares = %d.\n", cmpcnt););
+
+    return -1;
+}
+
+/****************************************************************
+ *
+ *  Function: mSearchCI(char *, int, char *, int)
+ *
+ *  Purpose: Determines if a string contains a (non-regex)
+ *           substring matching is case insensitive
+ *
+ *  Parameters:
+ *      buf => data buffer we want to find the data in
+ *      blen => data buffer length
+ *      ptrn => pattern to find
+ *      plen => length of the data in the pattern buffer
+ *      skip => the B-M skip array
+ *      shift => the B-M shift array
+ *
+ *  Returns:
+ *      -1 if not found or offset >= 0 if found
+ *
+ ****************************************************************/
+SO_PUBLIC int mSearchCI(const char *buf, int blen, const char *ptrn, int plen, int *skip, int *shift)
+{
+    int b_idx = plen;
+#ifdef DEBUG_MSGS
+    int cmpcnt = 0;
+#endif
+
+    if(plen == 0)
+        return -1;
+
+    while(b_idx <= blen)
+    {
+        int p_idx = plen, skip_stride, shift_stride;
+
+        while((unsigned char) ptrn[--p_idx] ==
+                toupper((unsigned char) buf[--b_idx]))
+        {
+#ifdef DEBUG_MSGS
+            cmpcnt++;
+#endif
+            if(p_idx == 0)
+            {
+                DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
+                            "match: compares = %d.\n",
+                            cmpcnt););
+                return b_idx;
+            }
+        }
+
+        skip_stride = skip[toupper((unsigned char) buf[b_idx])];
+        shift_stride = shift[p_idx];
+
+        b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;
+    }
+
+    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "no match: compares = %d.\n", cmpcnt););
+
+    return -1;
+}
+
+/****************************************************************
+ *
+ *  Function: mSearchREG(char *, int, char *, int)
+ *
+ *  Purpose: Determines if a string contains a (regex)
+ *           substring.
+ *
+ *  Parameters:
+ *      buf => data buffer we want to find the data in
+ *      blen => data buffer length
+ *      ptrn => pattern to find
+ *      plen => length of the data in the pattern buffer
+ *      skip => the B-M skip array
+ *      shift => the B-M shift array
+ *
+ *  Returns:
+ *      1 = found, 0 = not found
+ *
+ ****************************************************************/
+SO_PUBLIC int mSearchREG(
+    const char *buf, int blen, const char *ptrn, int plen, int *skip, int *shift)
+{
+    int b_idx = plen;
+    int literal = 0;
+    int regexcomp = 0;
+#ifdef DEBUG_MSGS
+    int cmpcnt = 0;
+#endif /* DEBUG_MSGS */
+
+    DEBUG_WRAP(
+              DebugMessage(DEBUG_PATTERN_MATCH, "buf: %p  blen: %d  ptrn: %p "
+                           " plen: %d b_idx: %d\n", buf, blen, ptrn, plen, b_idx);
+              DebugMessage(DEBUG_PATTERN_MATCH, "packet data: \"%s\"\n", buf);
+              DebugMessage(DEBUG_PATTERN_MATCH, "matching for \"%s\"\n", ptrn);
+              );
+
+    if(plen == 0)
+        return 1;
+
+    while(b_idx <= blen)
+    {
+        int p_idx = plen, skip_stride, shift_stride;
+
+       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Looping... "
+                               "([%d]0x%X (%c) -> [%d]0x%X(%c))\n",
+                               b_idx, buf[b_idx-1],
+                               buf[b_idx-1],
+                               p_idx, ptrn[p_idx-1], ptrn[p_idx-1]););
+
+        while(buf[--b_idx] == ptrn[--p_idx]
+              || (ptrn[p_idx] == '?' && !literal)
+              || (ptrn[p_idx] == '*' && !literal)
+              || (ptrn[p_idx] == '\\' && !literal))
+        {
+           DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "comparing: b:%c -> p:%c\n",
+                                   buf[b_idx], ptrn[p_idx]););
+#ifdef DEBUG_MSGS
+            cmpcnt++;
+#endif
+
+            if(literal)
+                literal = 0;
+            if(!literal && ptrn[p_idx] == '\\')
+                literal = 1;
+            if(ptrn[p_idx] == '*')
+            {
+               DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,"Checking wildcard matching...\n"););
+                while(p_idx != 0 && ptrn[--p_idx] == '*'); /* fool-proof */
+
+                while(buf[--b_idx] != ptrn[p_idx])
+                {
+                   DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "comparing: b[%d]:%c -> p[%d]:%c\n",
+                                           b_idx, buf[b_idx], p_idx, ptrn[p_idx]););
+
+                   regexcomp++;
+                    if(b_idx == 0)
+                    {
+                       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
+                                               "b_idx went to 0, returning 0\n");)
+                        return 0;
+                    }
+                }
+
+               DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "got wildcard final char match! (b[%d]: %c -> p[%d]: %c\n", b_idx, buf[b_idx], p_idx, ptrn[p_idx]););
+            }
+
+            if(p_idx == 0)
+            {
+               DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "match: compares = %d.\n",
+                                       cmpcnt););
+                return 1;
+            }
+
+            if(b_idx == 0)
+                break;
+        }
+
+       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "skip-shifting...\n"););
+       skip_stride = skip[(unsigned char) buf[b_idx]];
+       shift_stride = shift[p_idx];
+
+       b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;
+       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "b_idx skip-shifted to %d\n", b_idx););
+       b_idx += regexcomp;
+       DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
+                               "b_idx regex compensated %d steps, to %d\n", regexcomp, b_idx););
+       regexcomp = 0;
+    }
+
+    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "no match: compares = %d, b_idx = %d, "
+                           "blen = %d\n", cmpcnt, b_idx, blen););
+
+    return 0;
+}
+
diff --git a/src/utils/boyer_moore.h b/src/utils/boyer_moore.h
new file mode 100644 (file)
index 0000000..518bff4
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+** Copyright (C) 2014 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 BOYER_MOORE_H
+#define BOYER_MOORE_H
+
+// boyer_moore.h was split out of mstring.h
+
+int *make_skip(char *, int);
+int *make_shift(char *, int);
+int mSearch(const char *, int, const char *, int, int *, int *);
+int mSearchCI(const char *, int, const char *, int, int *, int *);
+int mSearchREG(const char *, int, const char *, int, int *, int *);
+
+#endif
+