]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: use generic integer functions for urilen
authorPhilippe Antoine <pantoine@oisf.net>
Thu, 9 Jun 2022 09:46:38 +0000 (11:46 +0200)
committerVictor Julien <vjulien@oisf.net>
Fri, 1 Jul 2022 15:04:08 +0000 (17:04 +0200)
Ticket: #4112

rust/src/detect.rs
src/detect-engine-content-inspection.c
src/detect-urilen.c
src/detect-urilen.h

index 6bc0ed0f3b24c1f78534331772d0bf83212b1cd5..b568214e74afcd4d0f9f66b4047cdbd918d229cf 100644 (file)
@@ -183,13 +183,18 @@ pub fn detect_match_uint<T: DetectIntType>(x: &DetectUintData<T>, val: T) -> boo
     return false;
 }
 
-pub fn detect_parse_uint<T: DetectIntType>(i: &str) -> IResult<&str, DetectUintData<T>> {
+pub fn detect_parse_uint_notending<T: DetectIntType>(i: &str) -> IResult<&str, DetectUintData<T>> {
     let (i, _) = opt(is_a(" "))(i)?;
     let (i, uint) = alt((
         detect_parse_uint_start_interval,
         detect_parse_uint_start_equal,
         detect_parse_uint_start_symbol,
     ))(i)?;
+    Ok((i, uint))
+}
+
+pub fn detect_parse_uint<T: DetectIntType>(i: &str) -> IResult<&str, DetectUintData<T>> {
+    let (i, uint) = detect_parse_uint_notending(i)?;
     let (i, _) = all_consuming(take_while(|c| c == ' '))(i)?;
     Ok((i, uint))
 }
@@ -349,9 +354,7 @@ pub struct DetectStreamSizeData {
 
 pub fn detect_parse_stream_size(i: &str) -> IResult<&str, DetectStreamSizeData> {
     let (i, _) = opt(is_a(" "))(i)?;
-    let (i, flags) = map_res(alpha0, |s: &str| {
-        DetectStreamSizeDataFlags::from_str(s)
-    })(i)?;
+    let (i, flags) = map_res(alpha0, |s: &str| DetectStreamSizeDataFlags::from_str(s))(i)?;
     let (i, _) = opt(is_a(" "))(i)?;
     let (i, _) = char(',')(i)?;
     let (i, _) = opt(is_a(" "))(i)?;
@@ -388,3 +391,56 @@ pub unsafe extern "C" fn rs_detect_stream_size_free(ctx: &mut DetectStreamSizeDa
     // Just unbox...
     std::mem::drop(Box::from_raw(ctx));
 }
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct DetectUrilenData {
+    pub du16: DetectUintData<u16>,
+    pub raw_buffer: bool,
+}
+
+pub fn detect_parse_urilen_raw(i: &str) -> IResult<&str, bool> {
+    let (i, _) = opt(is_a(" "))(i)?;
+    let (i, _) = char(',')(i)?;
+    let (i, _) = opt(is_a(" "))(i)?;
+    return alt((value(true, tag("raw")), value(false, tag("norm"))))(i);
+}
+
+pub fn detect_parse_urilen(i: &str) -> IResult<&str, DetectUrilenData> {
+    let (i, du16) = detect_parse_uint_notending::<u16>(i)?;
+    let (i, raw) = opt(detect_parse_urilen_raw)(i)?;
+    match raw {
+        Some(raw_buffer) => {
+            return Ok((i, DetectUrilenData { du16, raw_buffer }));
+        }
+        None => {
+            return Ok((
+                i,
+                DetectUrilenData {
+                    du16,
+                    raw_buffer: false,
+                },
+            ));
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_urilen_parse(
+    ustr: *const std::os::raw::c_char,
+) -> *mut DetectUrilenData {
+    let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
+    if let Ok(s) = ft_name.to_str() {
+        if let Ok((_, ctx)) = detect_parse_urilen(s) {
+            let boxed = Box::new(ctx);
+            return Box::into_raw(boxed) as *mut _;
+        }
+    }
+    return std::ptr::null_mut();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_urilen_free(ctx: &mut DetectUrilenData) {
+    // Just unbox...
+    std::mem::drop(Box::from_raw(ctx));
+}
index d0be34ca0d0a8f28cbbe366d20556cb5c58c37e5..94d3f5f7760f923b4b8067bd16b062ca4f66f1c7 100644 (file)
@@ -42,6 +42,7 @@
 #include "detect-engine-content-inspection.h"
 #include "detect-uricontent.h"
 #include "detect-urilen.h"
+#include "detect-engine-uint.h"
 #include "detect-bsize.h"
 #include "detect-lua.h"
 #include "detect-base64-decode.h"
@@ -605,28 +606,12 @@ uint8_t DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThrea
     } else if (smd->type == DETECT_AL_URILEN) {
         SCLogDebug("inspecting uri len");
 
-        uint8_t r = 0;
+        int r = 0;
         DetectUrilenData *urilend = (DetectUrilenData *) smd->ctx;
-
-        switch (urilend->mode) {
-            case DETECT_URILEN_EQ:
-                if (buffer_len == urilend->urilen1)
-                    r = 1;
-                break;
-            case DETECT_URILEN_LT:
-                if (buffer_len < urilend->urilen1)
-                    r = 1;
-                break;
-            case DETECT_URILEN_GT:
-                if (buffer_len > urilend->urilen1)
-                    r = 1;
-                break;
-            case DETECT_URILEN_RA:
-                if (buffer_len > urilend->urilen1 &&
-                    buffer_len < urilend->urilen2) {
-                    r = 1;
-                }
-                break;
+        if (buffer_len > UINT16_MAX) {
+            r = DetectU16Match(UINT16_MAX, &urilend->du16);
+        } else {
+            r = DetectU16Match((uint16_t)buffer_len, &urilend->du16);
         }
 
         if (r == 1) {
index 202fbb05850d6a6abd838eeae4ffdd068881fb86..518f216fca6f865382db79203c46a398d007984e 100644 (file)
@@ -35,6 +35,7 @@
 #include "detect-engine.h"
 #include "detect-engine-state.h"
 #include "detect-content.h"
+#include "detect-engine-uint.h"
 
 #include "detect-urilen.h"
 #include "util-debug.h"
 #include "flow-util.h"
 #include "stream-tcp.h"
 
-/**
- * \brief Regex for parsing our urilen
- */
-#define PARSE_REGEX  "^(?:\\s*)(<|>)?(?:\\s*)([0-9]{1,5})(?:\\s*)(?:(<>)(?:\\s*)([0-9]{1,5}))?\\s*(?:,\\s*(norm|raw))?\\s*$"
-
-static DetectParseRegex parse_regex;
 
 /*prototypes*/
 static int DetectUrilenSetup (DetectEngineCtx *, Signature *, const char *);
@@ -73,7 +68,6 @@ void DetectUrilenRegister(void)
 #ifdef UNITTESTS
     sigmatch_table[DETECT_AL_URILEN].RegisterTests = DetectUrilenRegisterTests;
 #endif
-    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
 
     g_http_uri_buffer_id = DetectBufferTypeRegister("http_uri");
     g_http_raw_uri_buffer_id = DetectBufferTypeRegister("http_raw_uri");
@@ -90,147 +84,7 @@ void DetectUrilenRegister(void)
 
 static DetectUrilenData *DetectUrilenParse (const char *urilenstr)
 {
-    DetectUrilenData *urilend = NULL;
-    char *arg1 = NULL;
-    char *arg2 = NULL;
-    char *arg3 = NULL;
-    char *arg4 = NULL;
-    char *arg5 = NULL;
-    int ret = 0, res = 0;
-    size_t pcre2_len;
-
-    ret = DetectParsePcreExec(&parse_regex, urilenstr, 0, 0);
-    if (ret < 3 || ret > 6) {
-        SCLogError(SC_ERR_PCRE_PARSE, "urilen option pcre parse error: \"%s\"", urilenstr);
-        goto error;
-    }
-    const char *str_ptr;
-
-    SCLogDebug("ret %d", ret);
-
-    res = SC_Pcre2SubstringGet(parse_regex.match, 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
-    if (res < 0) {
-        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_get_bynumber failed");
-        goto error;
-    }
-    arg1 = (char *) str_ptr;
-    SCLogDebug("Arg1 \"%s\"", arg1);
-
-    res = pcre2_substring_get_bynumber(parse_regex.match, 2, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
-    if (res < 0) {
-        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_get_bynumber failed");
-        goto error;
-    }
-    arg2 = (char *) str_ptr;
-    SCLogDebug("Arg2 \"%s\"", arg2);
-
-    if (ret > 3) {
-        res = SC_Pcre2SubstringGet(parse_regex.match, 3, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
-        if (res < 0) {
-            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_get_bynumber failed");
-            goto error;
-        }
-        arg3 = (char *) str_ptr;
-        SCLogDebug("Arg3 \"%s\"", arg3);
-
-        if (ret > 4) {
-            res = SC_Pcre2SubstringGet(parse_regex.match, 4, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
-            if (res < 0) {
-                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_get_bynumber failed");
-                goto error;
-            }
-            arg4 = (char *) str_ptr;
-            SCLogDebug("Arg4 \"%s\"", arg4);
-        }
-        if (ret > 5) {
-            res = pcre2_substring_get_bynumber(
-                    parse_regex.match, 5, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
-            if (res < 0) {
-                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_get_bynumber failed");
-                goto error;
-            }
-            arg5 = (char *) str_ptr;
-            SCLogDebug("Arg5 \"%s\"", arg5);
-        }
-    }
-
-    urilend = SCMalloc(sizeof (DetectUrilenData));
-    if (unlikely(urilend == NULL))
-        goto error;
-    memset(urilend, 0, sizeof(DetectUrilenData));
-
-    if (arg1 != NULL && arg1[0] == '<')
-        urilend->mode = DETECT_URILEN_LT;
-    else if (arg1 != NULL && arg1[0] == '>')
-        urilend->mode = DETECT_URILEN_GT;
-    else
-        urilend->mode = DETECT_URILEN_EQ;
-
-    if (arg3 != NULL && strcmp("<>", arg3) == 0) {
-        if (arg1 != NULL && strlen(arg1) != 0) {
-            SCLogError(SC_ERR_INVALID_ARGUMENT,"Range specified but mode also set");
-            goto error;
-        }
-        urilend->mode = DETECT_URILEN_RA;
-    }
-
-    /** set the first urilen value */
-    if (StringParseUint16(&urilend->urilen1, 10, (uint16_t)strlen(arg2), arg2) <= 0) {
-        SCLogError(SC_ERR_INVALID_ARGUMENT,"Invalid size :\"%s\"",arg2);
-        goto error;
-    }
-
-    /** set the second urilen value if specified */
-    if (arg4 != NULL && strlen(arg4) > 0) {
-        if (urilend->mode != DETECT_URILEN_RA) {
-            SCLogError(SC_ERR_INVALID_ARGUMENT,"Multiple urilen values specified"
-                                           " but mode is not range");
-            goto error;
-        }
-
-        if (StringParseUint16(&urilend->urilen2, 10, (uint16_t)strlen(arg4), arg4) <= 0) {
-            SCLogError(SC_ERR_INVALID_ARGUMENT,"Invalid size :\"%s\"",arg4);
-            goto error;
-        }
-
-        if (urilend->urilen2 <= urilend->urilen1){
-            SCLogError(SC_ERR_INVALID_ARGUMENT,"urilen2:%"PRIu16" <= urilen:"
-                        "%"PRIu16"",urilend->urilen2,urilend->urilen1);
-            goto error;
-        }
-    }
-
-    if (arg5 != NULL) {
-        if (strcasecmp("raw", arg5) == 0) {
-            urilend->raw_buffer = 1;
-        }
-    }
-
-    if (arg1 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg1);
-    pcre2_substring_free((PCRE2_UCHAR *)arg2);
-    if (arg3 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg3);
-    if (arg4 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg4);
-    if (arg5 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg5);
-    return urilend;
-
-error:
-    if (urilend)
-        SCFree(urilend);
-    if (arg1 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg1);
-    if (arg2 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg2);
-    if (arg3 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg3);
-    if (arg4 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg4);
-    if (arg5 != NULL)
-        pcre2_substring_free((PCRE2_UCHAR *)arg5);
-    return NULL;
+    return rs_detect_urilen_parse(urilenstr);
 }
 
 /**
@@ -284,7 +138,7 @@ static void DetectUrilenFree(DetectEngineCtx *de_ctx, void *ptr)
         return;
 
     DetectUrilenData *urilend = (DetectUrilenData *)ptr;
-    SCFree(urilend);
+    rs_detect_urilen_free(urilend);
 }
 
 /** \brief set prefilter dsize pair
@@ -292,7 +146,7 @@ static void DetectUrilenFree(DetectEngineCtx *de_ctx, void *ptr)
  */
 void DetectUrilenApplyToContent(Signature *s, int list)
 {
-    uint16_t high = 65535;
+    uint16_t high = UINT16_MAX;
     bool found = false;
 
     SigMatch *sm = s->init_data->smlists[list];
@@ -302,25 +156,35 @@ void DetectUrilenApplyToContent(Signature *s, int list)
 
         DetectUrilenData *dd = (DetectUrilenData *)sm->ctx;
 
-        switch (dd->mode) {
-            case DETECT_URILEN_LT:
-                high = dd->urilen1 + 1;
+        switch (dd->du16.mode) {
+            case DETECT_UINT_LT:
+                if (dd->du16.arg1 < UINT16_MAX) {
+                    high = dd->du16.arg1 + 1;
+                }
                 break;
-            case DETECT_URILEN_EQ:
-                high = dd->urilen1;
+            case DETECT_UINT_LTE:
+                // fallthrough
+            case DETECT_UINT_EQ:
+                high = dd->du16.arg1;
                 break;
-            case DETECT_URILEN_RA:
-                high = dd->urilen2 + 1;
+            case DETECT_UINT_RA:
+                if (dd->du16.arg2 < UINT16_MAX) {
+                    high = dd->du16.arg2 + 1;
+                }
                 break;
-            case DETECT_URILEN_GT:
-                high = 65535;
+            case DETECT_UINT_NE:
+                // fallthrough
+            case DETECT_UINT_GTE:
+                // fallthrough
+            case DETECT_UINT_GT:
+                high = UINT16_MAX;
                 break;
         }
         found = true;
     }
 
     // skip 65535 to avoid mismatch on uri > 64k
-    if (!found || high == 65535)
+    if (!found || high == UINT16_MAX)
         return;
 
     SCLogDebug("high %u", high);
@@ -336,7 +200,7 @@ void DetectUrilenApplyToContent(Signature *s, int list)
         }
 
         if (cd->depth == 0 || cd->depth > high) {
-            cd->depth = (uint16_t)high;
+            cd->depth = high;
             SCLogDebug("updated %u, content %u to have depth %u "
                     "because of urilen.", s->id, cd->id, cd->depth);
         }
@@ -382,8 +246,8 @@ static int DetectUrilenParseTest01(void)
 
     urilend = DetectUrilenParse("10");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 10 && urilend->mode == DETECT_URILEN_EQ &&
-            !urilend->raw_buffer)
+        if (urilend->du16.arg1 == 10 && urilend->du16.mode == DETECT_UINT_EQ &&
+                !urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -399,8 +263,8 @@ static int DetectUrilenParseTest02(void)
 
     urilend = DetectUrilenParse(" < 10  ");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 10 && urilend->mode == DETECT_URILEN_LT &&
-            !urilend->raw_buffer)
+        if (urilend->du16.arg1 == 10 && urilend->du16.mode == DETECT_UINT_LT &&
+                !urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -416,8 +280,8 @@ static int DetectUrilenParseTest03(void)
 
     urilend = DetectUrilenParse(" > 10 ");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 10 && urilend->mode == DETECT_URILEN_GT &&
-            !urilend->raw_buffer)
+        if (urilend->du16.arg1 == 10 && urilend->du16.mode == DETECT_UINT_GT &&
+                !urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -433,9 +297,8 @@ static int DetectUrilenParseTest04(void)
 
     urilend = DetectUrilenParse(" 5 <> 10 ");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 5 && urilend->urilen2 == 10 &&
-            urilend->mode == DETECT_URILEN_RA &&
-            !urilend->raw_buffer)
+        if (urilend->du16.arg1 == 5 && urilend->du16.arg2 == 10 &&
+                urilend->du16.mode == DETECT_UINT_RA && !urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -451,9 +314,8 @@ static int DetectUrilenParseTest05(void)
 
     urilend = DetectUrilenParse("5<>10,norm");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 5 && urilend->urilen2 == 10 &&
-            urilend->mode == DETECT_URILEN_RA &&
-            !urilend->raw_buffer)
+        if (urilend->du16.arg1 == 5 && urilend->du16.arg2 == 10 &&
+                urilend->du16.mode == DETECT_UINT_RA && !urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -469,9 +331,8 @@ static int DetectUrilenParseTest06(void)
 
     urilend = DetectUrilenParse("5<>10,raw");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 5 && urilend->urilen2 == 10 &&
-            urilend->mode == DETECT_URILEN_RA &&
-            urilend->raw_buffer)
+        if (urilend->du16.arg1 == 5 && urilend->du16.arg2 == 10 &&
+                urilend->du16.mode == DETECT_UINT_RA && urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -487,8 +348,8 @@ static int DetectUrilenParseTest07(void)
 
     urilend = DetectUrilenParse(">10, norm ");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 10 && urilend->mode == DETECT_URILEN_GT &&
-            !urilend->raw_buffer)
+        if (urilend->du16.arg1 == 10 && urilend->du16.mode == DETECT_UINT_GT &&
+                !urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -504,8 +365,8 @@ static int DetectUrilenParseTest08(void)
 
     urilend = DetectUrilenParse("<10, norm ");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 10 && urilend->mode == DETECT_URILEN_LT &&
-            !urilend->raw_buffer)
+        if (urilend->du16.arg1 == 10 && urilend->du16.mode == DETECT_UINT_LT &&
+                !urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -521,8 +382,7 @@ static int DetectUrilenParseTest09(void)
 
     urilend = DetectUrilenParse(">10, raw ");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 10 && urilend->mode == DETECT_URILEN_GT &&
-            urilend->raw_buffer)
+        if (urilend->du16.arg1 == 10 && urilend->du16.mode == DETECT_UINT_GT && urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -538,8 +398,7 @@ static int DetectUrilenParseTest10(void)
 
     urilend = DetectUrilenParse("<10, raw ");
     if (urilend != NULL) {
-        if (urilend->urilen1 == 10 && urilend->mode == DETECT_URILEN_LT &&
-            urilend->raw_buffer)
+        if (urilend->du16.arg1 == 10 && urilend->du16.mode == DETECT_UINT_LT && urilend->raw_buffer)
             ret = 1;
 
         DetectUrilenFree(NULL, urilend);
@@ -613,13 +472,14 @@ static int DetectUrilenSetpTest01(void)
         goto cleanup;
 
     if (urilend != NULL) {
-        if (urilend->urilen1 == 1 && urilend->urilen2 == 2 &&
-                urilend->mode == DETECT_URILEN_RA)
+        if (urilend->du16.arg1 == 1 && urilend->du16.arg2 == 2 &&
+                urilend->du16.mode == DETECT_UINT_RA)
             res = 1;
     }
 
 cleanup:
-    if (urilend) SCFree(urilend);
+    if (urilend)
+        DetectUrilenFree(NULL, urilend);
     SigGroupCleanup(de_ctx);
     SigCleanSignatures(de_ctx);
     DetectEngineCtxFree(de_ctx);
index 30f53c6aa762f39f5895d921f181796a7af83ac7..4f16cbdf8f7ef4311e44742c03e27d923a8e4c38 100644 (file)
 #ifndef _DETECT_URILEN_H
 #define        _DETECT_URILEN_H
 
-#define DETECT_URILEN_LT   0   /**< "less than" operator */
-#define DETECT_URILEN_GT   1   /**< "greater than" operator */
-#define DETECT_URILEN_RA   2   /**< range operator */
-#define DETECT_URILEN_EQ   3   /**< equal operator */
-
-typedef struct DetectUrilenData_ {
-    uint16_t urilen1;   /**< 1st Uri Length value in the signature*/
-    uint16_t urilen2;   /**< 2nd Uri Length value in the signature*/
-    uint8_t mode;   /**< operator used in the signature */
-    uint8_t raw_buffer;
-}DetectUrilenData;
-
 bool DetectUrilenValidateContent(const Signature *s, int list, const char **);
 void DetectUrilenApplyToContent(Signature *s, int list);
 int DetectUrilenMatch (ThreadVars *, DetectEngineThreadCtx *, Flow *,