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))
}
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)?;
// 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));
+}
#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 *);
#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");
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);
}
/**
return;
DetectUrilenData *urilend = (DetectUrilenData *)ptr;
- SCFree(urilend);
+ rs_detect_urilen_free(urilend);
}
/** \brief set prefilter dsize pair
*/
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];
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);
}
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);
}
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);