detect: use generic integer functions for urilen

Ticket: #4112
pull/7603/head
Philippe Antoine 2 years ago committed by Victor Julien
parent e87c53bb55
commit cfb60d0fce

@ -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));
}

@ -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) {

@ -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);

@ -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 *,

Loading…
Cancel
Save