From 3613946dd5a9fcc1b932941f62c999eca1495a5a Mon Sep 17 00:00:00 2001 From: Alice Akaki Date: Tue, 21 Jan 2025 00:23:54 -0400 Subject: [PATCH] detect/integers: add support for negated strings when enum is used function detect_parse_uint_enum can parse strings like !bind_request Ticket: #7513 --- doc/userguide/rules/integer-keywords.rst | 5 ++++- rust/src/detect/uint.rs | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/doc/userguide/rules/integer-keywords.rst b/doc/userguide/rules/integer-keywords.rst index 5bf5b93a3a18..50b3a9a943ff 100644 --- a/doc/userguide/rules/integer-keywords.rst +++ b/doc/userguide/rules/integer-keywords.rst @@ -55,7 +55,7 @@ Enumerations Some integers on the wire represent an enumeration, that is, some values have a string/meaning associated to it. -Rules can be written using one of these strings to check for equality. +Rules can be written using one of these strings to check for equality or inequality. This is meant to make rules more human-readable and equivalent for matching. Examples:: @@ -63,6 +63,9 @@ Examples:: websocket.opcode:text; websocket.opcode:1; # behaves the same + websocket.opcode:!ping; + websocket.opcode:!9; # behaves the same + Bitmasks -------- diff --git a/rust/src/detect/uint.rs b/rust/src/detect/uint.rs index 13b28fd7743f..e844b965cf20 100644 --- a/rust/src/detect/uint.rs +++ b/rust/src/detect/uint.rs @@ -19,7 +19,7 @@ use nom7::branch::alt; use nom7::bytes::complete::{is_a, tag, tag_no_case, take_while}; use nom7::character::complete::{char, digit1, hex_digit1}; use nom7::combinator::{all_consuming, map_opt, opt, value, verify}; -use nom7::error::{make_error, ErrorKind}; +use nom7::error::{make_error, Error, ErrorKind}; use nom7::Err; use nom7::IResult; @@ -58,15 +58,25 @@ pub struct DetectUintData { /// And if this fails, will resort to using the enumeration strings. /// /// Returns Some DetectUintData on success, None on failure -pub fn detect_parse_uint_enum>(s: &str) -> Option> { +pub fn detect_parse_uint_enum>( + s: &str, +) -> Option> { if let Ok((_, ctx)) = detect_parse_uint::(s) { return Some(ctx); } + + // we need to precise the Error type, we get error[E0283]: type annotations needed + let (s, neg) = opt(char::<_, Error<_>>('!'))(s).ok()?; + let mode = if neg.is_some() { + DetectUintMode::DetectUintModeNe + } else { + DetectUintMode::DetectUintModeEqual + }; if let Some(enum_val) = T2::from_str(s) { let ctx = DetectUintData:: { arg1: enum_val.into_u(), arg2: T1::min_value(), - mode: DetectUintMode::DetectUintModeEqual, + mode, }; return Some(ctx); }