From 9fc407fd7591785a891b42adad3c4c12c2c9f655 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Tue, 9 Sep 2025 15:16:28 +0200 Subject: [PATCH] mqtt/detect: mqtt.type can now use index Ticket: 7480 --- doc/userguide/rules/mqtt-keywords.rst | 2 + rust/src/mqtt/detect.rs | 55 +++++++++++++-------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/doc/userguide/rules/mqtt-keywords.rst b/doc/userguide/rules/mqtt-keywords.rst index 211ccf75d9..d82471f70e 100644 --- a/doc/userguide/rules/mqtt-keywords.rst +++ b/doc/userguide/rules/mqtt-keywords.rst @@ -48,6 +48,8 @@ where ``UNASSIGNED`` refers to message type code 0. mqtt.type uses an :ref:`unsigned 8-bits integer `. +mqtt.type is also a :ref:`multi-integer `. + Examples:: mqtt.type:CONNECT; diff --git a/rust/src/mqtt/detect.rs b/rust/src/mqtt/detect.rs index 97d75cc4c0..36e00c3c21 100644 --- a/rust/src/mqtt/detect.rs +++ b/rust/src/mqtt/detect.rs @@ -19,8 +19,8 @@ use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER}; use crate::detect::uint::{ - detect_match_uint, detect_parse_uint, detect_parse_uint_enum, DetectUintData, DetectUintMode, - SCDetectU8Free, SCDetectU8Parse, + detect_match_uint, detect_parse_array_uint_enum, detect_parse_uint, detect_uint_match_at_index, + DetectUintArrayData, DetectUintData, DetectUintMode, SCDetectU8Free, SCDetectU8Parse, }; use crate::detect::{helper_keyword_register_sticky_buffer, SigTableElmtStickyBuffer}; use suricata_sys::sys::{ @@ -38,19 +38,16 @@ use nom7::IResult; use super::mqtt::{MQTTState, MQTTTransaction, ALPROTO_MQTT}; use crate::conf::conf_get; -use crate::mqtt::mqtt_message::{MQTTOperation, MQTTTypeCode}; +use crate::mqtt::mqtt_message::{MQTTMessage, MQTTOperation, MQTTTypeCode}; use std::ffi::CStr; use std::os::raw::{c_int, c_void}; use std::ptr; use std::str::FromStr; -fn mqtt_tx_has_type(tx: &MQTTTransaction, mtype: &DetectUintData) -> c_int { - for msg in tx.msg.iter() { - if detect_match_uint(mtype, msg.header.message_type as u8) { - return 1; - } - } - return 0; +fn mqtt_tx_has_type(tx: &MQTTTransaction, ctx: &DetectUintArrayData) -> c_int { + return detect_uint_match_at_index::(&tx.msg, ctx, |msg| { + Some(msg.header.message_type as u8) + }); } unsafe extern "C" fn mqtt_conn_clientid_get_data( @@ -382,10 +379,12 @@ unsafe extern "C" fn sub_topic_setup( return 0; } -unsafe extern "C" fn mqtt_parse_type(ustr: *const std::os::raw::c_char) -> *mut DetectUintData { +unsafe extern "C" fn mqtt_parse_type( + ustr: *const std::os::raw::c_char, +) -> *mut DetectUintArrayData { let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe if let Ok(s) = ft_name.to_str() { - if let Some(ctx) = detect_parse_uint_enum::(s) { + if let Some(ctx) = detect_parse_array_uint_enum::(s) { let boxed = Box::new(ctx); return Box::into_raw(boxed) as *mut _; } @@ -423,14 +422,14 @@ unsafe extern "C" fn mqtt_type_match( tx: *mut c_void, _sig: *const Signature, ctx: *const SigMatchCtx, ) -> c_int { let tx = cast_pointer!(tx, MQTTTransaction); - let ctx = cast_pointer!(ctx, DetectUintData); + let ctx = cast_pointer!(ctx, DetectUintArrayData); return mqtt_tx_has_type(tx, ctx); } unsafe extern "C" fn mqtt_type_free(_de: *mut DetectEngineCtx, ctx: *mut c_void) { // Just unbox... - let ctx = cast_pointer!(ctx, DetectUintData); - SCDetectU8Free(ctx); + let ctx = cast_pointer!(ctx, DetectUintArrayData); + std::mem::drop(Box::from_raw(ctx)); } unsafe extern "C" fn mqtt_reason_code_setup( @@ -1324,19 +1323,19 @@ mod test { #[test] fn mqtt_type_test_parse() { - let ctx = detect_parse_uint_enum::("CONNECT").unwrap(); - assert_eq!(ctx.arg1, 1); - assert_eq!(ctx.mode, DetectUintMode::DetectUintModeEqual); - let ctx = detect_parse_uint_enum::("PINGRESP").unwrap(); - assert_eq!(ctx.arg1, 13); - assert_eq!(ctx.mode, DetectUintMode::DetectUintModeEqual); - let ctx = detect_parse_uint_enum::("auth").unwrap(); - assert_eq!(ctx.arg1, 15); - assert_eq!(ctx.mode, DetectUintMode::DetectUintModeEqual); - assert!(detect_parse_uint_enum::("invalidopt").is_none()); - let ctx = detect_parse_uint_enum::("unassigned").unwrap(); - assert_eq!(ctx.arg1, 0); - assert_eq!(ctx.mode, DetectUintMode::DetectUintModeEqual); + let ctx = detect_parse_array_uint_enum::("CONNECT").unwrap(); + assert_eq!(ctx.du.arg1, 1); + assert_eq!(ctx.du.mode, DetectUintMode::DetectUintModeEqual); + let ctx = detect_parse_array_uint_enum::("PINGRESP").unwrap(); + assert_eq!(ctx.du.arg1, 13); + assert_eq!(ctx.du.mode, DetectUintMode::DetectUintModeEqual); + let ctx = detect_parse_array_uint_enum::("auth").unwrap(); + assert_eq!(ctx.du.arg1, 15); + assert_eq!(ctx.du.mode, DetectUintMode::DetectUintModeEqual); + assert!(detect_parse_array_uint_enum::("invalidopt").is_none()); + let ctx = detect_parse_array_uint_enum::("unassigned").unwrap(); + assert_eq!(ctx.du.arg1, 0); + assert_eq!(ctx.du.mode, DetectUintMode::DetectUintModeEqual); } #[test]