]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/integers: add support for negated strings when enum is used
authorAlice Akaki <akakialice@gmail.com>
Tue, 21 Jan 2025 04:23:54 +0000 (00:23 -0400)
committerVictor Julien <victor@inliniac.net>
Tue, 11 Feb 2025 18:27:22 +0000 (19:27 +0100)
function detect_parse_uint_enum can parse strings like !bind_request

Ticket: #7513

doc/userguide/rules/integer-keywords.rst
rust/src/detect/uint.rs

index 5bf5b93a3a18565cc7ae5e0217a9fb391342e0ce..50b3a9a943ff30317c8708638a96f7bb06af96f0 100644 (file)
@@ -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
 --------
 
index 13b28fd7743f15a62496fb153466c689639c0d63..e844b965cf2098026f46a7fafdcb72c9590b6156 100644 (file)
@@ -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<T> {
 /// 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<T1: DetectIntType, T2: EnumString<T1>>(s: &str) -> Option<DetectUintData<T1>> {
+pub fn detect_parse_uint_enum<T1: DetectIntType, T2: EnumString<T1>>(
+    s: &str,
+) -> Option<DetectUintData<T1>> {
     if let Ok((_, ctx)) = detect_parse_uint::<T1>(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::<T1> {
             arg1: enum_val.into_u(),
             arg2: T1::min_value(),
-            mode: DetectUintMode::DetectUintModeEqual,
+            mode,
         };
         return Some(ctx);
     }