Move it away from http2 to generic core crate.
And use it for DCERPC (and SMB)
And remove the C version.
Main change in API is the free function is not free itself, but
a rust wrapper around unbox.
Ticket: #4112
DCERPCState, DCERPCTransaction, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE,
DCERPC_UUID_ENTRY_FLAG_FF,
};
+use crate::detect::{detect_match_uint, detect_parse_uint, DetectUintData};
use std::ffi::CStr;
use std::os::raw::{c_char, c_void};
use uuid::Uuid;
-pub const DETECT_DCE_IFACE_OP_NONE: u8 = 0;
-pub const DETECT_DCE_IFACE_OP_LT: u8 = 1;
-pub const DETECT_DCE_IFACE_OP_GT: u8 = 2;
-pub const DETECT_DCE_IFACE_OP_EQ: u8 = 3;
-pub const DETECT_DCE_IFACE_OP_NE: u8 = 4;
-
pub const DETECT_DCE_OPNUM_RANGE_UNINITIALIZED: u32 = 100000;
#[derive(Debug)]
pub struct DCEIfaceData {
pub if_uuid: Vec<u8>,
- pub op: u8,
- pub version: u16,
+ pub du16: Option<DetectUintData<u16>>,
pub any_frag: u8,
}
pub data: Vec<DCEOpnumRange>,
}
-fn extract_op_version(opver: &str) -> Result<(u8, u16), ()> {
- if !opver.is_char_boundary(1){
- return Err(());
- }
- let (op, version) = opver.split_at(1);
- let opval: u8 = match op {
- ">" => DETECT_DCE_IFACE_OP_GT,
- "<" => DETECT_DCE_IFACE_OP_LT,
- "=" => DETECT_DCE_IFACE_OP_EQ,
- "!" => DETECT_DCE_IFACE_OP_NE,
- _ => DETECT_DCE_IFACE_OP_NONE,
- };
-
- let version: u16 = match version.parse::<u16>() {
- Ok(res) => res,
- _ => {
- return Err(());
- }
- };
- if opval == DETECT_DCE_IFACE_OP_NONE
- || (opval == DETECT_DCE_IFACE_OP_LT && version == std::u16::MIN)
- || (opval == DETECT_DCE_IFACE_OP_GT && version == std::u16::MAX)
- {
- return Err(());
- }
-
- Ok((opval, version))
-}
-
-fn match_iface_version(version: u16, if_data: &DCEIfaceData) -> bool {
- match if_data.op {
- DETECT_DCE_IFACE_OP_LT => version < if_data.version,
- DETECT_DCE_IFACE_OP_GT => version > if_data.version,
- DETECT_DCE_IFACE_OP_EQ => version == if_data.version,
- DETECT_DCE_IFACE_OP_NE => version != if_data.version,
- _ => {
- return true;
- }
- }
-}
-
fn match_backuuid(
tx: &mut DCERPCTransaction, state: &mut DCERPCState, if_data: &mut DCEIfaceData,
) -> u8 {
continue;
}
- if if_data.op != DETECT_DCE_IFACE_OP_NONE
- && !match_iface_version(uuidentry.version, if_data)
- {
- SCLogDebug!("Interface version did not match");
- ret &= 0;
+ if let Some(x) = &if_data.du16 {
+ if !detect_match_uint(&x, uuidentry.version) {
+ SCLogDebug!("Interface version did not match");
+ ret &= 0;
+ }
}
if ret == 1 {
fn parse_iface_data(arg: &str) -> Result<DCEIfaceData, ()> {
let split_args: Vec<&str> = arg.split(',').collect();
- let mut op_version = (0, 0);
+ let mut du16 = None;
let mut any_frag: u8 = 0;
let if_uuid = match Uuid::parse_str(split_args[0]) {
Ok(res) => res.as_bytes().to_vec(),
any_frag = 1;
}
_ => {
- op_version = match extract_op_version(split_args[1]) {
- Ok((op, ver)) => (op, ver),
+ match detect_parse_uint(split_args[1]) {
+ Ok((_, x)) => du16 = Some(x),
_ => {
return Err(());
}
}
},
3 => {
- op_version = match extract_op_version(split_args[1]) {
- Ok((op, ver)) => (op, ver),
+ match detect_parse_uint(split_args[1]) {
+ Ok((_, x)) => du16 = Some(x),
_ => {
return Err(());
}
Ok(DCEIfaceData {
if_uuid: if_uuid,
- op: op_version.0,
- version: op_version.1,
+ du16: du16,
any_frag: any_frag,
})
}
#[cfg(test)]
mod test {
use super::*;
+ use crate::detect::DetectUintMode;
+ fn extract_op_version(i: &str) -> Result<(DetectUintMode, u16), ()> {
+ match detect_parse_uint(i) {
+ Ok((_, d)) => return Ok((d.mode, d.arg1)),
+ _ => {
+ return Err(());
+ }
+ }
+ }
#[test]
fn test_extract_op_version() {
let op_version = "<1";
assert_eq!(
- Ok((DETECT_DCE_IFACE_OP_LT, 1)),
+ Ok((DetectUintMode::DetectUintModeLt, 1)),
extract_op_version(op_version)
);
let op_version = ">10";
assert_eq!(
- Ok((DETECT_DCE_IFACE_OP_GT, 10)),
+ Ok((DetectUintMode::DetectUintModeGt, 10)),
extract_op_version(op_version)
);
let op_version = "=45";
assert_eq!(
- Ok((DETECT_DCE_IFACE_OP_EQ, 45)),
+ Ok((DetectUintMode::DetectUintModeEqual, 45)),
extract_op_version(op_version)
);
let op_version = "!0";
assert_eq!(
- Ok((DETECT_DCE_IFACE_OP_NE, 0)),
+ Ok((DetectUintMode::DetectUintModeNe, 0)),
extract_op_version(op_version)
);
assert_eq!(true, extract_op_version(op_version).is_err());
let op_version = "";
- assert_eq!(
- Err(()),
- extract_op_version(op_version)
- );
-
+ assert_eq!(Err(()), extract_op_version(op_version));
}
#[test]
fn test_match_iface_version() {
- let iface_data = DCEIfaceData {
- if_uuid: Vec::new(),
- op: 3,
- version: 10,
- any_frag: 0,
+ let iface_data = DetectUintData::<u16> {
+ mode: DetectUintMode::DetectUintModeEqual,
+ arg1: 10,
+ arg2: 0,
};
- let version = 10;
- assert_eq!(true, match_iface_version(version, &iface_data));
+ let version: u16 = 10;
+ assert_eq!(true, detect_match_uint(&iface_data, version));
- let version = 2;
- assert_eq!(false, match_iface_version(version, &iface_data));
+ let version: u16 = 2;
+ assert_eq!(false, detect_match_uint(&iface_data, version));
}
#[test]
let uuid = Uuid::from_slice(iface_data.if_uuid.as_slice());
let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
assert_eq!(expected_uuid, uuid);
- assert_eq!(DETECT_DCE_IFACE_OP_GT, iface_data.op);
- assert_eq!(1, iface_data.version);
+ let du16 = iface_data.du16.unwrap();
+ assert_eq!(DetectUintMode::DetectUintModeGt, du16.mode);
+ assert_eq!(1, du16.arg1);
let arg = "12345678-1234-1234-1234-123456789ABC,any_frag";
let iface_data = parse_iface_data(arg).unwrap();
let uuid = Uuid::from_slice(iface_data.if_uuid.as_slice());
let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
assert_eq!(expected_uuid, uuid);
- assert_eq!(DETECT_DCE_IFACE_OP_NONE, iface_data.op);
+ assert!(iface_data.du16.is_none());
assert_eq!(1, iface_data.any_frag);
- assert_eq!(0, iface_data.version);
let arg = "12345678-1234-1234-1234-123456789ABC,!10,any_frag";
let iface_data = parse_iface_data(arg).unwrap();
let uuid = Uuid::from_slice(iface_data.if_uuid.as_slice());
let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
assert_eq!(expected_uuid, uuid);
- assert_eq!(DETECT_DCE_IFACE_OP_NE, iface_data.op);
assert_eq!(1, iface_data.any_frag);
- assert_eq!(10, iface_data.version);
+ let du16 = iface_data.du16.unwrap();
+ assert_eq!(DetectUintMode::DetectUintModeNe, du16.mode);
+ assert_eq!(10, du16.arg1);
let arg = "12345678-1234-1234-1234-123456789ABC,>1,ay_frag";
let iface_data = parse_iface_data(arg);
let iface_data = parse_iface_data(arg);
assert_eq!(iface_data.is_err(), true);
- let arg = "12345678-1234-1234-1234-123456789ABC,>=1,any_frag";
+ let arg = "12345678-1234-1234-1234-123456789ABC,>=0,any_frag";
let iface_data = parse_iface_data(arg);
assert_eq!(iface_data.is_err(), true);
--- /dev/null
+/* Copyright (C) 2022 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+use nom7::branch::alt;
+use nom7::bytes::complete::{is_a, tag, take_while};
+use nom7::character::complete::digit1;
+use nom7::combinator::{all_consuming, map_opt, opt, value, verify};
+use nom7::error::{make_error, ErrorKind};
+use nom7::Err;
+use nom7::IResult;
+
+use std::ffi::CStr;
+
+#[derive(PartialEq, Clone, Debug)]
+#[repr(u8)]
+pub enum DetectUintMode {
+ DetectUintModeEqual,
+ DetectUintModeLt,
+ DetectUintModeLte,
+ DetectUintModeGt,
+ DetectUintModeGte,
+ DetectUintModeRange,
+ DetectUintModeNe,
+}
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct DetectUintData<T> {
+ pub arg1: T,
+ pub arg2: T,
+ pub mode: DetectUintMode,
+}
+
+pub trait DetectIntType:
+ std::str::FromStr + std::cmp::PartialOrd + num::PrimInt + num::Bounded
+{
+}
+impl<T> DetectIntType for T where
+ T: std::str::FromStr + std::cmp::PartialOrd + num::PrimInt + num::Bounded
+{
+}
+
+fn detect_parse_uint_start_equal<T: DetectIntType>(i: &str) -> IResult<&str, DetectUintData<T>> {
+ let (i, _) = opt(tag("="))(i)?;
+ let (i, _) = opt(is_a(" "))(i)?;
+ let (i, arg1) = map_opt(digit1, |s: &str| s.parse::<T>().ok())(i)?;
+ Ok((
+ i,
+ DetectUintData {
+ arg1,
+ arg2: T::min_value(),
+ mode: DetectUintMode::DetectUintModeEqual,
+ },
+ ))
+}
+
+fn detect_parse_uint_start_interval<T: DetectIntType>(i: &str) -> IResult<&str, DetectUintData<T>> {
+ let (i, arg1) = map_opt(digit1, |s: &str| s.parse::<T>().ok())(i)?;
+ let (i, _) = opt(is_a(" "))(i)?;
+ let (i, _) = alt((tag("-"), tag("<>")))(i)?;
+ let (i, _) = opt(is_a(" "))(i)?;
+ let (i, arg2) = verify(map_opt(digit1, |s: &str| s.parse::<T>().ok()), |x| {
+ x > &arg1 && *x - arg1 > T::one()
+ })(i)?;
+ Ok((
+ i,
+ DetectUintData {
+ arg1,
+ arg2,
+ mode: DetectUintMode::DetectUintModeRange,
+ },
+ ))
+}
+
+fn detect_parse_uint_mode(i: &str) -> IResult<&str, DetectUintMode> {
+ let (i, mode) = alt((
+ value(DetectUintMode::DetectUintModeGte, tag(">=")),
+ value(DetectUintMode::DetectUintModeLte, tag("<=")),
+ value(DetectUintMode::DetectUintModeGt, tag(">")),
+ value(DetectUintMode::DetectUintModeLt, tag("<")),
+ value(DetectUintMode::DetectUintModeNe, tag("!")),
+ ))(i)?;
+ return Ok((i, mode));
+}
+
+fn detect_parse_uint_start_symbol<T: DetectIntType>(i: &str) -> IResult<&str, DetectUintData<T>> {
+ let (i, mode) = detect_parse_uint_mode(i)?;
+ let (i, _) = opt(is_a(" "))(i)?;
+ let (i, arg1) = map_opt(digit1, |s: &str| s.parse::<T>().ok())(i)?;
+
+ match mode {
+ DetectUintMode::DetectUintModeNe => {}
+ DetectUintMode::DetectUintModeLt => {
+ if arg1 == T::min_value() {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ }
+ DetectUintMode::DetectUintModeLte => {
+ if arg1 == T::max_value() {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ }
+ DetectUintMode::DetectUintModeGt => {
+ if arg1 == T::max_value() {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ }
+ DetectUintMode::DetectUintModeGte => {
+ if arg1 == T::min_value() {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ }
+ _ => {
+ return Err(Err::Error(make_error(i, ErrorKind::MapOpt)));
+ }
+ }
+
+ Ok((
+ i,
+ DetectUintData {
+ arg1,
+ arg2: T::min_value(),
+ mode: mode,
+ },
+ ))
+}
+
+pub fn detect_match_uint<T: DetectIntType>(x: &DetectUintData<T>, val: T) -> bool {
+ match x.mode {
+ DetectUintMode::DetectUintModeEqual => {
+ if val == x.arg1 {
+ return true;
+ }
+ }
+ DetectUintMode::DetectUintModeNe => {
+ if val != x.arg1 {
+ return true;
+ }
+ }
+ DetectUintMode::DetectUintModeLt => {
+ if val < x.arg1 {
+ return true;
+ }
+ }
+ DetectUintMode::DetectUintModeLte => {
+ if val <= x.arg1 {
+ return true;
+ }
+ }
+ DetectUintMode::DetectUintModeGt => {
+ if val > x.arg1 {
+ return true;
+ }
+ }
+ DetectUintMode::DetectUintModeGte => {
+ if val >= x.arg1 {
+ return true;
+ }
+ }
+ DetectUintMode::DetectUintModeRange => {
+ if val > x.arg1 && val < x.arg2 {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+pub fn detect_parse_uint<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)?;
+ let (i, _) = all_consuming(take_while(|c| c == ' '))(i)?;
+ Ok((i, uint))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_u64_parse(
+ ustr: *const std::os::raw::c_char,
+) -> *mut DetectUintData<u64> {
+ let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
+ if let Ok(s) = ft_name.to_str() {
+ if let Ok((_, ctx)) = detect_parse_uint::<u64>(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_u64_free(ctx: *mut std::os::raw::c_void) {
+ // Just unbox...
+ std::mem::drop(Box::from_raw(ctx as *mut DetectUintData<u64>));
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_u32_parse(
+ ustr: *const std::os::raw::c_char,
+) -> *mut DetectUintData<u32> {
+ let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
+ if let Ok(s) = ft_name.to_str() {
+ if let Ok((_, ctx)) = detect_parse_uint::<u32>(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_u32_match(
+ arg: u32, ctx: &DetectUintData<u32>,
+) -> std::os::raw::c_int {
+ if detect_match_uint(ctx, arg) {
+ return 1;
+ }
+ return 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_u32_free(ctx: &mut DetectUintData<u32>) {
+ // Just unbox...
+ std::mem::drop(Box::from_raw(ctx));
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_u8_parse(
+ ustr: *const std::os::raw::c_char,
+) -> *mut DetectUintData<u8> {
+ let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
+ if let Ok(s) = ft_name.to_str() {
+ if let Ok((_, ctx)) = detect_parse_uint::<u8>(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_u8_match(
+ arg: u8, ctx: &DetectUintData<u8>,
+) -> std::os::raw::c_int {
+ if detect_match_uint(ctx, arg) {
+ return 1;
+ }
+ return 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_u8_free(ctx: &mut DetectUintData<u8>) {
+ // Just unbox...
+ std::mem::drop(Box::from_raw(ctx));
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_u16_parse(
+ ustr: *const std::os::raw::c_char,
+) -> *mut DetectUintData<u16> {
+ let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
+ if let Ok(s) = ft_name.to_str() {
+ if let Ok((_, ctx)) = detect_parse_uint::<u16>(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_u16_match(
+ arg: u16, ctx: &DetectUintData<u16>,
+) -> std::os::raw::c_int {
+ if detect_match_uint(ctx, arg) {
+ return 1;
+ }
+ return 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_detect_u16_free(ctx: &mut DetectUintData<u16>) {
+ // Just unbox...
+ std::mem::drop(Box::from_raw(ctx));
+}
};
use super::parser;
use crate::core::Direction;
+use crate::detect::{detect_match_uint, DetectUintData};
use std::ffi::CStr;
use std::str::FromStr;
None => {
return 1;
}
- Some(x) => match x.mode {
- parser::DetectUintMode::DetectUintModeEqual => {
- if set[i].value == x.value {
- return 1;
- }
- }
- parser::DetectUintMode::DetectUintModeLt => {
- if set[i].value <= x.value {
- return 1;
- }
- }
- parser::DetectUintMode::DetectUintModeGt => {
- if set[i].value >= x.value {
- return 1;
- }
- }
- parser::DetectUintMode::DetectUintModeRange => {
- if set[i].value <= x.value && set[i].value >= x.valrange {
- return 1;
- }
+ Some(x) => {
+ if detect_match_uint(&x, set[i].value) {
+ return 1;
}
- },
+ }
}
}
}
return http2_detect_settingsctx_match(ctx, tx, direction.into());
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_detect_u64_parse(
- str: *const std::os::raw::c_char,
-) -> *mut std::os::raw::c_void {
- let ft_name: &CStr = CStr::from_ptr(str); //unsafe
- if let Ok(s) = ft_name.to_str() {
- if let Ok((_, ctx)) = parser::detect_parse_u64(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_u64_free(ctx: *mut std::os::raw::c_void) {
- // Just unbox...
- std::mem::drop(Box::from_raw(ctx as *mut parser::DetectU64Data));
-}
-
fn http2_detect_sizeupdate_match(
- blocks: &[parser::HTTP2FrameHeaderBlock], ctx: &parser::DetectU64Data,
+ blocks: &[parser::HTTP2FrameHeaderBlock], ctx: &DetectUintData<u64>,
) -> std::os::raw::c_int {
for block in blocks.iter() {
- match ctx.mode {
- parser::DetectUintMode::DetectUintModeEqual => {
- if block.sizeupdate == ctx.value
- && block.error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
- {
- return 1;
- }
- }
- parser::DetectUintMode::DetectUintModeLt => {
- if block.sizeupdate <= ctx.value
- && block.error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
- {
- return 1;
- }
- }
- parser::DetectUintMode::DetectUintModeGt => {
- if block.sizeupdate >= ctx.value
- && block.error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
- {
- return 1;
- }
- }
- parser::DetectUintMode::DetectUintModeRange => {
- if block.sizeupdate <= ctx.value
- && block.sizeupdate >= ctx.valrange
- && block.error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
- {
- return 1;
- }
+ if block.error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate {
+ if detect_match_uint(&ctx, block.sizeupdate) {
+ return 1;
}
}
}
}
fn http2_detect_sizeupdatectx_match(
- ctx: &mut parser::DetectU64Data, tx: &mut HTTP2Transaction, direction: Direction,
+ ctx: &mut DetectUintData<u64>, tx: &mut HTTP2Transaction, direction: Direction,
) -> std::os::raw::c_int {
if direction == Direction::ToServer {
for i in 0..tx.frames_ts.len() {
pub unsafe extern "C" fn rs_http2_detect_sizeupdatectx_match(
ctx: *const std::os::raw::c_void, tx: *mut std::os::raw::c_void, direction: u8,
) -> std::os::raw::c_int {
- let ctx = cast_pointer!(ctx, parser::DetectU64Data);
+ let ctx = cast_pointer!(ctx, DetectUintData<u64>);
let tx = cast_pointer!(tx, HTTP2Transaction);
return http2_detect_sizeupdatectx_match(ctx, tx, direction.into());
}
use super::huffman;
use crate::common::nom7::bits;
+use crate::detect::{detect_parse_uint, DetectUintData};
use crate::http2::http2::{HTTP2DynTable, HTTP2_MAX_TABLESIZE};
use nom7::bits::streaming::take as take_bits;
use nom7::branch::alt;
-use nom7::bytes::streaming::{is_a, is_not, tag, take, take_while};
-use nom7::character::complete::digit1;
+use nom7::bytes::streaming::{is_a, is_not, take, take_while};
use nom7::combinator::{complete, cond, map_opt, opt, rest, verify};
use nom7::error::{make_error, ErrorKind};
use nom7::multi::many0;
}
}
-//TODOask move elsewhere generic with DetectU64Data and such
-#[derive(PartialEq, Debug)]
-pub enum DetectUintMode {
- DetectUintModeEqual,
- DetectUintModeLt,
- DetectUintModeGt,
- DetectUintModeRange,
-}
-
-pub struct DetectU32Data {
- pub value: u32,
- pub valrange: u32,
- pub mode: DetectUintMode,
-}
-
pub struct DetectHTTP2settingsSigCtx {
- pub id: HTTP2SettingsId, //identifier
- pub value: Option<DetectU32Data>, //optional value
-}
-
-fn detect_parse_u32_start_equal(i: &str) -> IResult<&str, DetectU32Data> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = opt(tag("="))(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, value) = map_opt(digit1, |s: &str| s.parse::<u32>().ok())(i)?;
- Ok((
- i,
- DetectU32Data {
- value,
- valrange: 0,
- mode: DetectUintMode::DetectUintModeEqual,
- },
- ))
-}
-
-fn detect_parse_u32_start_interval(i: &str) -> IResult<&str, DetectU32Data> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, value) = map_opt(digit1, |s: &str| s.parse::<u32>().ok())(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = tag("-")(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, valrange) = map_opt(digit1, |s: &str| s.parse::<u32>().ok())(i)?;
- Ok((
- i,
- DetectU32Data {
- value,
- valrange,
- mode: DetectUintMode::DetectUintModeRange,
- },
- ))
-}
-
-fn detect_parse_u32_start_lesser(i: &str) -> IResult<&str, DetectU32Data> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = tag("<")(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, value) = map_opt(digit1, |s: &str| s.parse::<u32>().ok())(i)?;
- Ok((
- i,
- DetectU32Data {
- value,
- valrange: 0,
- mode: DetectUintMode::DetectUintModeLt,
- },
- ))
-}
-
-fn detect_parse_u32_start_greater(i: &str) -> IResult<&str, DetectU32Data> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = tag(">")(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, value) = map_opt(digit1, |s: &str| s.parse::<u32>().ok())(i)?;
- Ok((
- i,
- DetectU32Data {
- value,
- valrange: 0,
- mode: DetectUintMode::DetectUintModeGt,
- },
- ))
-}
-
-fn detect_parse_u32(i: &str) -> IResult<&str, DetectU32Data> {
- let (i, u32) = alt((
- detect_parse_u32_start_lesser,
- detect_parse_u32_start_greater,
- complete(detect_parse_u32_start_interval),
- detect_parse_u32_start_equal,
- ))(i)?;
- Ok((i, u32))
+ pub id: HTTP2SettingsId, //identifier
+ pub value: Option<DetectUintData<u32>>, //optional value
}
pub fn http2_parse_settingsctx(i: &str) -> IResult<&str, DetectHTTP2settingsSigCtx> {
let (i, id) = map_opt(alt((complete(is_not(" <>=")), rest)), |s: &str| {
HTTP2SettingsId::from_str(s).ok()
})(i)?;
- let (i, value) = opt(complete(detect_parse_u32))(i)?;
+ let (i, value) = opt(complete(detect_parse_uint))(i)?;
Ok((i, DetectHTTP2settingsSigCtx { id, value }))
}
-pub struct DetectU64Data {
- pub value: u64,
- pub valrange: u64,
- pub mode: DetectUintMode,
-}
-
-fn detect_parse_u64_start_equal(i: &str) -> IResult<&str, DetectU64Data> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = opt(tag("="))(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, value) = map_opt(digit1, |s: &str| s.parse::<u64>().ok())(i)?;
- Ok((
- i,
- DetectU64Data {
- value,
- valrange: 0,
- mode: DetectUintMode::DetectUintModeEqual,
- },
- ))
-}
-
-fn detect_parse_u64_start_interval(i: &str) -> IResult<&str, DetectU64Data> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, value) = map_opt(digit1, |s: &str| s.parse::<u64>().ok())(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = tag("-")(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, valrange) = map_opt(digit1, |s: &str| s.parse::<u64>().ok())(i)?;
- Ok((
- i,
- DetectU64Data {
- value,
- valrange,
- mode: DetectUintMode::DetectUintModeRange,
- },
- ))
-}
-
-fn detect_parse_u64_start_lesser(i: &str) -> IResult<&str, DetectU64Data> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = tag("<")(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, value) = map_opt(digit1, |s: &str| s.parse::<u64>().ok())(i)?;
- Ok((
- i,
- DetectU64Data {
- value,
- valrange: 0,
- mode: DetectUintMode::DetectUintModeLt,
- },
- ))
-}
-
-fn detect_parse_u64_start_greater(i: &str) -> IResult<&str, DetectU64Data> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = tag(">")(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, value) = map_opt(digit1, |s: &str| s.parse::<u64>().ok())(i)?;
- Ok((
- i,
- DetectU64Data {
- value,
- valrange: 0,
- mode: DetectUintMode::DetectUintModeGt,
- },
- ))
-}
-
-pub fn detect_parse_u64(i: &str) -> IResult<&str, DetectU64Data> {
- let (i, u64) = alt((
- detect_parse_u64_start_lesser,
- detect_parse_u64_start_greater,
- complete(detect_parse_u64_start_interval),
- detect_parse_u64_start_equal,
- ))(i)?;
- Ok((i, u64))
-}
-
#[derive(Clone, Copy, Debug)]
pub struct HTTP2FrameSettings {
pub id: HTTP2SettingsId,
mod tests {
use super::*;
+ use crate::detect::DetectUintMode;
#[test]
fn test_http2_parse_header() {
assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
match ctx.value {
Some(ctxval) => {
- assert_eq!(ctxval.value, 42);
+ assert_eq!(ctxval.arg1, 42);
}
None => {
panic!("No value");
assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
match ctx.value {
Some(ctxval) => {
- assert_eq!(ctxval.value, 42);
+ assert_eq!(ctxval.arg1, 42);
assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeRange);
- assert_eq!(ctxval.valrange, 68);
+ assert_eq!(ctxval.arg2, 68);
}
None => {
panic!("No value");
assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
match ctx.value {
Some(ctxval) => {
- assert_eq!(ctxval.value, 54);
+ assert_eq!(ctxval.arg1, 54);
assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeLt);
}
None => {
assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
match ctx.value {
Some(ctxval) => {
- assert_eq!(ctxval.value, 76);
+ assert_eq!(ctxval.arg1, 76);
assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeGt);
}
None => {
pub mod filecontainer;
pub mod filetracker;
pub mod kerberos;
+pub mod detect;
#[cfg(feature = "lua")]
pub mod lua;
use crate::smb::smb::*;
use crate::dcerpc::detect::{DCEIfaceData, DCEOpnumData, DETECT_DCE_OPNUM_RANGE_UNINITIALIZED};
use crate::dcerpc::dcerpc::DCERPC_TYPE_REQUEST;
+use crate::detect::detect_match_uint;
#[no_mangle]
pub unsafe extern "C" fn rs_smb_tx_get_share(tx: &mut SMBTransaction,
return 0;
}
-/* based on:
- * typedef enum DetectDceIfaceOperators_ {
- * DETECT_DCE_IFACE_OP_NONE = 0,
- * DETECT_DCE_IFACE_OP_LT,
- * DETECT_DCE_IFACE_OP_GT,
- * DETECT_DCE_IFACE_OP_EQ,
- * DETECT_DCE_IFACE_OP_NE,
- * } DetectDceIfaceOperators;
- */
-#[inline]
-fn match_version(op: u8, them: u16, us: u16) -> bool {
- let result = match op {
- 0 => { // NONE
- true
- },
- 1 => { // LT
- them < us
- },
- 2 => { // GT
- them > us
- },
- 3 => { // EQ
- them == us
- },
- 4 => { // NE
- them != us
- },
- _ => {
- panic!("called with invalid op {}", op);
- },
- };
- result
-}
-
/* mimic logic that is/was in the C code:
* - match on REQUEST (so not on BIND/BINDACK (probably for mixing with
* dce_opnum and dce_stub_data)
-> u8
{
let if_uuid = dce_data.if_uuid.as_slice();
- let if_op = dce_data.op;
- let if_version = dce_data.version;
let is_dcerpc_request = match tx.type_data {
Some(SMBTransactionTypeData::DCERPC(ref x)) => {
x.req_cmd == DCERPC_TYPE_REQUEST
SCLogDebug!("stored UUID {:?} acked {} ack_result {}", i, i.acked, i.ack_result);
if i.acked && i.ack_result == 0 && i.uuid == if_uuid {
- if match_version(if_op as u8, if_version as u16, i.ver) {
+ if let Some(x) = &dce_data.du16 {
+ if detect_match_uint(&x, i.ver) {
+ return 1;
+ }
+ } else {
return 1;
}
}
#ifndef __DETECT_ENGINE_PREFILTER_COMMON_H__
#define __DETECT_ENGINE_PREFILTER_COMMON_H__
+#include "rust.h"
+
typedef union {
uint8_t u8[16];
uint16_t u16[8];
SigsArray *array[256];
} PrefilterPacketU8HashCtx;
-#define PREFILTER_U8HASH_MODE_EQ 0
-#define PREFILTER_U8HASH_MODE_LT 1
-#define PREFILTER_U8HASH_MODE_GT 2
-#define PREFILTER_U8HASH_MODE_RA 3
+#define PREFILTER_U8HASH_MODE_EQ DetectUintModeEqual
+#define PREFILTER_U8HASH_MODE_LT DetectUintModeLt
+#define PREFILTER_U8HASH_MODE_GT DetectUintModeGt
+#define PREFILTER_U8HASH_MODE_RA DetectUintModeRange
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx,
SigGroupHead *sgh, int sm_type,
#include "detect-parse.h"
#include "detect-engine-uint.h"
-/**
- * \brief Regex for parsing our options
- */
-#define PARSE_REGEX "^\\s*([0-9]*)?\\s*([<>=-]+)?\\s*([0-9]+)?\\s*$"
-
-static DetectParseRegex uint_pcre;
-
-int DetectU32Match(const uint32_t parg, const DetectU32Data *du32)
+int DetectU32Match(const uint32_t parg, const DetectUintData_u32 *du32)
{
- switch (du32->mode) {
- case DETECT_UINT_EQ:
- if (parg == du32->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_LT:
- if (parg < du32->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_LTE:
- if (parg <= du32->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_GT:
- if (parg > du32->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_GTE:
- if (parg >= du32->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_RA:
- if (parg > du32->arg1 && parg < du32->arg2) {
- return 1;
- }
- return 0;
- default:
- BUG_ON(1); // unknown mode
- }
- return 0;
-}
-
-static int DetectU32Validate(DetectU32Data *du32)
-{
- switch (du32->mode) {
- case DETECT_UINT_LT:
- if (du32->arg1 == 0) {
- return 1;
- }
- break;
- case DETECT_UINT_GT:
- if (du32->arg1 == UINT32_MAX) {
- return 1;
- }
- break;
- case DETECT_UINT_RA:
- if (du32->arg1 >= du32->arg2) {
- return 1;
- }
- // we need at least one value that can match parg > du32->arg1 && parg < du32->arg2
- if (du32->arg1 + 1 >= du32->arg2) {
- return 1;
- }
- break;
- default:
- break;
- }
- return 0;
+ return rs_detect_u32_match(parg, du32);
}
/**
* \retval NULL on failure
*/
-DetectU32Data *DetectU32Parse (const char *u32str)
+DetectUintData_u32 *DetectU32Parse(const char *u32str)
{
- /* We initialize these to please static checkers, these values will
- either be updated or not used later on */
- DetectU32Data u32da = {0, 0, 0};
- DetectU32Data *u32d = NULL;
- char arg1[16] = "";
- char arg2[16] = "";
- char arg3[16] = "";
-
- int ret = 0, res = 0;
- size_t pcre2len;
-
- ret = DetectParsePcreExec(&uint_pcre, u32str, 0, 0);
- if (ret < 2 || ret > 4) {
- SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
- return NULL;
- }
-
- pcre2len = sizeof(arg1);
- res = pcre2_substring_copy_bynumber(uint_pcre.match, 1, (PCRE2_UCHAR8 *)arg1, &pcre2len);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre2_substring_copy_bynumber failed");
- return NULL;
- }
- SCLogDebug("Arg1 \"%s\"", arg1);
-
- if (ret >= 3) {
- pcre2len = sizeof(arg2);
- res = pcre2_substring_copy_bynumber(uint_pcre.match, 2, (PCRE2_UCHAR8 *)arg2, &pcre2len);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre2_substring_copy_bynumber failed");
- return NULL;
- }
- SCLogDebug("Arg2 \"%s\"", arg2);
-
- if (ret >= 4) {
- pcre2len = sizeof(arg3);
- res = pcre2_substring_copy_bynumber(
- uint_pcre.match, 3, (PCRE2_UCHAR8 *)arg3, &pcre2len);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre2_substring_copy_bynumber failed");
- return NULL;
- }
- SCLogDebug("Arg3 \"%s\"", arg3);
- }
- }
-
- if (strlen(arg2) > 0) {
- /*set the values*/
- switch(arg2[0]) {
- case '<':
- case '>':
- if (strlen(arg2) == 1) {
- if (strlen(arg3) == 0)
- return NULL;
-
- if (ByteExtractStringUint32(&u32da.arg1, 10, strlen(arg3), arg3) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
- return NULL;
- }
-
- SCLogDebug("u32 is %" PRIu32 "", u32da.arg1);
- if (strlen(arg1) > 0)
- return NULL;
-
- if (arg2[0] == '<') {
- u32da.mode = DETECT_UINT_LT;
- } else { // arg2[0] == '>'
- u32da.mode = DETECT_UINT_GT;
- }
- break;
- } else if (strlen(arg2) == 2) {
- if (arg2[0] == '<' && arg2[1] == '=') {
- u32da.mode = DETECT_UINT_LTE;
- break;
- } else if (arg2[0] == '>' || arg2[1] == '=') {
- u32da.mode = DETECT_UINT_GTE;
- break;
- } else if (arg2[0] != '<' || arg2[1] != '>') {
- return NULL;
- }
- } else {
- return NULL;
- }
- // fall through
- case '-':
- if (strlen(arg1)== 0)
- return NULL;
- if (strlen(arg3)== 0)
- return NULL;
-
- u32da.mode = DETECT_UINT_RA;
- if (ByteExtractStringUint32(&u32da.arg1, 10, strlen(arg1), arg1) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
- return NULL;
- }
- if (ByteExtractStringUint32(&u32da.arg2, 10, strlen(arg3), arg3) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
- return NULL;
- }
-
- SCLogDebug("u32 is %"PRIu32" to %"PRIu32"", u32da.arg1, u32da.arg2);
- if (u32da.arg1 >= u32da.arg2) {
- SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid u32 range. ");
- return NULL;
- }
- break;
- default:
- u32da.mode = DETECT_UINT_EQ;
-
- if (strlen(arg2) > 0 ||
- strlen(arg3) > 0 ||
- strlen(arg1) == 0)
- return NULL;
-
- if (ByteExtractStringUint32(&u32da.arg1, 10, strlen(arg1), arg1) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
- return NULL;
- }
- }
- } else {
- u32da.mode = DETECT_UINT_EQ;
-
- if (strlen(arg3) > 0 ||
- strlen(arg1) == 0)
- return NULL;
-
- if (ByteExtractStringUint32(&u32da.arg1, 10, strlen(arg1), arg1) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
- return NULL;
- }
- }
- if (DetectU32Validate(&u32da)) {
- SCLogError(SC_ERR_INVALID_VALUE, "Impossible value for uint32 condition : %s", u32str);
- return NULL;
- }
- u32d = SCCalloc(1, sizeof (DetectU32Data));
- if (unlikely(u32d == NULL))
- return NULL;
- u32d->arg1 = u32da.arg1;
- u32d->arg2 = u32da.arg2;
- u32d->mode = u32da.mode;
-
- return u32d;
+ return rs_detect_u32_parse(u32str);
}
void
PrefilterPacketU32Set(PrefilterPacketHeaderValue *v, void *smctx)
{
- const DetectU32Data *a = smctx;
+ const DetectUintData_u32 *a = smctx;
v->u8[0] = a->mode;
v->u32[1] = a->arg1;
v->u32[2] = a->arg2;
bool
PrefilterPacketU32Compare(PrefilterPacketHeaderValue v, void *smctx)
{
- const DetectU32Data *a = smctx;
+ const DetectUintData_u32 *a = smctx;
if (v.u8[0] == a->mode &&
v.u32[1] == a->arg1 &&
v.u32[2] == a->arg2)
return false;
}
-static bool g_detect_uint_registered = false;
-
-void DetectUintRegister(void)
-{
- if (g_detect_uint_registered == false) {
- // register only once
- DetectSetupParseRegexes(PARSE_REGEX, &uint_pcre);
- g_detect_uint_registered = true;
- }
-}
-
//same as u32 but with u8
-int DetectU8Match(const uint8_t parg, const DetectU8Data *du8)
-{
- switch (du8->mode) {
- case DETECT_UINT_EQ:
- if (parg == du8->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_LT:
- if (parg < du8->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_LTE:
- if (parg <= du8->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_GT:
- if (parg > du8->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_GTE:
- if (parg >= du8->arg1) {
- return 1;
- }
- return 0;
- case DETECT_UINT_RA:
- if (parg > du8->arg1 && parg < du8->arg2) {
- return 1;
- }
- return 0;
- default:
- BUG_ON(1); // unknown mode
- }
- return 0;
-}
-
-static int DetectU8Validate(DetectU8Data *du8)
+int DetectU8Match(const uint8_t parg, const DetectUintData_u8 *du8)
{
- switch (du8->mode) {
- case DETECT_UINT_LT:
- if (du8->arg1 == 0) {
- return 1;
- }
- break;
- case DETECT_UINT_GT:
- if (du8->arg1 == UINT8_MAX) {
- return 1;
- }
- break;
- case DETECT_UINT_RA:
- if (du8->arg1 >= du8->arg2) {
- return 1;
- }
- // we need at least one value that can match parg > du8->arg1 && parg < du8->arg2
- if (du8->arg1 + 1 >= du8->arg2) {
- return 1;
- }
- break;
- default:
- break;
- }
- return 0;
+ return rs_detect_u8_match(parg, du8);
}
/**
* \retval NULL on failure
*/
-DetectU8Data *DetectU8Parse (const char *u8str)
+DetectUintData_u8 *DetectU8Parse(const char *u8str)
{
- /* We initialize these to please static checkers, these values will
- either be updated or not used later on */
- DetectU8Data u8da = {0, 0, 0};
- DetectU8Data *u8d = NULL;
- char arg1[16] = "";
- char arg2[16] = "";
- char arg3[16] = "";
-
- int ret = 0, res = 0;
- size_t pcre2len;
-
- ret = DetectParsePcreExec(&uint_pcre, u8str, 0, 0);
- if (ret < 2 || ret > 4) {
- SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
- return NULL;
- }
-
- pcre2len = sizeof(arg1);
- res = pcre2_substring_copy_bynumber(uint_pcre.match, 1, (PCRE2_UCHAR8 *)arg1, &pcre2len);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre2_substring_copy_bynumber failed");
- return NULL;
- }
- SCLogDebug("Arg1 \"%s\"", arg1);
-
- if (ret >= 3) {
- pcre2len = sizeof(arg2);
- res = pcre2_substring_copy_bynumber(uint_pcre.match, 2, (PCRE2_UCHAR8 *)arg2, &pcre2len);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre2_substring_copy_bynumber failed");
- return NULL;
- }
- SCLogDebug("Arg2 \"%s\"", arg2);
-
- if (ret >= 4) {
- pcre2len = sizeof(arg3);
- res = pcre2_substring_copy_bynumber(
- uint_pcre.match, 3, (PCRE2_UCHAR8 *)arg3, &pcre2len);
- if (res < 0) {
- SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre2_substring_copy_bynumber failed");
- return NULL;
- }
- SCLogDebug("Arg3 \"%s\"", arg3);
- }
- }
-
- if (strlen(arg2) > 0) {
- /*set the values*/
- switch(arg2[0]) {
- case '<':
- case '>':
- if (strlen(arg2) == 1) {
- if (StringParseUint8(&u8da.arg1, 10, strlen(arg3), arg3) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
- return NULL;
- }
-
- SCLogDebug("u8 is %" PRIu8 "", u8da.arg1);
- if (strlen(arg1) > 0)
- return NULL;
+ return rs_detect_u8_parse(u8str);
+}
- if (arg2[0] == '<') {
- u8da.mode = DETECT_UINT_LT;
- } else { // arg2[0] == '>'
- u8da.mode = DETECT_UINT_GT;
- }
- break;
- } else if (strlen(arg2) == 2) {
- if (arg2[0] == '<' && arg2[1] == '=') {
- u8da.mode = DETECT_UINT_LTE;
- break;
- } else if (arg2[0] == '>' || arg2[1] == '=') {
- u8da.mode = DETECT_UINT_GTE;
- break;
- } else if (arg2[0] != '<' || arg2[1] != '>') {
- return NULL;
- }
- } else {
- return NULL;
- }
- // fall through
- case '-':
- u8da.mode = DETECT_UINT_RA;
- if (StringParseUint8(&u8da.arg1, 10, strlen(arg1), arg1) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
- return NULL;
- }
- if (StringParseUint8(&u8da.arg2, 10, strlen(arg3), arg3) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
- return NULL;
- }
+void PrefilterPacketU8Set(PrefilterPacketHeaderValue *v, void *smctx)
+{
+ const DetectUintData_u8 *a = smctx;
+ v->u8[0] = a->mode;
+ v->u8[1] = a->arg1;
+ v->u8[2] = a->arg2;
+}
- SCLogDebug("u8 is %"PRIu8" to %"PRIu8"", u8da.arg1, u8da.arg2);
- if (u8da.arg1 >= u8da.arg2) {
- SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid u8 range. ");
- return NULL;
- }
- break;
- default:
- u8da.mode = DETECT_UINT_EQ;
+bool PrefilterPacketU8Compare(PrefilterPacketHeaderValue v, void *smctx)
+{
+ const DetectUintData_u8 *a = smctx;
+ if (v.u8[0] == a->mode && v.u8[1] == a->arg1 && v.u8[2] == a->arg2)
+ return true;
+ return false;
+}
- if (strlen(arg2) > 0 ||
- strlen(arg3) > 0)
- return NULL;
+// same as u32 but with u16
+int DetectU16Match(const uint16_t parg, const DetectUintData_u16 *du16)
+{
+ return rs_detect_u16_match(parg, du16);
+}
- if (StringParseUint8(&u8da.arg1, 10, strlen(arg1), arg1) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
- return NULL;
- }
- }
- } else {
- u8da.mode = DETECT_UINT_EQ;
+/**
+ * \brief This function is used to parse u16 options passed via some u16 keyword
+ *
+ * \param u16str Pointer to the user provided u16 options
+ *
+ * \retval DetectU16Data pointer to DetectU16Data on success
+ * \retval NULL on failure
+ */
- if (strlen(arg3) > 0)
- return NULL;
+DetectUintData_u16 *DetectU16Parse(const char *u16str)
+{
+ return rs_detect_u16_parse(u16str);
+}
- if (StringParseUint8(&u8da.arg1, 10, strlen(arg1), arg1) < 0) {
- SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
- return NULL;
- }
- }
- if (DetectU8Validate(&u8da)) {
- SCLogError(SC_ERR_INVALID_VALUE, "Impossible value for uint8 condition : %s", u8str);
- return NULL;
- }
- u8d = SCCalloc(1, sizeof (DetectU8Data));
- if (unlikely(u8d == NULL))
- return NULL;
- u8d->arg1 = u8da.arg1;
- u8d->arg2 = u8da.arg2;
- u8d->mode = u8da.mode;
+void PrefilterPacketU16Set(PrefilterPacketHeaderValue *v, void *smctx)
+{
+ const DetectUintData_u16 *a = smctx;
+ v->u8[0] = a->mode;
+ v->u16[1] = a->arg1;
+ v->u16[2] = a->arg2;
+}
- return u8d;
+bool PrefilterPacketU16Compare(PrefilterPacketHeaderValue v, void *smctx)
+{
+ const DetectUintData_u16 *a = smctx;
+ if (v.u8[0] == a->mode && v.u16[1] == a->arg1 && v.u16[2] == a->arg2)
+ return true;
+ return false;
}
#ifndef __DETECT_ENGINE_UINT_H
#define __DETECT_ENGINE_UINT_H
+#include "rust.h"
#include "detect-engine-prefilter-common.h"
-typedef enum {
- DETECT_UINT_LT = PREFILTER_U8HASH_MODE_LT,
- DETECT_UINT_EQ = PREFILTER_U8HASH_MODE_EQ,
- DETECT_UINT_GT = PREFILTER_U8HASH_MODE_GT,
- DETECT_UINT_RA = PREFILTER_U8HASH_MODE_RA,
- DETECT_UINT_LTE,
- DETECT_UINT_GTE,
-} DetectUintMode;
-
-typedef struct DetectU32Data_ {
- uint32_t arg1; /**< first arg value in the signature*/
- uint32_t arg2; /**< second arg value in the signature, in case of range
- operator*/
- DetectUintMode mode; /**< operator used in the signature */
-} DetectU32Data;
-
-int DetectU32Match(const uint32_t parg, const DetectU32Data *du32);
-DetectU32Data *DetectU32Parse (const char *u32str);
+// These definitions are kept to minimize the diff
+// We can run a big sed commit next
+#define DETECT_UINT_GT DetectUintModeGt
+#define DETECT_UINT_GTE DetectUintModeGte
+#define DETECT_UINT_RA DetectUintModeRange
+#define DETECT_UINT_EQ DetectUintModeEqual
+#define DETECT_UINT_NE DetectUintModeNe
+#define DETECT_UINT_LT DetectUintModeLt
+#define DETECT_UINT_LTE DetectUintModeLte
+
+typedef DetectUintData_u32 DetectU32Data;
+typedef DetectUintData_u16 DetectU16Data;
+typedef DetectUintData_u8 DetectU8Data;
+
+int DetectU32Match(const uint32_t parg, const DetectUintData_u32 *du32);
+DetectUintData_u32 *DetectU32Parse(const char *u32str);
void PrefilterPacketU32Set(PrefilterPacketHeaderValue *v, void *smctx);
bool PrefilterPacketU32Compare(PrefilterPacketHeaderValue v, void *smctx);
-void DetectUintRegister(void);
+int DetectU8Match(const uint8_t parg, const DetectUintData_u8 *du8);
+DetectUintData_u8 *DetectU8Parse(const char *u8str);
+void PrefilterPacketU8Set(PrefilterPacketHeaderValue *v, void *smctx);
+bool PrefilterPacketU8Compare(PrefilterPacketHeaderValue v, void *smctx);
-typedef struct DetectU8Data_ {
- uint8_t arg1; /**< first arg value in the signature*/
- uint8_t arg2; /**< second arg value in the signature, in case of range
- operator*/
- DetectUintMode mode; /**< operator used in the signature */
-} DetectU8Data;
-
-int DetectU8Match(const uint8_t parg, const DetectU8Data *du8);
-DetectU8Data *DetectU8Parse (const char *u8str);
+int DetectU16Match(const uint16_t parg, const DetectUintData_u16 *du16);
+DetectUintData_u16 *DetectU16Parse(const char *u16str);
+void PrefilterPacketU16Set(PrefilterPacketHeaderValue *v, void *smctx);
+bool PrefilterPacketU16Compare(PrefilterPacketHeaderValue v, void *smctx);
#endif /* __DETECT_UTIL_UINT_H */
"http2", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectHTTP2, NULL);
g_http2_match_buffer_id = DetectBufferTypeRegister("http2");
- DetectUintRegister();
-
return;
}
SigMatch *sm = SigMatchAlloc();
if (sm == NULL) {
- SCFree(prio);
+ rs_detect_u8_free(prio);
return -1;
}
*/
void DetectHTTP2priorityFree(DetectEngineCtx *de_ctx, void *ptr)
{
- SCFree(ptr);
+ rs_detect_u8_free(ptr);
}
/**
SigMatch *sm = SigMatchAlloc();
if (sm == NULL) {
- SCFree(wu);
+ rs_detect_u32_free(wu);
return -1;
}
*/
void DetectHTTP2windowFree(DetectEngineCtx *de_ctx, void *ptr)
{
- SCFree(ptr);
+ rs_detect_u32_free(ptr);
}
/**
#endif
sigmatch_table[DETECT_ICMPV6MTU].SupportsPrefilter = PrefilterIcmpv6mtuIsPrefilterable;
sigmatch_table[DETECT_ICMPV6MTU].SetupPrefilter = PrefilterSetupIcmpv6mtu;
-
- DetectUintRegister();
return;
}
*/
void DetectICMPv6mtuFree(DetectEngineCtx *de_ctx, void *ptr)
{
- SCFree(ptr);
+ rs_detect_u32_free(ptr);
}
/* prefilter code */
error:
if (icd != NULL)
- SCFree(icd);
+ rs_detect_u8_free(icd);
if (sm != NULL) SCFree(sm);
return -1;
}
*/
void DetectICodeFree(DetectEngineCtx *de_ctx, void *ptr)
{
- SCFree(ptr);
+ rs_detect_u8_free(ptr);
}
/* prefilter code */
}
}
-static void
-PrefilterPacketICodeSet(PrefilterPacketHeaderValue *v, void *smctx)
-{
- const DetectU8Data *a = smctx;
- v->u8[0] = a->mode;
- v->u8[1] = a->arg1;
- v->u8[2] = a->arg2;
-}
-
-static bool
-PrefilterPacketICodeCompare(PrefilterPacketHeaderValue v, void *smctx)
-{
- const DetectU8Data *a = smctx;
- if (v.u8[0] == a->mode && v.u8[1] == a->arg1 && v.u8[2] == a->arg2)
- return true;
- return false;
-}
-
static int PrefilterSetupICode(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
{
- return PrefilterSetupPacketHeaderU8Hash(de_ctx, sgh, DETECT_ICODE,
- PrefilterPacketICodeSet,
- PrefilterPacketICodeCompare,
- PrefilterPacketICodeMatch);
+ return PrefilterSetupPacketHeaderU8Hash(de_ctx, sgh, DETECT_ICODE, PrefilterPacketU8Set,
+ PrefilterPacketU8Compare, PrefilterPacketICodeMatch);
}
static bool PrefilterICodeIsPrefilterable(const Signature *s)
DetectEngineInspectIkeExchTypeGeneric, NULL);
g_ike_exch_type_buffer_id = DetectBufferTypeGetByName("ike.exchtype");
-
- DetectUintRegister();
}
static int DetectEngineInspectIkeExchTypeGeneric(DetectEngineCtx *de_ctx,
*/
static void DetectIkeExchTypeFree(DetectEngineCtx *de_ctx, void *ptr)
{
- SCFree(ptr);
+ rs_detect_u8_free(ptr);
}
g_ike_key_exch_payload_length_buffer_id =
DetectBufferTypeGetByName("ike.key_exchange_payload_length");
-
- DetectUintRegister();
}
static int DetectEngineInspectIkeKeyExchangePayloadLengthGeneric(DetectEngineCtx *de_ctx,
*/
static void DetectIkeKeyExchangePayloadLengthFree(DetectEngineCtx *de_ctx, void *ptr)
{
- SCFree(ptr);
+ rs_detect_u32_free(ptr);
}
1, DetectEngineInspectIkeNoncePayloadLengthGeneric, NULL);
g_ike_nonce_payload_length_buffer_id = DetectBufferTypeGetByName("ike.nonce_payload_length");
-
- DetectUintRegister();
}
static int DetectEngineInspectIkeNoncePayloadLengthGeneric(DetectEngineCtx *de_ctx,
*/
static void DetectIkeNoncePayloadLengthFree(DetectEngineCtx *de_ctx, void *ptr)
{
- SCFree(ptr);
+ rs_detect_u32_free(ptr);
}
error:
if (de != NULL)
- SCFree(de);
+ rs_detect_u8_free(de);
if (sm != NULL)
SCFree(sm);
return -1;
*/
void DetectMQTTProtocolVersionFree(DetectEngineCtx *de_ctx, void *de_ptr)
{
- if (de_ptr != NULL)
- SCFree(de_ptr);
+ rs_detect_u8_free(de_ptr);
}
/*