Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rust/cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ include = [
"FtpDataStateValues",
"HTTP2TransactionState",
"DataRepType",
"DETECT_COUNT_INDEX",
]

# A list of items to not include in the generated bindings
Expand Down
2 changes: 2 additions & 0 deletions rust/src/detect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ pub const SIGMATCH_INFO_MULTI_UINT: u32 = 0x80000; // BIT_U32(19)
pub const SIGMATCH_INFO_ENUM_UINT: u32 = 0x100000; // BIT_U32(20)
pub const SIGMATCH_INFO_BITFLAGS_UINT: u32 = 0x200000; // BIT_U32(21)

pub const DETECT_COUNT_INDEX: u32 = 0xFFFFFFFF;

#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
// endian <big|little|dce>
Expand Down
117 changes: 108 additions & 9 deletions rust/src/detect/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,20 @@ pub struct DetectUintData<T> {
pub mode: DetectUintMode,
}

#[repr(C)]
#[derive(Debug, PartialEq)]
pub struct DetectUintIndexPrecise {
pub oob: bool,
pub pos: i32,
}

#[derive(Debug, PartialEq)]
pub enum DetectUintIndex {
Any,
AllOrAbsent,
All,
OrAbsent,
Index((bool, i32)),
Index(DetectUintIndexPrecise),
NumberMatches(DetectUintData<u32>),
Count(DetectUintData<u32>),
}
Expand All @@ -74,7 +81,13 @@ fn parse_uint_index_precise(s: &str) -> IResult<&str, DetectUintIndex> {
let (s, oob) = opt(tag("oob_or")).parse(s)?;
let (s, _) = opt(is_a(" ")).parse(s)?;
let (s, i32_index) = nom_i32.parse(s)?;
Ok((s, DetectUintIndex::Index((oob.is_some(), i32_index))))
Ok((
s,
DetectUintIndex::Index(DetectUintIndexPrecise {
oob: oob.is_some(),
pos: i32_index,
}),
))
}

fn parse_uint_index_nb(s: &str) -> IResult<&str, DetectUintIndex> {
Expand Down Expand Up @@ -112,7 +125,8 @@ fn parse_uint_subslice(parts: &[&str]) -> Option<(i32, i32)> {
return Some((start, end));
}

fn parse_uint_count(s: &str) -> IResult<&str, DetectUintData<u32>> {
fn parse_multi_count(s: &str) -> IResult<&str, DetectUintData<u32>> {
let (s, _) = opt(is_a(" ")).parse(s)?;
let (s, _) = tag("count").parse(s)?;
let (s, _) = opt(is_a(" ")).parse(s)?;
let (s, du32) = detect_parse_uint::<u32>(s)?;
Expand All @@ -129,7 +143,7 @@ fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
// not only a literal, but some numeric value
_ => return parse_uint_index_val(parts[1]),
}
} else if let Ok((_, du)) = parse_uint_count(parts[0]) {
} else if let Ok((_, du)) = parse_multi_count(parts[0]) {
DetectUintIndex::Count(du)
} else {
DetectUintIndex::Any
Expand Down Expand Up @@ -320,15 +334,15 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
}
return 0;
}
DetectUintIndex::Index((oob, idx)) => {
let index = if *idx < 0 {
DetectUintIndex::Index(prec) => {
let index = if prec.pos < 0 {
// negative values for backward indexing.
((subslice.len() as i32) + idx) as usize
((subslice.len() as i32) + prec.pos) as usize
} else {
*idx as usize
prec.pos as usize
};
if subslice.len() <= index {
if *oob && eof {
if prec.oob && eof {
return 1;
}
return 0;
Expand Down Expand Up @@ -988,6 +1002,91 @@ pub unsafe extern "C" fn SCDetectU16Free(ctx: &mut DetectUintData<u16>) {
std::mem::drop(Box::from_raw(ctx));
}

#[no_mangle]
pub unsafe extern "C" fn SCDetectMultiCountParse(ustr: *const std::os::raw::c_char) -> *mut c_void {
let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
if let Ok(s) = ft_name.to_str() {
if let Ok((_, ctx)) = parse_multi_count(s) {
let boxed = Box::new(ctx);
return Box::into_raw(boxed) as *mut c_void;
}
}
return std::ptr::null_mut();
}

/// just a u8 for FFI
#[derive(PartialEq, Eq, Clone, Debug)]
#[repr(u8)]
pub enum DetectMultiIndex {
DetectMultiIndexAny,
DetectMultiIndexAbsentOr,
DetectMultiIndexAll,
DetectMultiIndexAllOrAbsent,
DetectMultiIndexNb,
DetectMultiIndexPrecise,
DetectMultiIndexError,
}

impl DetectUintIndex {
// just borrow
fn index(&self) -> DetectMultiIndex {
match self {
DetectUintIndex::All => DetectMultiIndex::DetectMultiIndexAll,
DetectUintIndex::AllOrAbsent => DetectMultiIndex::DetectMultiIndexAllOrAbsent,
DetectUintIndex::Any => DetectMultiIndex::DetectMultiIndexAny,
DetectUintIndex::OrAbsent => DetectMultiIndex::DetectMultiIndexAbsentOr,
DetectUintIndex::NumberMatches(_) => DetectMultiIndex::DetectMultiIndexNb,
DetectUintIndex::Index(_) => DetectMultiIndex::DetectMultiIndexPrecise,
DetectUintIndex::Count(_) => DetectMultiIndex::DetectMultiIndexError,
}
}

// take ownership and move
fn into_box(self) -> *mut c_void {
match self {
DetectUintIndex::NumberMatches(du32) => {
let boxed = Box::new(du32);
Box::into_raw(boxed) as *mut c_void
}
DetectUintIndex::Index(prec) => {
let boxed = Box::new(prec);
Box::into_raw(boxed) as *mut c_void
}
_ => std::ptr::null_mut(),
}
}
}

#[no_mangle]
pub unsafe extern "C" fn SCDetectMultiIndexFree(ctx: &mut DetectUintIndexPrecise) {
std::mem::drop(Box::from_raw(ctx));
}

fn parse_multi_index(s: &str) -> Option<DetectUintIndex> {
match s {
"all" => Some(DetectUintIndex::All),
"all_or_absent" => Some(DetectUintIndex::AllOrAbsent),
"any" => Some(DetectUintIndex::Any),
"absent_or" => Some(DetectUintIndex::OrAbsent),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

means any or absent

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added any_or_absent syntax sugar

// not only a literal, but some numeric value
_ => return parse_uint_index_val(s),
}
}

#[no_mangle]
pub unsafe extern "C" fn SCDetectMultiIndexParse(
ustr: *const std::os::raw::c_char, it: *mut DetectMultiIndex,
) -> *mut c_void {
let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
if let Ok(s) = ft_name.to_str() {
if let Some(ctx) = parse_multi_index(s) {
*it = ctx.index();
return ctx.into_box();
}
}
return std::ptr::null_mut();
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
36 changes: 21 additions & 15 deletions rust/src/detect/vlan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

use super::uint::{
detect_parse_array_uint, detect_uint_match_at_index, DetectUintArrayData, DetectUintData,
DetectUintIndex,
DetectUintIndex, DetectUintIndexPrecise,
};
use std::ffi::{c_int, c_void, CStr};

Expand Down Expand Up @@ -49,7 +49,7 @@ pub fn detect_parse_vlan_id(s: &str) -> Option<DetectUintArrayData<u16>> {
SCLogError!("vlan id should be less than 4096");
return None;
}
match a.index {
match &a.index {
DetectUintIndex::All => {
// keep previous behavior that vlan.id: all matched only if there was vlan
return Some(DetectUintArrayData {
Expand All @@ -59,8 +59,8 @@ pub fn detect_parse_vlan_id(s: &str) -> Option<DetectUintArrayData<u16>> {
end: a.end,
});
}
DetectUintIndex::Index((_, i)) => {
if !(-VLAN_MAX_LAYERS..=VLAN_MAX_LAYERS - 1).contains(&i) {
DetectUintIndex::Index(prec) => {
if !(-VLAN_MAX_LAYERS..=VLAN_MAX_LAYERS - 1).contains(&prec.pos) {
SCLogError!(
"vlan id index should belong in range {:?}",
(-VLAN_MAX_LAYERS..=VLAN_MAX_LAYERS - 1)
Expand Down Expand Up @@ -110,7 +110,10 @@ pub unsafe extern "C" fn SCDetectVlanIdPrefilterMatch(
DETECT_VLAN_ID_ALL => DetectUintIndex::All,
DETECT_VLAN_ID_ALL_OR_ABSENT => DetectUintIndex::AllOrAbsent,
DETECT_VLAN_ID_OR_ABSENT => DetectUintIndex::OrAbsent,
i => DetectUintIndex::Index((false, i.into())),
i => DetectUintIndex::Index(DetectUintIndexPrecise {
oob: false,
pos: i.into(),
}),
};

let ctx = DetectUintArrayData {
Expand All @@ -127,12 +130,12 @@ pub unsafe extern "C" fn SCDetectVlanIdPrefilterMatch(
pub unsafe extern "C" fn SCDetectVlanIdPrefilter(
ctx: &DetectUintArrayData<u16>,
) -> DetectVlanIdDataPrefilter {
let layer = match ctx.index {
let layer = match &ctx.index {
DetectUintIndex::Any => DETECT_VLAN_ID_ANY,
DetectUintIndex::All => DETECT_VLAN_ID_ALL,
DetectUintIndex::AllOrAbsent => DETECT_VLAN_ID_ALL_OR_ABSENT,
DetectUintIndex::OrAbsent => DETECT_VLAN_ID_OR_ABSENT,
DetectUintIndex::Index((_, i)) => i as i8,
DetectUintIndex::Index(prec) => prec.pos as i8,
DetectUintIndex::NumberMatches(_) => DETECT_VLAN_ID_ERROR,
DetectUintIndex::Count(_) => DETECT_VLAN_ID_ERROR,
};
Expand All @@ -148,13 +151,13 @@ pub unsafe extern "C" fn SCDetectVlanIdPrefilterable(ctx: *const c_void) -> bool
if ctx.start != 0 || ctx.end != 0 {
return false;
}
match ctx.index {
match &ctx.index {
DetectUintIndex::Any => true,
DetectUintIndex::All => true,
DetectUintIndex::AllOrAbsent => true,
DetectUintIndex::OrAbsent => true,
// do not prefilter for precise index with "or out of bounds"
DetectUintIndex::Index((oob, _)) => !oob,
DetectUintIndex::Index(prec) => !prec.oob,
DetectUintIndex::NumberMatches(_) => false,
DetectUintIndex::Count(_) => false,
}
Expand Down Expand Up @@ -214,7 +217,7 @@ mod test {
arg2: 0,
mode: DetectUintMode::DetectUintModeEqual,
},
index: DetectUintIndex::Index((false, 1)),
index: DetectUintIndex::Index(DetectUintIndexPrecise { oob: false, pos: 1 }),
start: 0,
end: 0,
}
Expand All @@ -227,7 +230,10 @@ mod test {
arg2: 0,
mode: DetectUintMode::DetectUintModeEqual,
},
index: DetectUintIndex::Index((false, -1)),
index: DetectUintIndex::Index(DetectUintIndexPrecise {
oob: false,
pos: -1
}),
start: 0,
end: 0,
}
Expand All @@ -240,7 +246,7 @@ mod test {
arg2: 0,
mode: DetectUintMode::DetectUintModeNe,
},
index: DetectUintIndex::Index((false, 2)),
index: DetectUintIndex::Index(DetectUintIndexPrecise { oob: false, pos: 2 }),
start: 0,
end: 0,
}
Expand All @@ -253,7 +259,7 @@ mod test {
arg2: 0,
mode: DetectUintMode::DetectUintModeGt,
},
index: DetectUintIndex::Index((false, 2)),
index: DetectUintIndex::Index(DetectUintIndexPrecise { oob: false, pos: 2 }),
start: 0,
end: 0,
}
Expand All @@ -266,7 +272,7 @@ mod test {
arg2: 300,
mode: DetectUintMode::DetectUintModeRange,
},
index: DetectUintIndex::Index((false, 0)),
index: DetectUintIndex::Index(DetectUintIndexPrecise { oob: false, pos: 0 }),
start: 0,
end: 0,
}
Expand All @@ -279,7 +285,7 @@ mod test {
arg2: 0,
mode: DetectUintMode::DetectUintModeEqual,
},
index: DetectUintIndex::Index((false, 2)),
index: DetectUintIndex::Index(DetectUintIndexPrecise { oob: false, pos: 2 }),
start: 0,
end: 0,
}
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ noinst_HEADERS = \
detect-metadata.h \
detect-modbus.h \
detect-msg.h \
detect-multi.h \
detect-nfs-version.h \
detect-noalert.h \
detect-nocase.h \
Expand Down Expand Up @@ -830,6 +831,7 @@ libsuricata_c_a_SOURCES = \
detect-metadata.c \
detect-modbus.c \
detect-msg.c \
detect-multi.c \
detect-nfs-version.c \
detect-noalert.c \
detect-nocase.c \
Expand Down
2 changes: 2 additions & 0 deletions src/detect-engine-register.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@
#include "detect-ja4-hash.h"
#include "detect-ftp-command.h"
#include "detect-entropy.h"
#include "detect-multi.h"
#include "detect-ftp-command-data.h"
#include "detect-ftp-completion-code.h"
#include "detect-ftp-reply.h"
Expand Down Expand Up @@ -614,6 +615,7 @@ void SigTableSetup(void)
DetectBytejumpRegister();
DetectBytemathRegister();
DetectEntropyRegister();
DetectMultiRegister();
DetectSameipRegister();
DetectGeoipRegister();
DetectL3ProtoRegister();
Expand Down
5 changes: 5 additions & 0 deletions src/detect-engine-register.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ enum DetectKeywordId {
DETECT_URILEN,
DETECT_ABSENT,
DETECT_ENTROPY,
DETECT_MULTI_COUNT,
DETECT_MULTI_ALL,
DETECT_MULTI_ALL_OR_ABSENT,
DETECT_MULTI_NB,
DETECT_MULTI_INDEX,
/* end of content inspection */

DETECT_METADATA,
Expand Down
Loading