From cfb60d0fce0357b167e025b193d1c896a1c53519 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 9 Jun 2022 11:46:38 +0200 Subject: [PATCH] detect: use generic integer functions for urilen Ticket: #4112 --- rust/src/detect.rs | 64 ++++++- src/detect-engine-content-inspection.c | 27 +-- src/detect-urilen.c | 234 +++++-------------------- src/detect-urilen.h | 12 -- 4 files changed, 113 insertions(+), 224 deletions(-) diff --git a/rust/src/detect.rs b/rust/src/detect.rs index 6bc0ed0f3b..b568214e74 100644 --- a/rust/src/detect.rs +++ b/rust/src/detect.rs @@ -183,13 +183,18 @@ pub fn detect_match_uint(x: &DetectUintData, val: T) -> boo return false; } -pub fn detect_parse_uint(i: &str) -> IResult<&str, DetectUintData> { +pub fn detect_parse_uint_notending(i: &str) -> IResult<&str, DetectUintData> { 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(i: &str) -> IResult<&str, DetectUintData> { + 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, + 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::(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)); +} diff --git a/src/detect-engine-content-inspection.c b/src/detect-engine-content-inspection.c index d0be34ca0d..94d3f5f776 100644 --- a/src/detect-engine-content-inspection.c +++ b/src/detect-engine-content-inspection.c @@ -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) { diff --git a/src/detect-urilen.c b/src/detect-urilen.c index 202fbb0585..518f216fca 100644 --- a/src/detect-urilen.c +++ b/src/detect-urilen.c @@ -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" @@ -42,12 +43,6 @@ #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); diff --git a/src/detect-urilen.h b/src/detect-urilen.h index 30f53c6aa7..4f16cbdf8f 100644 --- a/src/detect-urilen.h +++ b/src/detect-urilen.h @@ -24,18 +24,6 @@ #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 *,