|
|
|
@ -17,7 +17,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
use nom7::branch::alt;
|
|
|
|
use nom7::branch::alt;
|
|
|
|
use nom7::bytes::complete::{is_a, tag, tag_no_case, take_while};
|
|
|
|
use nom7::bytes::complete::{is_a, tag, tag_no_case, take_while};
|
|
|
|
use nom7::character::complete::{char, digit1, hex_digit1};
|
|
|
|
use nom7::character::complete::{char, digit1, hex_digit1, i32 as nom_i32};
|
|
|
|
use nom7::combinator::{all_consuming, map_opt, opt, value, verify};
|
|
|
|
use nom7::combinator::{all_consuming, map_opt, opt, value, verify};
|
|
|
|
use nom7::error::{make_error, Error, ErrorKind};
|
|
|
|
use nom7::error::{make_error, Error, ErrorKind};
|
|
|
|
use nom7::Err;
|
|
|
|
use nom7::Err;
|
|
|
|
@ -26,7 +26,6 @@ use nom7::IResult;
|
|
|
|
use super::EnumString;
|
|
|
|
use super::EnumString;
|
|
|
|
|
|
|
|
|
|
|
|
use std::ffi::{c_int, c_void, CStr};
|
|
|
|
use std::ffi::{c_int, c_void, CStr};
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
|
|
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
|
|
|
#[repr(u8)]
|
|
|
|
#[repr(u8)]
|
|
|
|
@ -57,6 +56,7 @@ pub enum DetectUintIndex {
|
|
|
|
All,
|
|
|
|
All,
|
|
|
|
All1,
|
|
|
|
All1,
|
|
|
|
Index(i32),
|
|
|
|
Index(i32),
|
|
|
|
|
|
|
|
NumberMatches(DetectUintData<u32>),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
@ -65,16 +65,30 @@ pub struct DetectUintArrayData<T> {
|
|
|
|
pub index: DetectUintIndex,
|
|
|
|
pub index: DetectUintIndex,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn parse_uint_index_precise(s: &str) -> IResult<&str, DetectUintIndex> {
|
|
|
|
|
|
|
|
let (s, i32_index) = nom_i32(s)?;
|
|
|
|
|
|
|
|
Ok((s, DetectUintIndex::Index(i32_index)))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn parse_uint_index_nb(s: &str) -> IResult<&str, DetectUintIndex> {
|
|
|
|
|
|
|
|
let (s, _) = tag("nb")(s)?;
|
|
|
|
|
|
|
|
let (s, du32) = detect_parse_uint::<u32>(s)?;
|
|
|
|
|
|
|
|
Ok((s, DetectUintIndex::NumberMatches(du32)))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn parse_uint_index_val(s: &str) -> Option<DetectUintIndex> {
|
|
|
|
|
|
|
|
let (_s, arg1) = alt((parse_uint_index_precise, parse_uint_index_nb))(s).ok()?;
|
|
|
|
|
|
|
|
Some(arg1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
|
|
|
|
fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
|
|
|
|
let index = if parts.len() == 2 {
|
|
|
|
let index = if parts.len() == 2 {
|
|
|
|
match parts[1] {
|
|
|
|
match parts[1] {
|
|
|
|
"all" => DetectUintIndex::All,
|
|
|
|
"all" => DetectUintIndex::All,
|
|
|
|
"all1" => DetectUintIndex::All1,
|
|
|
|
"all1" => DetectUintIndex::All1,
|
|
|
|
"any" => DetectUintIndex::Any,
|
|
|
|
"any" => DetectUintIndex::Any,
|
|
|
|
_ => {
|
|
|
|
// not only a literal, but some numeric value
|
|
|
|
let i32_index = i32::from_str(parts[1]).ok()?;
|
|
|
|
_ => return parse_uint_index_val(parts[1]),
|
|
|
|
DetectUintIndex::Index(i32_index)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
DetectUintIndex::Any
|
|
|
|
DetectUintIndex::Any
|
|
|
|
@ -111,7 +125,7 @@ pub(crate) fn detect_parse_array_uint_enum<T1: DetectIntType, T2: EnumString<T1>
|
|
|
|
pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
|
|
|
|
pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
|
|
|
|
array: &[T], ctx: &DetectUintArrayData<U>, get_value: impl Fn(&T) -> Option<U>, eof: bool,
|
|
|
|
array: &[T], ctx: &DetectUintArrayData<U>, get_value: impl Fn(&T) -> Option<U>, eof: bool,
|
|
|
|
) -> c_int {
|
|
|
|
) -> c_int {
|
|
|
|
match ctx.index {
|
|
|
|
match &ctx.index {
|
|
|
|
DetectUintIndex::Any => {
|
|
|
|
DetectUintIndex::Any => {
|
|
|
|
for response in array {
|
|
|
|
for response in array {
|
|
|
|
if let Some(code) = get_value(response) {
|
|
|
|
if let Some(code) = get_value(response) {
|
|
|
|
@ -122,6 +136,28 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DetectUintIndex::NumberMatches(du32) => {
|
|
|
|
|
|
|
|
if !eof {
|
|
|
|
|
|
|
|
match du32.mode {
|
|
|
|
|
|
|
|
DetectUintMode::DetectUintModeGt | DetectUintMode::DetectUintModeGte => {}
|
|
|
|
|
|
|
|
_ => {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut nb = 0u32;
|
|
|
|
|
|
|
|
for response in array {
|
|
|
|
|
|
|
|
if let Some(code) = get_value(response) {
|
|
|
|
|
|
|
|
if detect_match_uint::<U>(&ctx.du, code) {
|
|
|
|
|
|
|
|
nb += 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if detect_match_uint(du32, nb) {
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
DetectUintIndex::All => {
|
|
|
|
DetectUintIndex::All => {
|
|
|
|
if !eof {
|
|
|
|
if !eof {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
@ -154,11 +190,11 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DetectUintIndex::Index(idx) => {
|
|
|
|
DetectUintIndex::Index(idx) => {
|
|
|
|
let index = if idx < 0 {
|
|
|
|
let index = if *idx < 0 {
|
|
|
|
// negative values for backward indexing.
|
|
|
|
// negative values for backward indexing.
|
|
|
|
((array.len() as i32) + idx) as usize
|
|
|
|
((array.len() as i32) + idx) as usize
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
idx as usize
|
|
|
|
*idx as usize
|
|
|
|
};
|
|
|
|
};
|
|
|
|
if array.len() <= index {
|
|
|
|
if array.len() <= index {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
|