Skip to content

Commit 61a1348

Browse files
committed
detect/mqtt: reason_code keyword is now a multi-integer
Ticket: 7929
1 parent c61f1cb commit 61a1348

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-7
lines changed

doc/userguide/rules/mqtt-keywords.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ Match on the numeric value of the reason code that is used in MQTT 5.0 for some
9898

9999
mqtt.reason_code uses an :ref:`unsigned 8-bits integer <rules-integer-keywords>`.
100100

101+
mqtt.reason_code is also a :ref:`multi-integer <multi-integers>`.
102+
101103
Examples::
102104

103105
# match on attempts to unsubscribe from a non-subscribed topic

rust/src/mqtt/detect.rs

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER};
2121
use crate::detect::uint::{
2222
detect_match_uint, detect_parse_array_uint_enum, detect_parse_uint_bitflags,
2323
detect_uint_match_at_index, DetectBitflagModifier, DetectUintArrayData, DetectUintData,
24-
SCDetectU8Free, SCDetectU8Parse,
24+
DetectUintIndex, SCDetectU8ArrayFree, SCDetectU8ArrayParse, SCDetectU8Free, SCDetectU8Parse,
2525
};
2626
use crate::detect::{
2727
helper_keyword_register_multi_buffer, helper_keyword_register_sticky_buffer,
@@ -440,7 +440,7 @@ unsafe extern "C" fn mqtt_reason_code_setup(
440440
if SCDetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
441441
return -1;
442442
}
443-
let ctx = SCDetectU8Parse(raw) as *mut c_void;
443+
let ctx = SCDetectU8ArrayParse(raw) as *mut c_void;
444444
if ctx.is_null() {
445445
return -1;
446446
}
@@ -464,19 +464,61 @@ unsafe extern "C" fn mqtt_reason_code_match(
464464
tx: *mut c_void, _sig: *const Signature, ctx: *const SigMatchCtx,
465465
) -> c_int {
466466
let tx = cast_pointer!(tx, MQTTTransaction);
467-
let ctx = cast_pointer!(ctx, DetectUintData<u8>);
467+
let ctx = cast_pointer!(ctx, DetectUintArrayData<u8>);
468+
if ctx.index != DetectUintIndex::Any {
469+
let mut vals = Vec::new();
470+
for msg in tx.msg.iter() {
471+
match msg.op {
472+
MQTTOperation::PUBACK(ref v)
473+
| MQTTOperation::PUBREL(ref v)
474+
| MQTTOperation::PUBREC(ref v)
475+
| MQTTOperation::PUBCOMP(ref v) => {
476+
if let Some(rcode) = v.reason_code {
477+
vals.push(rcode);
478+
}
479+
}
480+
MQTTOperation::AUTH(ref v) => {
481+
vals.push(v.reason_code);
482+
}
483+
MQTTOperation::CONNACK(ref v) => {
484+
vals.push(v.return_code);
485+
}
486+
MQTTOperation::DISCONNECT(ref v) => {
487+
if let Some(rcode) = v.reason_code {
488+
vals.push(rcode);
489+
}
490+
}
491+
MQTTOperation::UNSUBACK(ref unsuback) => {
492+
if let Some(ref reason_codes) = unsuback.reason_codes {
493+
for rc in reason_codes.iter() {
494+
vals.push(*rc);
495+
}
496+
}
497+
}
498+
MQTTOperation::SUBACK(ref suback) => {
499+
// in SUBACK these are stored as "QOS granted" historically
500+
for rc in suback.qoss.iter() {
501+
vals.push(*rc);
502+
}
503+
}
504+
_ => {}
505+
}
506+
}
507+
508+
return detect_uint_match_at_index::<u8, u8>(&vals, ctx, |v| Some(*v), tx.complete);
509+
}
468510
if let Some(v) = mqtt_tx_get_reason_code(tx) {
469-
if detect_match_uint(ctx, v) {
511+
if detect_match_uint(&ctx.du, v) {
470512
return 1;
471513
}
472514
}
473-
return mqtt_tx_suback_unsuback_has_reason_code(tx, ctx);
515+
return mqtt_tx_suback_unsuback_has_reason_code(tx, &ctx.du);
474516
}
475517

476518
unsafe extern "C" fn mqtt_reason_code_free(_de: *mut DetectEngineCtx, ctx: *mut c_void) {
477519
// Just unbox...
478-
let ctx = cast_pointer!(ctx, DetectUintData<u8>);
479-
SCDetectU8Free(ctx);
520+
let ctx = cast_pointer!(ctx, DetectUintArrayData<u8>);
521+
SCDetectU8ArrayFree(ctx);
480522
}
481523

482524
unsafe extern "C" fn mqtt_parse_qos(ustr: *const std::os::raw::c_char) -> *mut u8 {

0 commit comments

Comments
 (0)