where ``UNASSIGNED`` refers to message type code 0.
+mqtt.type uses an :ref:`unsigned 8-bits integer <rules-integer-keywords>`.
+
Examples::
mqtt.type:CONNECT;
mqtt.type:PUBLISH;
+ mqtt.type:2;
mqtt.flags
Match on a combination of MQTT header flags, separated by commas (``,``). Flags may be prefixed by ``!`` to indicate negation, i.e. a flag prefixed by ``!`` must `not` be set to match.
+mqtt.flags uses an :ref:`unsigned 8-bits integer <rules-integer-keywords>`
+
Valid flags are:
* ``dup`` (duplicate message)
Match on the numeric value of the reason code that is used in MQTT 5.0 for some message types. Please refer to the specification for the meaning of these values, which are often specific to the message type in question.
+mqtt.reason_code uses an :ref:`unsigned 8-bits integer <rules-integer-keywords>`.
+
Examples::
# match on attempts to unsubscribe from a non-subscribed topic
Match on a combination of MQTT CONNECT flags, separated by commas (``,``). Flags may be prefixed by ``!`` to indicate negation, i.e. a flag prefixed by ``!`` must `not` be set to match.
+mqtt.connect.flags uses an :ref:`unsigned 8-bits integer <rules-integer-keywords>`
+
Valid flags are:
* ``username`` (message contains a username)
pub fn SigMatchAppendSMToList(
de: *mut c_void, s: *mut c_void, kwid: c_int, ctx: *const c_void, bufid: c_int,
) -> *mut c_void;
+ // in detect-engine-helper.h
+ pub fn DetectHelperGetMultiData(
+ de: *mut c_void,
+ transforms: *const c_void,
+ flow: *const c_void,
+ flow_flags: u8,
+ tx: *const c_void,
+ list_id: c_int,
+ local_id: u32,
+ get_buf: unsafe extern "C" fn(*const c_void, u8, u32, *mut *const u8, *mut u32) -> bool,
+ ) -> *mut c_void;
+ pub fn DetectHelperMultiBufferMpmRegister(
+ name: *const libc::c_char, desc: *const libc::c_char, alproto: AppProto, toclient: bool,
+ toserver: bool,
+ get_multi_data: unsafe extern "C" fn(
+ *mut c_void,
+ *const c_void,
+ *const c_void,
+ u8,
+ *const c_void,
+ i32,
+ u32,
+ ) -> *mut c_void,
+ ) -> c_int;
}
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
let (_, val) = detect_parse_uint::<u32>("> 3MB").unwrap();
assert_eq!(val.arg1, 3 * 1024 * 1024);
}
+
+ #[test]
+ fn test_parse_uint_like_mqtt_protocol_version() {
+ let (_, val) = detect_parse_uint::<u8>("3").unwrap();
+ assert_eq!(val.mode, DetectUintMode::DetectUintModeEqual);
+ assert_eq!(val.arg1, 3);
+ let (_, val) = detect_parse_uint::<u8>("5").unwrap();
+ assert_eq!(val.mode, DetectUintMode::DetectUintModeEqual);
+ assert_eq!(val.arg1, 5);
+ let (_, val) = detect_parse_uint::<u8>(">3").unwrap();
+ assert_eq!(val.mode, DetectUintMode::DetectUintModeGt);
+ assert_eq!(val.arg1, 3);
+ let (_, val) = detect_parse_uint::<u8>("<44").unwrap();
+ assert_eq!(val.mode, DetectUintMode::DetectUintModeLt);
+ assert_eq!(val.arg1, 44);
+ assert!(detect_parse_uint::<u8>("").is_err());
+ assert!(detect_parse_uint::<u8>("<444").is_err());
+ }
}
// written by Sascha Steinbiss <sascha@steinbiss.name>
-use crate::mqtt::mqtt::{MQTTState, MQTTTransaction};
+use crate::detect::uint::{
+ detect_match_uint, detect_parse_uint, detect_parse_uint_enum, rs_detect_u8_free,
+ rs_detect_u8_parse, DetectUintData, DetectUintMode,
+};
+use crate::detect::{
+ DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperBufferRegister,
+ DetectHelperGetData, DetectHelperGetMultiData, DetectHelperKeywordRegister,
+ DetectHelperMultiBufferMpmRegister, DetectSignatureSetAppProto, SCSigTableElmt,
+ SigMatchAppendSMToList, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT,
+};
+
+use nom7::branch::alt;
+use nom7::bytes::complete::{is_a, tag};
+use nom7::combinator::{opt, value};
+use nom7::multi::many1;
+use nom7::IResult;
+
+use super::mqtt::{MQTTState, MQTTTransaction, ALPROTO_MQTT};
+use crate::conf::conf_get;
use crate::mqtt::mqtt_message::{MQTTOperation, MQTTTypeCode};
use std::ffi::CStr;
+use std::os::raw::{c_int, c_void};
use std::ptr;
use std::str::FromStr;
-#[derive(FromPrimitive, Debug, Copy, Clone, PartialOrd, PartialEq, Eq)]
-#[allow(non_camel_case_types)]
-#[repr(u8)]
-pub enum MQTTFlagState {
- MQTT_DONT_CARE = 0,
- MQTT_MUST_BE_SET = 1,
- MQTT_CANT_BE_SET = 2,
-}
-
-#[inline]
-fn check_flag_state(flag_state: MQTTFlagState, flag_value: bool, ok: &mut bool) {
- match flag_state {
- MQTTFlagState::MQTT_MUST_BE_SET => {
- if !flag_value {
- *ok = false;
- }
- }
- MQTTFlagState::MQTT_CANT_BE_SET => {
- if flag_value {
- *ok = false;
- }
- }
- _ => {}
- }
-}
-
-#[no_mangle]
-pub extern "C" fn rs_mqtt_tx_has_type(tx: &MQTTTransaction, mtype: u8) -> u8 {
- for msg in tx.msg.iter() {
- if mtype == msg.header.message_type as u8 {
- return 1;
- }
- }
- return 0;
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_cstr_message_code(
- str: *const std::os::raw::c_char,
-) -> std::os::raw::c_int {
- let msgtype: &CStr = CStr::from_ptr(str);
- if let Ok(s) = msgtype.to_str() {
- if let Ok(x) = MQTTTypeCode::from_str(s) {
- return x as i32;
- }
- }
- return -1;
-}
-
-#[no_mangle]
-pub extern "C" fn rs_mqtt_tx_has_flags(
- tx: &MQTTTransaction, qretain: MQTTFlagState, qdup: MQTTFlagState,
-) -> u8 {
- for msg in tx.msg.iter() {
- let mut ok = true;
- check_flag_state(qretain, msg.header.retain, &mut ok);
- check_flag_state(qdup, msg.header.dup_flag, &mut ok);
- if ok {
- return 1;
- }
- }
-
- return 0;
-}
-
-#[no_mangle]
-pub extern "C" fn rs_mqtt_tx_has_qos(tx: &MQTTTransaction, qos: u8) -> u8 {
+fn mqtt_tx_has_type(tx: &MQTTTransaction, mtype: &DetectUintData<u8>) -> c_int {
for msg in tx.msg.iter() {
- if qos == msg.header.qos_level {
+ if detect_match_uint(mtype, msg.header.message_type as u8) {
return 1;
}
}
return 0;
}
-#[no_mangle]
-pub extern "C" fn rs_mqtt_tx_get_protocol_version(state: &MQTTState) -> u8 {
- return state.protocol_version;
-}
-
-#[no_mangle]
-pub extern "C" fn rs_mqtt_tx_has_connect_flags(
- tx: &MQTTTransaction, username: MQTTFlagState, password: MQTTFlagState, will: MQTTFlagState,
- will_retain: MQTTFlagState, clean_session: MQTTFlagState,
-) -> u8 {
- for msg in tx.msg.iter() {
- if let MQTTOperation::CONNECT(ref cv) = msg.op {
- let mut ok = true;
- check_flag_state(username, cv.username_flag, &mut ok);
- check_flag_state(password, cv.password_flag, &mut ok);
- check_flag_state(will, cv.will_flag, &mut ok);
- check_flag_state(will_retain, cv.will_retain, &mut ok);
- check_flag_state(clean_session, cv.clean_session, &mut ok);
- if ok {
- return 1;
- }
- }
- }
- return 0;
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_connect_clientid(
- tx: &MQTTTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn mqtt_tx_get_connect_clientid(
+ tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
if let MQTTOperation::CONNECT(ref cv) = msg.op {
let p = &cv.client_id;
if !p.is_empty() {
*buffer = p.as_ptr();
*buffer_len = p.len() as u32;
- return 1;
+ return true;
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
- return 0;
+ return false;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_connect_username(
- tx: &MQTTTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn mqtt_tx_get_connect_username(
+ tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
if let MQTTOperation::CONNECT(ref cv) = msg.op {
if let Some(p) = &cv.username {
if !p.is_empty() {
*buffer = p.as_ptr();
*buffer_len = p.len() as u32;
- return 1;
+ return true;
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
-
- return 0;
+ return false;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_connect_password(
- tx: &MQTTTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn mqtt_tx_get_connect_password(
+ tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
if let MQTTOperation::CONNECT(ref cv) = msg.op {
if let Some(p) = &cv.password {
if !p.is_empty() {
*buffer = p.as_ptr();
*buffer_len = p.len() as u32;
- return 1;
+ return true;
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
- return 0;
+ return false;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_connect_willtopic(
- tx: &MQTTTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn mqtt_tx_get_connect_willtopic(
+ tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
if let MQTTOperation::CONNECT(ref cv) = msg.op {
if let Some(p) = &cv.will_topic {
if !p.is_empty() {
*buffer = p.as_ptr();
*buffer_len = p.len() as u32;
- return 1;
+ return true;
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
-
- return 0;
+ return false;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_connect_willmessage(
- tx: &MQTTTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn mqtt_tx_get_connect_willmessage(
+ tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
if let MQTTOperation::CONNECT(ref cv) = msg.op {
if let Some(p) = &cv.will_message {
if !p.is_empty() {
*buffer = p.as_ptr();
*buffer_len = p.len() as u32;
- return 1;
+ return true;
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
-
- return 0;
+ return false;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_connect_protocol_string(
- tx: &MQTTTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn mqtt_tx_get_connect_protocol_string(
+ tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
if let MQTTOperation::CONNECT(ref cv) = msg.op {
let p = &cv.protocol_string;
if !p.is_empty() {
*buffer = p.as_ptr();
*buffer_len = p.len() as u32;
- return 1;
+ return true;
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
- return 0;
+ return false;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_connack_sessionpresent(
- tx: &MQTTTransaction, session_present: *mut bool,
-) -> u8 {
- for msg in tx.msg.iter() {
- if let MQTTOperation::CONNACK(ref ca) = msg.op {
- *session_present = ca.session_present;
- return 1;
- }
- }
- return 0;
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_publish_topic(
- tx: &MQTTTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn mqtt_tx_get_publish_topic(
+ tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
if let MQTTOperation::PUBLISH(ref pubv) = msg.op {
let p = &pubv.topic;
if !p.is_empty() {
*buffer = p.as_ptr();
*buffer_len = p.len() as u32;
- return 1;
+ return true;
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
-
- return 0;
+ return false;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_publish_message(
- tx: &MQTTTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn mqtt_tx_get_publish_message(
+ tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
if let MQTTOperation::PUBLISH(ref pubv) = msg.op {
let p = &pubv.message;
if !p.is_empty() {
*buffer = p.as_ptr();
*buffer_len = p.len() as u32;
- return 1;
+ return true;
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
+ return false;
+}
+
+fn mqtt_tx_get_reason_code(tx: &MQTTTransaction) -> Option<u8> {
+ for msg in tx.msg.iter() {
+ match msg.op {
+ MQTTOperation::PUBACK(ref v)
+ | MQTTOperation::PUBREL(ref v)
+ | MQTTOperation::PUBREC(ref v)
+ | MQTTOperation::PUBCOMP(ref v) => {
+ if let Some(rcode) = v.reason_code {
+ return Some(rcode);
+ }
+ }
+ MQTTOperation::AUTH(ref v) => {
+ return Some(v.reason_code);
+ }
+ MQTTOperation::CONNACK(ref v) => {
+ return Some(v.return_code);
+ }
+ MQTTOperation::DISCONNECT(ref v) => {
+ if let Some(rcode) = v.reason_code {
+ return Some(rcode);
+ }
+ }
+ _ => {}
+ }
+ }
+ return None;
+}
+fn mqtt_tx_unsuback_has_reason_code(tx: &MQTTTransaction, code: &DetectUintData<u8>) -> c_int {
+ for msg in tx.msg.iter() {
+ if let MQTTOperation::UNSUBACK(ref unsuback) = msg.op {
+ if let Some(ref reason_codes) = unsuback.reason_codes {
+ for rc in reason_codes.iter() {
+ if detect_match_uint(code, *rc) {
+ return 1;
+ }
+ }
+ }
+ }
+ }
return 0;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_subscribe_topic(
- tx: &MQTTTransaction, i: u32, buf: *mut *const u8, len: *mut u32,
-) -> u8 {
+static mut UNSUB_TOPIC_MATCH_LIMIT: isize = 100;
+static mut G_MQTT_UNSUB_TOPIC_BUFFER_ID: c_int = 0;
+static mut G_MQTT_TYPE_KW_ID: c_int = 0;
+static mut G_MQTT_TYPE_BUFFER_ID: c_int = 0;
+static mut SUB_TOPIC_MATCH_LIMIT: isize = 100;
+static mut G_MQTT_SUB_TOPIC_BUFFER_ID: c_int = 0;
+static mut G_MQTT_REASON_CODE_KW_ID: c_int = 0;
+static mut G_MQTT_REASON_CODE_BUFFER_ID: c_int = 0;
+static mut G_MQTT_QOS_KW_ID: c_int = 0;
+static mut G_MQTT_QOS_BUFFER_ID: c_int = 0;
+static mut G_MQTT_PUB_TOPIC_BUFFER_ID: c_int = 0;
+static mut G_MQTT_PUB_MSG_BUFFER_ID: c_int = 0;
+static mut G_MQTT_PROTOCOL_VERSION_KW_ID: c_int = 0;
+static mut G_MQTT_PROTOCOL_VERSION_BUFFER_ID: c_int = 0;
+static mut G_MQTT_FLAGS_KW_ID: c_int = 0;
+static mut G_MQTT_FLAGS_BUFFER_ID: c_int = 0;
+static mut G_MQTT_CONN_WILLTOPIC_BUFFER_ID: c_int = 0;
+static mut G_MQTT_CONN_WILLMSG_BUFFER_ID: c_int = 0;
+static mut G_MQTT_CONN_USERNAME_BUFFER_ID: c_int = 0;
+static mut G_MQTT_CONN_PROTOCOLSTRING_BUFFER_ID: c_int = 0;
+static mut G_MQTT_CONN_PASSWORD_BUFFER_ID: c_int = 0;
+static mut G_MQTT_CONN_CLIENTID_BUFFER_ID: c_int = 0;
+static mut G_MQTT_CONNACK_SESSIONPRESENT_KW_ID: c_int = 0;
+static mut G_MQTT_CONNACK_SESSIONPRESENT_BUFFER_ID: c_int = 0;
+static mut G_MQTT_CONN_FLAGS_KW_ID: c_int = 0;
+static mut G_MQTT_CONN_FLAGS_BUFFER_ID: c_int = 0;
+
+unsafe extern "C" fn unsub_topic_get_data(
+ tx: *const c_void, _flow_flags: u8, local_id: u32, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let ml = UNSUB_TOPIC_MATCH_LIMIT;
+ if ml > 0 && local_id >= ml as u32 {
+ return false;
+ }
let mut offset = 0;
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
- if let MQTTOperation::SUBSCRIBE(ref subv) = msg.op {
- if (i as usize) < subv.topics.len() + offset {
- let topic = &subv.topics[(i as usize) - offset];
- if !topic.topic_name.is_empty() {
- *len = topic.topic_name.len() as u32;
- *buf = topic.topic_name.as_ptr();
- return 1;
- }
+ if let MQTTOperation::UNSUBSCRIBE(ref unsubv) = msg.op {
+ if (local_id as usize) < unsubv.topics.len() + offset {
+ let topic = &unsubv.topics[(local_id as usize) - offset];
+ *buffer_len = topic.len() as u32;
+ *buffer = topic.as_ptr();
+ return true;
} else {
- offset += subv.topics.len();
+ offset += unsubv.topics.len();
}
}
}
- *buf = ptr::null();
- *len = 0;
+ *buffer = ptr::null();
+ *buffer_len = 0;
+ return false;
+}
+
+unsafe extern "C" fn unsub_topic_get_data_wrapper(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int, local_id: u32,
+) -> *mut c_void {
+ return DetectHelperGetMultiData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ local_id,
+ unsub_topic_get_data,
+ );
+}
+
+unsafe extern "C" fn unsub_topic_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_UNSUB_TOPIC_BUFFER_ID) < 0 {
+ return -1;
+ }
return 0;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_unsubscribe_topic(
- tx: &MQTTTransaction, i: u32, buf: *mut *const u8, len: *mut u32,
-) -> u8 {
+unsafe extern "C" fn sub_topic_get_data(
+ tx: *const c_void, _flow_flags: u8, local_id: u32, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let ml = SUB_TOPIC_MATCH_LIMIT;
+ if ml > 0 && local_id >= ml as u32 {
+ return false;
+ }
let mut offset = 0;
+ let tx = cast_pointer!(tx, MQTTTransaction);
for msg in tx.msg.iter() {
- if let MQTTOperation::UNSUBSCRIBE(ref unsubv) = msg.op {
- if (i as usize) < unsubv.topics.len() + offset {
- let topic = &unsubv.topics[(i as usize) - offset];
- if !topic.is_empty() {
- *len = topic.len() as u32;
- *buf = topic.as_ptr();
- return 1;
- }
+ if let MQTTOperation::SUBSCRIBE(ref subv) = msg.op {
+ if (local_id as usize) < subv.topics.len() + offset {
+ let topic = &subv.topics[(local_id as usize) - offset];
+ *buffer_len = topic.topic_name.len() as u32;
+ *buffer = topic.topic_name.as_ptr();
+ return true;
} else {
- offset += unsubv.topics.len();
+ offset += subv.topics.len();
}
}
}
- *buf = ptr::null();
- *len = 0;
+ *buffer = ptr::null();
+ *buffer_len = 0;
+ return false;
+}
+
+unsafe extern "C" fn sub_topic_get_data_wrapper(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int, local_id: u32,
+) -> *mut c_void {
+ return DetectHelperGetMultiData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ local_id,
+ sub_topic_get_data,
+ );
+}
+
+unsafe extern "C" fn sub_topic_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_SUB_TOPIC_BUFFER_ID) < 0 {
+ return -1;
+ }
return 0;
}
-#[no_mangle]
-pub unsafe extern "C" fn rs_mqtt_tx_get_reason_code(tx: &MQTTTransaction, result: *mut u8) -> u8 {
+unsafe extern "C" fn mqtt_parse_type(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 Some(ctx) = detect_parse_uint_enum::<u8, MQTTTypeCode>(s) {
+ let boxed = Box::new(ctx);
+ return Box::into_raw(boxed) as *mut _;
+ }
+ }
+ return std::ptr::null_mut();
+}
+
+unsafe extern "C" fn mqtt_type_setup(
+ de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ let ctx = mqtt_parse_type(raw) as *mut c_void;
+ if ctx.is_null() {
+ return -1;
+ }
+ if SigMatchAppendSMToList(de, s, G_MQTT_TYPE_KW_ID, ctx, G_MQTT_TYPE_BUFFER_ID).is_null() {
+ mqtt_type_free(std::ptr::null_mut(), ctx);
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_type_match(
+ _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void,
+ _sig: *const c_void, ctx: *const c_void,
+) -> c_int {
+ let tx = cast_pointer!(tx, MQTTTransaction);
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ return mqtt_tx_has_type(tx, ctx);
+}
+
+unsafe extern "C" fn mqtt_type_free(_de: *mut c_void, ctx: *mut c_void) {
+ // Just unbox...
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ rs_detect_u8_free(ctx);
+}
+
+unsafe extern "C" fn mqtt_reason_code_setup(
+ de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ let ctx = rs_detect_u8_parse(raw) as *mut c_void;
+ if ctx.is_null() {
+ return -1;
+ }
+ if SigMatchAppendSMToList(
+ de,
+ s,
+ G_MQTT_REASON_CODE_KW_ID,
+ ctx,
+ G_MQTT_REASON_CODE_BUFFER_ID,
+ )
+ .is_null()
+ {
+ mqtt_reason_code_free(std::ptr::null_mut(), ctx);
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_reason_code_match(
+ _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void,
+ _sig: *const c_void, ctx: *const c_void,
+) -> c_int {
+ let tx = cast_pointer!(tx, MQTTTransaction);
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ if let Some(v) = mqtt_tx_get_reason_code(tx) {
+ if detect_match_uint(ctx, v) {
+ return 1;
+ }
+ }
+ return mqtt_tx_unsuback_has_reason_code(tx, ctx);
+}
+
+unsafe extern "C" fn mqtt_reason_code_free(_de: *mut c_void, ctx: *mut c_void) {
+ // Just unbox...
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ rs_detect_u8_free(ctx);
+}
+
+unsafe extern "C" fn mqtt_parse_qos(ustr: *const std::os::raw::c_char) -> *mut u8 {
+ let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
+ if let Ok(s) = ft_name.to_str() {
+ if let Ok(ctx) = u8::from_str(s.trim()) {
+ if ctx <= 2 {
+ let boxed = Box::new(ctx);
+ return Box::into_raw(boxed) as *mut _;
+ }
+ }
+ }
+ return std::ptr::null_mut();
+}
+
+unsafe extern "C" fn mqtt_qos_setup(
+ de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ let ctx = mqtt_parse_qos(raw) as *mut c_void;
+ if ctx.is_null() {
+ return -1;
+ }
+ if SigMatchAppendSMToList(de, s, G_MQTT_QOS_KW_ID, ctx, G_MQTT_QOS_BUFFER_ID).is_null() {
+ mqtt_qos_free(std::ptr::null_mut(), ctx);
+ return -1;
+ }
+ return 0;
+}
+
+fn mqtt_tx_has_qos(tx: &MQTTTransaction, qos: u8) -> c_int {
for msg in tx.msg.iter() {
- match msg.op {
- MQTTOperation::PUBACK(ref v)
- | MQTTOperation::PUBREL(ref v)
- | MQTTOperation::PUBREC(ref v)
- | MQTTOperation::PUBCOMP(ref v) => {
- if let Some(rcode) = v.reason_code {
- *result = rcode;
- return 1;
- }
+ if qos == msg.header.qos_level {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_qos_match(
+ _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void,
+ _sig: *const c_void, ctx: *const c_void,
+) -> c_int {
+ let tx = cast_pointer!(tx, MQTTTransaction);
+ let ctx = cast_pointer!(ctx, u8);
+ return mqtt_tx_has_qos(tx, *ctx);
+}
+
+unsafe extern "C" fn mqtt_qos_free(_de: *mut c_void, ctx: *mut c_void) {
+ std::mem::drop(Box::from_raw(ctx as *mut u8));
+}
+
+unsafe extern "C" fn mqtt_parse_bool(ustr: *const std::os::raw::c_char) -> *mut bool {
+ let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
+ if let Ok(s) = ft_name.to_str() {
+ if let Ok(ctx) = u8::from_str(s.trim()) {
+ if ctx <= 2 {
+ let boxed = Box::new(ctx);
+ return Box::into_raw(boxed) as *mut _;
}
- MQTTOperation::AUTH(ref v) => {
- *result = v.reason_code;
+ }
+ }
+ return std::ptr::null_mut();
+}
+
+unsafe extern "C" fn mqtt_connack_sessionpresent_setup(
+ de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ let ctx = mqtt_parse_bool(raw) as *mut c_void;
+ if ctx.is_null() {
+ return -1;
+ }
+ if SigMatchAppendSMToList(
+ de,
+ s,
+ G_MQTT_CONNACK_SESSIONPRESENT_KW_ID,
+ ctx,
+ G_MQTT_CONNACK_SESSIONPRESENT_BUFFER_ID,
+ )
+ .is_null()
+ {
+ mqtt_connack_sessionpresent_free(std::ptr::null_mut(), ctx);
+ return -1;
+ }
+ return 0;
+}
+
+fn mqtt_tx_get_connack_sessionpresent(tx: &MQTTTransaction, session_present: bool) -> c_int {
+ for msg in tx.msg.iter() {
+ if let MQTTOperation::CONNACK(ref ca) = msg.op {
+ if session_present == ca.session_present {
return 1;
}
- MQTTOperation::CONNACK(ref v) => {
- *result = v.return_code;
- return 1;
+ }
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_connack_sessionpresent_match(
+ _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void,
+ _sig: *const c_void, ctx: *const c_void,
+) -> c_int {
+ let tx = cast_pointer!(tx, MQTTTransaction);
+ let ctx = cast_pointer!(ctx, bool);
+ return mqtt_tx_get_connack_sessionpresent(tx, *ctx);
+}
+
+unsafe extern "C" fn mqtt_connack_sessionpresent_free(_de: *mut c_void, ctx: *mut c_void) {
+ std::mem::drop(Box::from_raw(ctx as *mut bool));
+}
+
+unsafe extern "C" fn mqtt_pub_topic_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_PUB_TOPIC_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_pub_topic_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int,
+) -> *mut c_void {
+ return DetectHelperGetData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ mqtt_tx_get_publish_topic,
+ );
+}
+
+unsafe extern "C" fn mqtt_pub_msg_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_PUB_MSG_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_pub_msg_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int,
+) -> *mut c_void {
+ return DetectHelperGetData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ mqtt_tx_get_publish_message,
+ );
+}
+
+unsafe extern "C" fn mqtt_protocol_version_setup(
+ de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ let ctx = rs_detect_u8_parse(raw) as *mut c_void;
+ if ctx.is_null() {
+ return -1;
+ }
+ if SigMatchAppendSMToList(
+ de,
+ s,
+ G_MQTT_PROTOCOL_VERSION_KW_ID,
+ ctx,
+ G_MQTT_PROTOCOL_VERSION_BUFFER_ID,
+ )
+ .is_null()
+ {
+ mqtt_protocol_version_free(std::ptr::null_mut(), ctx);
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_protocol_version_match(
+ _de: *mut c_void, _f: *mut c_void, _flags: u8, state: *mut c_void, _tx: *mut c_void,
+ _sig: *const c_void, ctx: *const c_void,
+) -> c_int {
+ let state = cast_pointer!(state, MQTTState);
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ if detect_match_uint(ctx, state.protocol_version) {
+ return 1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_protocol_version_free(_de: *mut c_void, ctx: *mut c_void) {
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ rs_detect_u8_free(ctx);
+}
+
+// maybe to factor with websocket.flags
+struct MqttParsedFlagItem {
+ neg: bool,
+ value: u8,
+}
+
+fn parse_flag_list_item(s: &str) -> IResult<&str, MqttParsedFlagItem> {
+ let (s, _) = opt(is_a(" "))(s)?;
+ let (s, neg) = opt(tag("!"))(s)?;
+ let neg = neg.is_some();
+ let (s, value) = alt((value(0x8, tag("dup")), value(0x1, tag("retain"))))(s)?;
+ let (s, _) = opt(is_a(" ,"))(s)?;
+ Ok((s, MqttParsedFlagItem { neg, value }))
+}
+
+fn parse_flag_list(s: &str) -> IResult<&str, Vec<MqttParsedFlagItem>> {
+ return many1(parse_flag_list_item)(s);
+}
+
+fn parse_flags(s: &str) -> Option<DetectUintData<u8>> {
+ // try first numerical value
+ if let Ok((_, ctx)) = detect_parse_uint::<u8>(s) {
+ return Some(ctx);
+ }
+ // otherwise, try strings for bitmask
+ if let Ok((rem, l)) = parse_flag_list(s) {
+ if !rem.is_empty() {
+ SCLogWarning!("junk at the end of mqtt.flags");
+ return None;
+ }
+ let mut arg1 = 0;
+ let mut arg2 = 0;
+ for elem in l.iter() {
+ if elem.value & arg1 != 0 {
+ SCLogWarning!("Repeated bitflag for mqtt.flags");
+ return None;
}
- MQTTOperation::DISCONNECT(ref v) => {
- if let Some(rcode) = v.reason_code {
- *result = rcode;
- return 1;
- }
+ arg1 |= elem.value;
+ if !elem.neg {
+ arg2 |= elem.value;
}
- _ => return 0,
}
+ let ctx = DetectUintData::<u8> {
+ arg1,
+ arg2,
+ mode: DetectUintMode::DetectUintModeBitmask,
+ };
+ return Some(ctx);
+ }
+ return None;
+}
+
+unsafe extern "C" fn mqtt_parse_flags(
+ 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 Some(ctx) = parse_flags(s) {
+ let boxed = Box::new(ctx);
+ return Box::into_raw(boxed) as *mut _;
+ }
+ }
+ return std::ptr::null_mut();
+}
+
+unsafe extern "C" fn mqtt_flags_setup(
+ de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ let ctx = mqtt_parse_flags(raw) as *mut c_void;
+ if ctx.is_null() {
+ return -1;
+ }
+ if SigMatchAppendSMToList(de, s, G_MQTT_FLAGS_KW_ID, ctx, G_MQTT_FLAGS_BUFFER_ID).is_null() {
+ mqtt_flags_free(std::ptr::null_mut(), ctx);
+ return -1;
}
return 0;
}
-#[no_mangle]
-pub extern "C" fn rs_mqtt_tx_unsuback_has_reason_code(tx: &MQTTTransaction, code: u8) -> u8 {
+fn mqtt_tx_has_flags(tx: &MQTTTransaction, ctx: &DetectUintData<u8>) -> c_int {
for msg in tx.msg.iter() {
- if let MQTTOperation::UNSUBACK(ref unsuback) = msg.op {
- if let Some(ref reason_codes) = unsuback.reason_codes {
- for rc in reason_codes.iter() {
- if *rc == code {
- return 1;
- }
- }
+ let mut v = 0;
+ if msg.header.retain {
+ v |= 1;
+ }
+ if msg.header.dup_flag {
+ v |= 0x8;
+ }
+ if detect_match_uint(ctx, v) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_flags_match(
+ _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void,
+ _sig: *const c_void, ctx: *const c_void,
+) -> c_int {
+ let tx = cast_pointer!(tx, MQTTTransaction);
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ return mqtt_tx_has_flags(tx, ctx);
+}
+
+unsafe extern "C" fn mqtt_flags_free(_de: *mut c_void, ctx: *mut c_void) {
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ rs_detect_u8_free(ctx);
+}
+
+fn parse_conn_flag_list_item(s: &str) -> IResult<&str, MqttParsedFlagItem> {
+ let (s, _) = opt(is_a(" "))(s)?;
+ let (s, neg) = opt(tag("!"))(s)?;
+ let neg = neg.is_some();
+ let (s, value) = alt((
+ value(0x80, tag("username")),
+ value(0x40, tag("password")),
+ // longer version first
+ value(0x4, tag("will_retain")),
+ value(0x20, tag("will")),
+ value(0x2, tag("clean_session")),
+ ))(s)?;
+ let (s, _) = opt(is_a(" ,"))(s)?;
+ Ok((s, MqttParsedFlagItem { neg, value }))
+}
+
+fn parse_conn_flag_list(s: &str) -> IResult<&str, Vec<MqttParsedFlagItem>> {
+ return many1(parse_conn_flag_list_item)(s);
+}
+
+fn parse_conn_flags(s: &str) -> Option<DetectUintData<u8>> {
+ // try first numerical value
+ if let Ok((_, ctx)) = detect_parse_uint::<u8>(s) {
+ return Some(ctx);
+ }
+ // otherwise, try strings for bitmask
+ if let Ok((rem, l)) = parse_conn_flag_list(s) {
+ if !rem.is_empty() {
+ SCLogWarning!("junk at the end of mqtt.connect.flags");
+ return None;
+ }
+ let mut arg1 = 0;
+ let mut arg2 = 0;
+ for elem in l.iter() {
+ if elem.value & arg1 != 0 {
+ SCLogWarning!("Repeated bitflag for mqtt.connect.flags");
+ return None;
+ }
+ arg1 |= elem.value;
+ if !elem.neg {
+ arg2 |= elem.value;
+ }
+ }
+ let ctx = DetectUintData::<u8> {
+ arg1,
+ arg2,
+ mode: DetectUintMode::DetectUintModeBitmask,
+ };
+ return Some(ctx);
+ }
+ return None;
+}
+
+unsafe extern "C" fn mqtt_parse_conn_flags(
+ 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 Some(ctx) = parse_conn_flags(s) {
+ let boxed = Box::new(ctx);
+ return Box::into_raw(boxed) as *mut _;
+ }
+ }
+ return std::ptr::null_mut();
+}
+
+unsafe extern "C" fn mqtt_conn_flags_setup(
+ de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ let ctx = mqtt_parse_conn_flags(raw) as *mut c_void;
+ if ctx.is_null() {
+ return -1;
+ }
+ if SigMatchAppendSMToList(
+ de,
+ s,
+ G_MQTT_CONN_FLAGS_KW_ID,
+ ctx,
+ G_MQTT_CONN_FLAGS_BUFFER_ID,
+ )
+ .is_null()
+ {
+ mqtt_conn_flags_free(std::ptr::null_mut(), ctx);
+ return -1;
+ }
+ return 0;
+}
+
+fn rs_mqtt_tx_has_conn_flags(tx: &MQTTTransaction, ctx: &DetectUintData<u8>) -> c_int {
+ for msg in tx.msg.iter() {
+ if let MQTTOperation::CONNECT(ref cv) = msg.op {
+ if detect_match_uint(ctx, cv.rawflags) {
+ return 1;
}
}
}
return 0;
}
+unsafe extern "C" fn mqtt_conn_flags_match(
+ _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void,
+ _sig: *const c_void, ctx: *const c_void,
+) -> c_int {
+ let tx = cast_pointer!(tx, MQTTTransaction);
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ return rs_mqtt_tx_has_conn_flags(tx, ctx);
+}
+
+unsafe extern "C" fn mqtt_conn_flags_free(_de: *mut c_void, ctx: *mut c_void) {
+ let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ rs_detect_u8_free(ctx);
+}
+
+unsafe extern "C" fn mqtt_conn_willtopic_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_CONN_WILLTOPIC_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_conn_willtopic_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int,
+) -> *mut c_void {
+ return DetectHelperGetData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ mqtt_tx_get_connect_willtopic,
+ );
+}
+
+unsafe extern "C" fn mqtt_conn_willmsg_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_CONN_WILLMSG_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_conn_willmsg_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int,
+) -> *mut c_void {
+ return DetectHelperGetData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ mqtt_tx_get_connect_willmessage,
+ );
+}
+
+unsafe extern "C" fn mqtt_conn_username_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_CONN_USERNAME_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_conn_username_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int,
+) -> *mut c_void {
+ return DetectHelperGetData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ mqtt_tx_get_connect_username,
+ );
+}
+
+unsafe extern "C" fn mqtt_conn_protocolstring_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_CONN_PROTOCOLSTRING_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_conn_protocolstring_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int,
+) -> *mut c_void {
+ return DetectHelperGetData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ mqtt_tx_get_connect_protocol_string,
+ );
+}
+
+unsafe extern "C" fn mqtt_conn_password_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_CONN_PASSWORD_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_conn_password_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int,
+) -> *mut c_void {
+ return DetectHelperGetData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ mqtt_tx_get_connect_password,
+ );
+}
+
+unsafe extern "C" fn mqtt_conn_clientid_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_MQTT) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_MQTT_CONN_CLIENTID_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn mqtt_conn_clientid_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int,
+) -> *mut c_void {
+ return DetectHelperGetData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ mqtt_tx_get_connect_clientid,
+ );
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn ScDetectMqttRegister() {
+ let keyword_name = b"mqtt.unsubscribe.topic\0".as_ptr() as *const libc::c_char;
+ let kw = SCSigTableElmt {
+ name: keyword_name,
+ desc: b"sticky buffer to match MQTT UNSUBSCRIBE topic\0".as_ptr() as *const libc::c_char,
+ url: b"/rules/mqtt-keywords.html#mqtt-unsubscribe-topic\0".as_ptr() as *const libc::c_char,
+ Setup: unsub_topic_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ if let Some(val) = conf_get("app-layer.protocols.mqtt.unsubscribe-topic-match-limit") {
+ if let Ok(v) = val.parse::<isize>() {
+ UNSUB_TOPIC_MATCH_LIMIT = v;
+ } else {
+ SCLogError!("Invalid value for app-layer.protocols.mqtt.unsubscribe-topic-match-limit");
+ }
+ }
+ let _g_mqtt_unsub_topic_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_UNSUB_TOPIC_BUFFER_ID = DetectHelperMultiBufferMpmRegister(
+ keyword_name,
+ b"unsubscribe topic query\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ unsub_topic_get_data_wrapper,
+ );
+
+ let kw = SCSigTableElmt {
+ name: b"mqtt.type\0".as_ptr() as *const libc::c_char,
+ desc: b"match MQTT control packet type\0".as_ptr() as *const libc::c_char,
+ url: b"/rules/mqtt-keywords.html#mqtt-type\0".as_ptr() as *const libc::c_char,
+ AppLayerTxMatch: Some(mqtt_type_match),
+ Setup: mqtt_type_setup,
+ Free: Some(mqtt_type_free),
+ flags: 0,
+ };
+ G_MQTT_TYPE_KW_ID = DetectHelperKeywordRegister(&kw);
+ G_MQTT_TYPE_BUFFER_ID = DetectHelperBufferRegister(
+ b"mqtt.type\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false, // only to server
+ true,
+ );
+
+ let keyword_name = b"mqtt.subscribe.topic\0".as_ptr() as *const libc::c_char;
+ let kw = SCSigTableElmt {
+ name: keyword_name,
+ desc: b"sticky buffer to match MQTT SUBSCRIBE topic\0".as_ptr() as *const libc::c_char,
+ url: b"/rules/mqtt-keywords.html#mqtt-subscribe-topic\0".as_ptr() as *const libc::c_char,
+ Setup: sub_topic_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ if let Some(val) = conf_get("app-layer.protocols.mqtt.subscribe-topic-match-limit") {
+ if let Ok(v) = val.parse::<isize>() {
+ SUB_TOPIC_MATCH_LIMIT = v;
+ } else {
+ SCLogError!("Invalid value for app-layer.protocols.mqtt.subscribe-topic-match-limit");
+ }
+ }
+ let _g_mqtt_sub_topic_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_SUB_TOPIC_BUFFER_ID = DetectHelperMultiBufferMpmRegister(
+ keyword_name,
+ b"subscribe topic query\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ sub_topic_get_data_wrapper,
+ );
+
+ let kw = SCSigTableElmt {
+ name: b"mqtt.reason_code\0".as_ptr() as *const libc::c_char,
+ desc: b"match MQTT 5.0+ reason code\0".as_ptr() as *const libc::c_char,
+ //TODO alias "mqtt.connack.return_code"
+ url: b"/rules/mqtt-keywords.html#mqtt-reason-code\0".as_ptr() as *const libc::c_char,
+ AppLayerTxMatch: Some(mqtt_reason_code_match),
+ Setup: mqtt_reason_code_setup,
+ Free: Some(mqtt_reason_code_free),
+ flags: 0,
+ };
+ G_MQTT_REASON_CODE_KW_ID = DetectHelperKeywordRegister(&kw);
+ G_MQTT_REASON_CODE_BUFFER_ID = DetectHelperBufferRegister(
+ b"mqtt.reason_code\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false, // only to server
+ true,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.connack.session_present\0".as_ptr() as *const libc::c_char,
+ desc: b"match MQTT CONNACK session present flag\0".as_ptr() as *const libc::c_char,
+ url: b"/rules/mqtt-keywords.html#mqtt-connack-session-present\0".as_ptr()
+ as *const libc::c_char,
+ AppLayerTxMatch: Some(mqtt_connack_sessionpresent_match),
+ Setup: mqtt_connack_sessionpresent_setup,
+ Free: Some(mqtt_connack_sessionpresent_free),
+ flags: 0,
+ };
+ G_MQTT_CONNACK_SESSIONPRESENT_KW_ID = DetectHelperKeywordRegister(&kw);
+ G_MQTT_CONNACK_SESSIONPRESENT_BUFFER_ID = DetectHelperBufferRegister(
+ b"mqtt.connack.session_present\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false, // only to server
+ true,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.qos\0".as_ptr() as *const libc::c_char,
+ desc: b"match MQTT fixed header QOS level\0".as_ptr() as *const libc::c_char,
+ //TODO alias "mqtt.connack.return_code"
+ url: b"/rules/mqtt-keywords.html#mqtt-qos\0".as_ptr() as *const libc::c_char,
+ AppLayerTxMatch: Some(mqtt_qos_match),
+ Setup: mqtt_qos_setup,
+ Free: Some(mqtt_qos_free),
+ flags: 0,
+ };
+ G_MQTT_QOS_KW_ID = DetectHelperKeywordRegister(&kw);
+ G_MQTT_QOS_BUFFER_ID = DetectHelperBufferRegister(
+ b"mqtt.qos\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false, // only to server
+ true,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.publish.topic\0".as_ptr() as *const libc::c_char,
+ desc: b"sticky buffer to match on the MQTT PUBLISH topic\0".as_ptr() as *const libc::c_char,
+ url: b"mqtt-keywords.html#mqtt-publish-topic\0".as_ptr() as *const libc::c_char,
+ Setup: mqtt_pub_topic_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_mqtt_pub_topic_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_PUB_TOPIC_BUFFER_ID = DetectHelperBufferMpmRegister(
+ b"mqtt.publish.topic\0".as_ptr() as *const libc::c_char,
+ b"MQTT PUBLISH topic\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ mqtt_pub_topic_get_data,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.publish.message\0".as_ptr() as *const libc::c_char,
+ desc: b"sticky buffer to match on the MQTT PUBLISH message\0".as_ptr()
+ as *const libc::c_char,
+ url: b"mqtt-keywords.html#mqtt-publish-message\0".as_ptr() as *const libc::c_char,
+ Setup: mqtt_pub_msg_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_mqtt_pub_msg_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_PUB_MSG_BUFFER_ID = DetectHelperBufferMpmRegister(
+ b"mqtt.publish.message\0".as_ptr() as *const libc::c_char,
+ b"MQTT PUBLISH message\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ mqtt_pub_msg_get_data,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.protocol_version\0".as_ptr() as *const libc::c_char,
+ desc: b"match MQTT protocol version\0".as_ptr() as *const libc::c_char,
+ url: b"/rules/mqtt-keywords.html#mqtt-protocol-version\0".as_ptr() as *const libc::c_char,
+ AppLayerTxMatch: Some(mqtt_protocol_version_match),
+ Setup: mqtt_protocol_version_setup,
+ Free: Some(mqtt_protocol_version_free),
+ flags: 0,
+ };
+ G_MQTT_PROTOCOL_VERSION_KW_ID = DetectHelperKeywordRegister(&kw);
+ G_MQTT_PROTOCOL_VERSION_BUFFER_ID = DetectHelperBufferRegister(
+ b"mqtt.protocol_version\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false, // only to server
+ true,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.flags\0".as_ptr() as *const libc::c_char,
+ desc: b"match MQTT fixed header flags\0".as_ptr() as *const libc::c_char,
+ url: b"/rules/mqtt-keywords.html#mqtt-flags\0".as_ptr() as *const libc::c_char,
+ AppLayerTxMatch: Some(mqtt_flags_match),
+ Setup: mqtt_flags_setup,
+ Free: Some(mqtt_flags_free),
+ flags: 0,
+ };
+ G_MQTT_FLAGS_KW_ID = DetectHelperKeywordRegister(&kw);
+ G_MQTT_FLAGS_BUFFER_ID = DetectHelperBufferRegister(
+ b"mqtt.flags\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false, // only to server
+ true,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.connect.flags\0".as_ptr() as *const libc::c_char,
+ desc: b"match MQTT CONNECT variable header flags\0".as_ptr() as *const libc::c_char,
+ url: b"/rules/mqtt-keywords.html#mqtt-connect-flags\0".as_ptr() as *const libc::c_char,
+ AppLayerTxMatch: Some(mqtt_conn_flags_match),
+ Setup: mqtt_conn_flags_setup,
+ Free: Some(mqtt_conn_flags_free),
+ flags: 0,
+ };
+ G_MQTT_CONN_FLAGS_KW_ID = DetectHelperKeywordRegister(&kw);
+ G_MQTT_CONN_FLAGS_BUFFER_ID = DetectHelperBufferRegister(
+ b"mqtt.connect.flags\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false, // only to server
+ true,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.connect.willtopic\0".as_ptr() as *const libc::c_char,
+ desc: b"sticky buffer to match on the MQTT CONNECT will topic\0".as_ptr()
+ as *const libc::c_char,
+ url: b"mqtt-keywords.html#mqtt-connect-willtopic\0".as_ptr() as *const libc::c_char,
+ Setup: mqtt_conn_willtopic_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_mqtt_conn_willtopic_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_CONN_WILLTOPIC_BUFFER_ID = DetectHelperBufferMpmRegister(
+ b"mqtt.connect.willtopic\0".as_ptr() as *const libc::c_char,
+ b"MQTT CONNECT will topic\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ mqtt_conn_willtopic_get_data,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.connect.willmessage\0".as_ptr() as *const libc::c_char,
+ desc: b"sticky buffer to match on the MQTT CONNECT will message\0".as_ptr()
+ as *const libc::c_char,
+ url: b"mqtt-keywords.html#mqtt-connect-willmessage\0".as_ptr() as *const libc::c_char,
+ Setup: mqtt_conn_willmsg_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_mqtt_conn_willmsg_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_CONN_WILLMSG_BUFFER_ID = DetectHelperBufferMpmRegister(
+ b"mqtt.connect.willmessage\0".as_ptr() as *const libc::c_char,
+ b"MQTT CONNECT will message\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ mqtt_conn_willmsg_get_data,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.connect.username\0".as_ptr() as *const libc::c_char,
+ desc: b"sticky buffer to match on the MQTT CONNECT username\0".as_ptr()
+ as *const libc::c_char,
+ url: b"mqtt-keywords.html#mqtt-connect-username\0".as_ptr() as *const libc::c_char,
+ Setup: mqtt_conn_username_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_mqtt_conn_username_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_CONN_USERNAME_BUFFER_ID = DetectHelperBufferMpmRegister(
+ b"mqtt.connect.username\0".as_ptr() as *const libc::c_char,
+ b"MQTT CONNECT username\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ mqtt_conn_username_get_data,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.connect.protocol_string\0".as_ptr() as *const libc::c_char,
+ desc: b"sticky buffer to match on the MQTT CONNECT protocol string\0".as_ptr()
+ as *const libc::c_char,
+ url: b"mqtt-keywords.html#mqtt-connect-protocol_string\0".as_ptr() as *const libc::c_char,
+ Setup: mqtt_conn_protocolstring_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_mqtt_conn_protostr_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_CONN_PROTOCOLSTRING_BUFFER_ID = DetectHelperBufferMpmRegister(
+ b"mqtt.connect.protocol_string\0".as_ptr() as *const libc::c_char,
+ b"MQTT CONNECT protocol string\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ mqtt_conn_protocolstring_get_data,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.connect.password\0".as_ptr() as *const libc::c_char,
+ desc: b"sticky buffer to match on the MQTT CONNECT password\0".as_ptr()
+ as *const libc::c_char,
+ url: b"mqtt-keywords.html#mqtt-connect-password\0".as_ptr() as *const libc::c_char,
+ Setup: mqtt_conn_password_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_mqtt_conn_password_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_CONN_PASSWORD_BUFFER_ID = DetectHelperBufferMpmRegister(
+ b"mqtt.connect.password\0".as_ptr() as *const libc::c_char,
+ b"MQTT CONNECT password\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ mqtt_conn_password_get_data,
+ );
+ let kw = SCSigTableElmt {
+ name: b"mqtt.connect.clientid\0".as_ptr() as *const libc::c_char,
+ desc: b"sticky buffer to match on the MQTT CONNECT clientid\0".as_ptr()
+ as *const libc::c_char,
+ url: b"mqtt-keywords.html#mqtt-connect-clientid\0".as_ptr() as *const libc::c_char,
+ Setup: mqtt_conn_clientid_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_mqtt_conn_password_kw_id = DetectHelperKeywordRegister(&kw);
+ G_MQTT_CONN_CLIENTID_BUFFER_ID = DetectHelperBufferMpmRegister(
+ b"mqtt.connect.clientid\0".as_ptr() as *const libc::c_char,
+ b"MQTT CONNECT clientid\0".as_ptr() as *const libc::c_char,
+ ALPROTO_MQTT,
+ false,
+ true,
+ mqtt_conn_clientid_get_data,
+ );
+}
+
#[cfg(test)]
mod test {
use super::*;
use crate::core::Direction;
+ use crate::detect::uint::DetectUintMode;
use crate::mqtt::mqtt::MQTTTransaction;
use crate::mqtt::mqtt_message::*;
use crate::mqtt::parser::FixedHeader;
use std;
+ #[test]
+ fn mqtt_type_test_qos() {
+ let ctx = unsafe { mqtt_parse_qos("0\0".as_ptr() as *const libc::c_char) };
+ assert!(!ctx.is_null());
+ assert_eq!(unsafe { *ctx }, 0);
+ let ctx = unsafe { mqtt_parse_qos(" 0\0".as_ptr() as *const libc::c_char) };
+ assert!(!ctx.is_null());
+ assert_eq!(unsafe { *ctx }, 0);
+ let ctx = unsafe { mqtt_parse_qos("1\0".as_ptr() as *const libc::c_char) };
+ assert!(!ctx.is_null());
+ assert_eq!(unsafe { *ctx }, 1);
+ let ctx = unsafe { mqtt_parse_qos("2\0".as_ptr() as *const libc::c_char) };
+ assert!(!ctx.is_null());
+ assert_eq!(unsafe { *ctx }, 2);
+ let ctx = unsafe { mqtt_parse_qos("3\0".as_ptr() as *const libc::c_char) };
+ assert!(ctx.is_null());
+ let ctx = unsafe { mqtt_parse_qos("12\0".as_ptr() as *const libc::c_char) };
+ assert!(ctx.is_null());
+ }
+
+ #[test]
+ fn mqtt_parse_flags() {
+ let ctx = parse_flags("retain").unwrap();
+ assert_eq!(ctx.arg1, 1);
+ assert_eq!(ctx.arg2, 1);
+ let ctx = parse_flags("dup").unwrap();
+ assert_eq!(ctx.arg1, 8);
+ assert_eq!(ctx.arg2, 8);
+ let ctx = parse_flags("retain,dup").unwrap();
+ assert_eq!(ctx.arg1, 8 | 1);
+ assert_eq!(ctx.arg2, 8 | 1);
+ let ctx = parse_flags("dup, retain").unwrap();
+ assert_eq!(ctx.arg1, 8 | 1);
+ assert_eq!(ctx.arg2, 8 | 1);
+ let ctx = parse_flags("retain,!dup").unwrap();
+ assert_eq!(ctx.arg1, 1 | 8);
+ assert_eq!(ctx.arg2, 1);
+ assert!(parse_flags("ref").is_none());
+ assert!(parse_flags("dup,!").is_none());
+ assert!(parse_flags("dup,!dup").is_none());
+ assert!(parse_flags("!retain,retain").is_none());
+ }
+
+ #[test]
+ fn mqtt_parse_conn_flags() {
+ let ctx = parse_conn_flags("username").unwrap();
+ assert_eq!(ctx.arg1, 0x80);
+ assert_eq!(ctx.arg2, 0x80);
+ let ctx = parse_conn_flags("username,password,will,will_retain,clean_session").unwrap();
+ assert_eq!(ctx.arg1, 0xE6);
+ assert_eq!(ctx.arg2, 0xE6);
+ let ctx =
+ parse_conn_flags("!username,!password,!will,!will_retain,!clean_session").unwrap();
+ assert_eq!(ctx.arg1, 0xE6);
+ assert_eq!(ctx.arg2, 0);
+ let ctx = parse_conn_flags(" username,password").unwrap();
+ assert_eq!(ctx.arg1, 0xC0);
+ assert_eq!(ctx.arg2, 0xC0);
+ assert!(parse_conn_flags("foobar").is_none());
+ assert!(parse_conn_flags("will,!").is_none());
+ assert!(parse_conn_flags("").is_none());
+ assert!(parse_conn_flags("username, username").is_none());
+ assert!(parse_conn_flags("!username, username").is_none());
+ assert!(parse_conn_flags("!username,password,!password").is_none());
+ assert!(parse_conn_flags("will, username,password, !will, will").is_none());
+ }
+
+ #[test]
+ fn mqtt_type_test_parse() {
+ let ctx = detect_parse_uint_enum::<u8, MQTTTypeCode>("CONNECT").unwrap();
+ assert_eq!(ctx.arg1, 1);
+ assert_eq!(ctx.mode, DetectUintMode::DetectUintModeEqual);
+ let ctx = detect_parse_uint_enum::<u8, MQTTTypeCode>("PINGRESP").unwrap();
+ assert_eq!(ctx.arg1, 13);
+ assert_eq!(ctx.mode, DetectUintMode::DetectUintModeEqual);
+ let ctx = detect_parse_uint_enum::<u8, MQTTTypeCode>("auth").unwrap();
+ assert_eq!(ctx.arg1, 15);
+ assert_eq!(ctx.mode, DetectUintMode::DetectUintModeEqual);
+ assert!(detect_parse_uint_enum::<u8, MQTTTypeCode>("invalidopt").is_none());
+ let ctx = detect_parse_uint_enum::<u8, MQTTTypeCode>("unassigned").unwrap();
+ assert_eq!(ctx.arg1, 0);
+ assert_eq!(ctx.mode, DetectUintMode::DetectUintModeEqual);
+ }
+
#[test]
fn test_multi_unsubscribe() {
let mut t = MQTTTransaction::new(
});
let mut s: *const u8 = std::ptr::null_mut();
let mut slen: u32 = 0;
- let mut r = unsafe { rs_mqtt_tx_get_unsubscribe_topic(&t, 0, &mut s, &mut slen) };
- assert_eq!(r, 1);
+ let tx = &t as *const _ as *mut _;
+ let mut r = unsafe { unsub_topic_get_data(tx, 0, 0, &mut s, &mut slen) };
+ assert!(r);
let mut topic = String::from_utf8_lossy(unsafe { build_slice!(s, slen as usize) });
assert_eq!(topic, "foo");
- r = unsafe { rs_mqtt_tx_get_unsubscribe_topic(&t, 1, &mut s, &mut slen) };
- assert_eq!(r, 1);
+ r = unsafe { unsub_topic_get_data(tx, 0, 1, &mut s, &mut slen) };
+ assert!(r);
topic = String::from_utf8_lossy(unsafe { build_slice!(s, slen as usize) });
assert_eq!(topic, "baar");
- r = unsafe { rs_mqtt_tx_get_unsubscribe_topic(&t, 2, &mut s, &mut slen) };
- assert_eq!(r, 1);
+ r = unsafe { unsub_topic_get_data(tx, 0, 2, &mut s, &mut slen) };
+ assert!(r);
topic = String::from_utf8_lossy(unsafe { build_slice!(s, slen as usize) });
assert_eq!(topic, "fieee");
- r = unsafe { rs_mqtt_tx_get_unsubscribe_topic(&t, 3, &mut s, &mut slen) };
- assert_eq!(r, 1);
+ r = unsafe { unsub_topic_get_data(tx, 0, 3, &mut s, &mut slen) };
+ assert!(r);
topic = String::from_utf8_lossy(unsafe { build_slice!(s, slen as usize) });
assert_eq!(topic, "baaaaz");
- r = unsafe { rs_mqtt_tx_get_unsubscribe_topic(&t, 4, &mut s, &mut slen) };
- assert_eq!(r, 0);
+ r = unsafe { unsub_topic_get_data(tx, 0, 4, &mut s, &mut slen) };
+ assert!(!r);
}
#[test]
});
let mut s: *const u8 = std::ptr::null_mut();
let mut slen: u32 = 0;
- let mut r = unsafe { rs_mqtt_tx_get_subscribe_topic(&t, 0, &mut s, &mut slen) };
- assert_eq!(r, 1);
+ let tx = &t as *const _ as *mut _;
+ let mut r = unsafe { sub_topic_get_data(tx, 0, 0, &mut s, &mut slen) };
+ assert!(r);
let mut topic = String::from_utf8_lossy(unsafe { build_slice!(s, slen as usize) });
assert_eq!(topic, "foo");
- r = unsafe { rs_mqtt_tx_get_subscribe_topic(&t, 1, &mut s, &mut slen) };
- assert_eq!(r, 1);
+ r = unsafe { sub_topic_get_data(tx, 0, 1, &mut s, &mut slen) };
+ assert!(r);
topic = String::from_utf8_lossy(unsafe { build_slice!(s, slen as usize) });
assert_eq!(topic, "baar");
- r = unsafe { rs_mqtt_tx_get_subscribe_topic(&t, 2, &mut s, &mut slen) };
- assert_eq!(r, 1);
+ r = unsafe { sub_topic_get_data(tx, 0, 2, &mut s, &mut slen) };
+ assert!(r);
topic = String::from_utf8_lossy(unsafe { build_slice!(s, slen as usize) });
assert_eq!(topic, "fieee");
- r = unsafe { rs_mqtt_tx_get_subscribe_topic(&t, 3, &mut s, &mut slen) };
- assert_eq!(r, 1);
+ r = unsafe { sub_topic_get_data(tx, 0, 3, &mut s, &mut slen) };
+ assert!(r);
topic = String::from_utf8_lossy(unsafe { build_slice!(s, slen as usize) });
assert_eq!(topic, "baaaaz");
- r = unsafe { rs_mqtt_tx_get_subscribe_topic(&t, 4, &mut s, &mut slen) };
- assert_eq!(r, 0);
+ r = unsafe { sub_topic_get_data(tx, 0, 4, &mut s, &mut slen) };
+ assert!(!r);
}
}
static mut MQTT_MAX_TX: usize = 1024;
-static mut ALPROTO_MQTT: AppProto = ALPROTO_UNKNOWN;
+pub(super) static mut ALPROTO_MQTT: AppProto = ALPROTO_UNKNOWN;
#[derive(AppLayerFrameType)]
pub enum MQTTFrameType {
#[no_mangle]
pub unsafe extern "C" fn rs_mqtt_tx_is_toclient(
- tx: *const std::os::raw::c_void,
+ tx: &MQTTTransaction,
) -> std::os::raw::c_int {
- let tx = cast_pointer!(tx, MQTTTransaction);
if tx.toclient {
return 1;
}
use crate::mqtt::mqtt_property::*;
use crate::mqtt::parser::*;
use std::fmt;
+use suricata_derive::EnumStringU8;
#[derive(Debug)]
pub struct MQTTMessage {
}
#[repr(u8)]
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, FromPrimitive, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, FromPrimitive, Debug, EnumStringU8)]
pub enum MQTTTypeCode {
UNASSIGNED = 0,
CONNECT = 1,
}
}
-impl std::str::FromStr for MQTTTypeCode {
- type Err = String;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- let su = s.to_uppercase();
- let su_slice: &str = &su;
- match su_slice {
- "CONNECT" => Ok(MQTTTypeCode::CONNECT),
- "CONNACK" => Ok(MQTTTypeCode::CONNACK),
- "PUBLISH" => Ok(MQTTTypeCode::PUBLISH),
- "PUBACK" => Ok(MQTTTypeCode::PUBACK),
- "PUBREC" => Ok(MQTTTypeCode::PUBREC),
- "PUBREL" => Ok(MQTTTypeCode::PUBREL),
- "PUBCOMP" => Ok(MQTTTypeCode::PUBCOMP),
- "SUBSCRIBE" => Ok(MQTTTypeCode::SUBSCRIBE),
- "SUBACK" => Ok(MQTTTypeCode::SUBACK),
- "UNSUBSCRIBE" => Ok(MQTTTypeCode::UNSUBSCRIBE),
- "UNSUBACK" => Ok(MQTTTypeCode::UNSUBACK),
- "PINGREQ" => Ok(MQTTTypeCode::PINGREQ),
- "PINGRESP" => Ok(MQTTTypeCode::PINGRESP),
- "DISCONNECT" => Ok(MQTTTypeCode::DISCONNECT),
- "AUTH" => Ok(MQTTTypeCode::AUTH),
- _ => Err(format!("'{}' is not a valid value for MQTTTypeCode", s)),
- }
- }
-}
-
#[derive(Debug)]
pub struct MQTTConnectData {
pub protocol_string: String,
detect-quic-version.h \
detect-quic-cyu-hash.h \
detect-quic-cyu-string.h \
- detect-mqtt-connack-sessionpresent.h \
- detect-mqtt-connect-clientid.h \
- detect-mqtt-connect-flags.h \
- detect-mqtt-connect-password.h \
- detect-mqtt-connect-protocol-string.h \
- detect-mqtt-connect-username.h \
- detect-mqtt-connect-willmessage.h \
- detect-mqtt-connect-willtopic.h \
- detect-mqtt-flags.h \
- detect-mqtt-protocol-version.h \
- detect-mqtt-publish-message.h \
- detect-mqtt-publish-topic.h \
- detect-mqtt-qos.h \
- detect-mqtt-reason-code.h \
- detect-mqtt-subscribe-topic.h \
- detect-mqtt-type.h \
- detect-mqtt-unsubscribe-topic.h \
detect-msg.h \
detect-nfs-procedure.h \
detect-nfs-version.h \
detect-quic-version.c \
detect-quic-cyu-hash.c \
detect-quic-cyu-string.c \
- detect-mqtt-connack-sessionpresent.c \
- detect-mqtt-connect-clientid.c \
- detect-mqtt-connect-flags.c \
- detect-mqtt-connect-password.c \
- detect-mqtt-connect-protocol-string.c \
- detect-mqtt-connect-username.c \
- detect-mqtt-connect-willmessage.c \
- detect-mqtt-connect-willtopic.c \
- detect-mqtt-flags.c \
- detect-mqtt-protocol-version.c \
- detect-mqtt-publish-message.c \
- detect-mqtt-publish-topic.c \
- detect-mqtt-qos.c \
- detect-mqtt-reason-code.c \
- detect-mqtt-subscribe-topic.c \
- detect-mqtt-type.c \
- detect-mqtt-unsubscribe-topic.c \
detect-msg.c \
detect-nfs-procedure.c \
detect-nfs-version.c \
#include "detect-rfb-name.h"
#include "detect-target.h"
#include "detect-template-rust-buffer.h"
-#include "detect-mqtt-type.h"
-#include "detect-mqtt-flags.h"
-#include "detect-mqtt-qos.h"
-#include "detect-mqtt-protocol-version.h"
-#include "detect-mqtt-reason-code.h"
-#include "detect-mqtt-connect-flags.h"
-#include "detect-mqtt-connect-clientid.h"
-#include "detect-mqtt-connect-username.h"
-#include "detect-mqtt-connect-password.h"
-#include "detect-mqtt-connect-protocol-string.h"
-#include "detect-mqtt-connect-willtopic.h"
-#include "detect-mqtt-connect-willmessage.h"
-#include "detect-mqtt-connack-sessionpresent.h"
-#include "detect-mqtt-publish-topic.h"
-#include "detect-mqtt-publish-message.h"
-#include "detect-mqtt-subscribe-topic.h"
-#include "detect-mqtt-unsubscribe-topic.h"
#include "detect-quic-sni.h"
#include "detect-quic-ua.h"
#include "detect-quic-version.h"
DetectRfbNameRegister();
DetectTargetRegister();
DetectTemplateRustBufferRegister();
- DetectMQTTTypeRegister();
- DetectMQTTFlagsRegister();
- DetectMQTTQosRegister();
- DetectMQTTProtocolVersionRegister();
- DetectMQTTReasonCodeRegister();
- DetectMQTTConnectFlagsRegister();
- DetectMQTTConnectClientIDRegister();
- DetectMQTTConnectUsernameRegister();
- DetectMQTTConnectPasswordRegister();
- DetectMQTTConnectProtocolStringRegister();
- DetectMQTTConnectWillTopicRegister();
- DetectMQTTConnectWillMessageRegister();
- DetectMQTTConnackSessionPresentRegister();
- DetectMQTTPublishTopicRegister();
- DetectMQTTPublishMessageRegister();
- DetectMQTTSubscribeTopicRegister();
- DetectMQTTUnsubscribeTopicRegister();
DetectQuicSniRegister();
DetectQuicUaRegister();
DetectQuicVersionRegister();
ScDetectDHCPRegister();
ScDetectWebsocketRegister();
ScDetectEnipRegister();
+ ScDetectMqttRegister();
/* close keyword registration */
DetectBufferTypeCloseRegistration();
DETECT_FTPDATA,
DETECT_TARGET,
DETECT_AL_TEMPLATE_BUFFER,
- DETECT_AL_MQTT_TYPE,
- DETECT_AL_MQTT_FLAGS,
- DETECT_AL_MQTT_QOS,
- DETECT_AL_MQTT_PROTOCOL_VERSION,
- DETECT_AL_MQTT_REASON_CODE,
- DETECT_AL_MQTT_CONNECT_FLAGS,
- DETECT_AL_MQTT_CONNECT_CLIENTID,
- DETECT_AL_MQTT_CONNECT_USERNAME,
- DETECT_AL_MQTT_CONNECT_PASSWORD,
- DETECT_AL_MQTT_CONNECT_PROTOCOL_STRING,
- DETECT_AL_MQTT_CONNECT_WILLTOPIC,
- DETECT_AL_MQTT_CONNECT_WILLMESSAGE,
- DETECT_AL_MQTT_CONNACK_SESSION_PRESENT,
- DETECT_AL_MQTT_PUBLISH_TOPIC,
- DETECT_AL_MQTT_PUBLISH_MESSAGE,
- DETECT_AL_MQTT_SUBSCRIBE_TOPIC,
- DETECT_AL_MQTT_UNSUBSCRIBE_TOPIC,
DETECT_AL_QUIC_VERSION,
DETECT_AL_QUIC_SNI,
DETECT_AL_QUIC_UA,
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-#include "conf.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-mqtt-connack-sessionpresent.h"
-#include "util-unittest.h"
-
-#include "rust.h"
-
-#define PARSE_REGEX "^true|false|yes|no$"
-static DetectParseRegex parse_regex;
-
-static int mqtt_connack_session_present_id = 0;
-
-static int DetectMQTTConnackSessionPresentMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx);
-static int DetectMQTTConnackSessionPresentSetup (DetectEngineCtx *, Signature *, const char *);
-void MQTTConnackSessionPresentRegisterTests(void);
-void DetectMQTTConnackSessionPresentFree(DetectEngineCtx *de_ctx, void *);
-
-/**
- * \brief Registration function for mqtt.connack.session_present: keyword
- */
-void DetectMQTTConnackSessionPresentRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_CONNACK_SESSION_PRESENT].name = "mqtt.connack.session_present";
- sigmatch_table[DETECT_AL_MQTT_CONNACK_SESSION_PRESENT].desc = "match MQTT CONNACK session present flag";
- sigmatch_table[DETECT_AL_MQTT_CONNACK_SESSION_PRESENT].url = "/rules/mqtt-keywords.html#mqtt-connack-session-present";
- sigmatch_table[DETECT_AL_MQTT_CONNACK_SESSION_PRESENT].AppLayerTxMatch = DetectMQTTConnackSessionPresentMatch;
- sigmatch_table[DETECT_AL_MQTT_CONNACK_SESSION_PRESENT].Setup = DetectMQTTConnackSessionPresentSetup;
- sigmatch_table[DETECT_AL_MQTT_CONNACK_SESSION_PRESENT].Free = DetectMQTTConnackSessionPresentFree;
-#ifdef UNITTESTS
- sigmatch_table[DETECT_AL_MQTT_CONNACK_SESSION_PRESENT].RegisterTests = MQTTConnackSessionPresentRegisterTests;
-#endif
-
- DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
-
- DetectAppLayerInspectEngineRegister("mqtt.connack.session_present", ALPROTO_MQTT,
- SIG_FLAG_TOSERVER, 1, DetectEngineInspectGenericList, NULL);
-
- mqtt_connack_session_present_id = DetectBufferTypeGetByName("mqtt.connack.session_present");
-}
-
-/**
- * \internal
- * \brief Function to match session_present flag of an MQTT CONNACK message
- *
- * \param det_ctx Pointer to the pattern matcher thread.
- * \param f Pointer to the current flow.
- * \param flags Flags.
- * \param state App layer state.
- * \param txv Pointer to the transaction.
- * \param s Pointer to the Signature.
- * \param ctx Pointer to the sigmatch that we will cast into DetectMQTTConnackSessionPresentData.
- *
- * \retval 0 no match.
- * \retval 1 match.
- */
-static int DetectMQTTConnackSessionPresentMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx)
-{
- const bool *de = (const bool *)ctx;
- bool value = false;
-
- if (!de)
- return 0;
-
- if (rs_mqtt_tx_get_connack_sessionpresent(txv, &value) ==0 ) {
- return 0;
- }
- if (value != *de) {
- return 0;
- }
-
- return 1;
-}
-
-/**
- * \internal
- * \brief This function is used to parse options passed via mqtt.connack.session_present: keyword
- *
- * \param rawstr Pointer to the user provided options
- *
- * \retval de pointer to DetectMQTTConnackSessionPresentData on success
- * \retval NULL on failure
- */
-static bool *DetectMQTTConnackSessionPresentParse(const char *rawstr)
-{
- bool *de = NULL;
- de = SCMalloc(sizeof(bool));
- if (unlikely(de == NULL))
- return NULL;
- *de = false;
-
- if (strcmp(rawstr, "yes") == 0) {
- *de = true;
- } else if (strcmp(rawstr, "true") == 0) {
- *de = true;
- } else if (strcmp(rawstr, "no") == 0) {
- *de = false;
- } else if (strcmp(rawstr, "false") == 0) {
- *de = false;
- } else {
- SCLogError("invalid session_present flag definition: %s", rawstr);
- goto error;
- }
-
- return de;
-
-error:
- /* de can't be NULL here */
- SCFree(de);
- return NULL;
-}
-
-/**
- * \internal
- * \brief this function is used to add the parsed type query into the current signature
- *
- * \param de_ctx pointer to the Detection Engine Context
- * \param s pointer to the Current Signature
- * \param rawstr pointer to the user provided options
- *
- * \retval 0 on Success
- * \retval -1 on Failure
- */
-static int DetectMQTTConnackSessionPresentSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
-{
- bool *de = NULL;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- de = DetectMQTTConnackSessionPresentParse(rawstr);
- if (de == NULL)
- goto error;
-
- if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_MQTT_CONNACK_SESSION_PRESENT, (SigMatchCtx *)de,
- mqtt_connack_session_present_id) == NULL) {
- goto error;
- }
-
- return 0;
-
-error:
- if (de != NULL)
- SCFree(de);
- return -1;
-}
-
-/**
- * \internal
- * \brief this function will free memory associated with DetectMQTTConnackSessionPresentData
- *
- * \param de pointer to DetectMQTTConnackSessionPresentData
- */
-void DetectMQTTConnackSessionPresentFree(DetectEngineCtx *de_ctx, void *de_ptr)
-{
- if (de_ptr != NULL)
- SCFree(de_ptr);
-}
-
-/*
- * ONLY TESTS BELOW THIS COMMENT
- */
-
-#ifdef UNITTESTS
-/**
- * \test MQTTConnackSessionPresentTestParse01 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnackSessionPresentTestParse01 (void)
-{
- bool *de = NULL;
-
- de = DetectMQTTConnackSessionPresentParse("yes");
- FAIL_IF_NULL(de);
- DetectMQTTConnackSessionPresentFree(NULL, de);
-
- de = DetectMQTTConnackSessionPresentParse("true");
- FAIL_IF_NULL(de);
- DetectMQTTConnackSessionPresentFree(NULL, de);
-
- de = DetectMQTTConnackSessionPresentParse("false");
- FAIL_IF_NULL(de);
- DetectMQTTConnackSessionPresentFree(NULL, de);
-
- de = DetectMQTTConnackSessionPresentParse("no");
- FAIL_IF_NULL(de);
- DetectMQTTConnackSessionPresentFree(NULL, de);
-
- PASS;
-}
-
-/**
- * \test MQTTConnackSessionPresentTestParse02 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnackSessionPresentTestParse02 (void)
-{
- bool *de = NULL;
- de = DetectMQTTConnackSessionPresentParse("nix");
- if (de) {
- DetectMQTTConnackSessionPresentFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTConnackSessionPresentTestParse03 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnackSessionPresentTestParse03 (void)
-{
- bool *de = NULL;
- de = DetectMQTTConnackSessionPresentParse("");
- if (de) {
- DetectMQTTConnackSessionPresentFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTConnackSessionPresentTestParse04 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnackSessionPresentTestParse04 (void)
-{
- bool *de = NULL;
- de = DetectMQTTConnackSessionPresentParse(",");
- if (de) {
- DetectMQTTConnackSessionPresentFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-
-#endif /* UNITTESTS */
-
-/**
- * \brief this function registers unit tests for MQTTConnackSessionPresent
- */
-void MQTTConnackSessionPresentRegisterTests(void)
-{
-#ifdef UNITTESTS
- UtRegisterTest("MQTTConnackSessionPresentTestParse01", MQTTConnackSessionPresentTestParse01);
- UtRegisterTest("MQTTConnackSessionPresentTestParse02", MQTTConnackSessionPresentTestParse02);
- UtRegisterTest("MQTTConnackSessionPresentTestParse03", MQTTConnackSessionPresentTestParse03);
- UtRegisterTest("MQTTConnackSessionPresentTestParse04", MQTTConnackSessionPresentTestParse04);
-#endif /* UNITTESTS */
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_CONNACK_SESSIONPRESENT_H
-#define SURICATA_DETECT_MQTT_CONNACK_SESSIONPRESENT_H
-
-void DetectMQTTConnackSessionPresentRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_CONNACK_SESSIONPRESENT_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- *
- * Implements the mqtt.connect.clientid sticky buffer
- */
-
-#include "suricata-common.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-connect-clientid.h"
-#include "rust.h"
-
-#define KEYWORD_NAME "mqtt.connect.clientid"
-#define KEYWORD_DOC "mqtt-keywords.html#mqtt-connect-clientid"
-#define BUFFER_NAME "mqtt.connect.clientid"
-#define BUFFER_DESC "MQTT CONNECT client ID"
-static int g_buffer_id = 0;
-
-static int DetectMQTTConnectClientIDSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
- return -1;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- return 0;
-}
-
-static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms,
- Flow *_f, const uint8_t _flow_flags,
- void *txv, const int list_id)
-{
- InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
- if (buffer->inspect == NULL) {
- const uint8_t *b = NULL;
- uint32_t b_len = 0;
-
- if (rs_mqtt_tx_get_connect_clientid(txv, &b, &b_len) != 1)
- return NULL;
- if (b == NULL || b_len == 0)
- return NULL;
-
- InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
- InspectionBufferApplyTransforms(buffer, transforms);
- }
- return buffer;
-}
-
-void DetectMQTTConnectClientIDRegister(void)
-{
- /* mqtt.connect.clientid sticky buffer */
- sigmatch_table[DETECT_AL_MQTT_CONNECT_CLIENTID].name = KEYWORD_NAME;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_CLIENTID].desc = "sticky buffer to match on the MQTT CONNECT client ID";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_CLIENTID].url = "/rules/" KEYWORD_DOC;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_CLIENTID].Setup = DetectMQTTConnectClientIDSetup;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_CLIENTID].flags |= SIGMATCH_NOOPT;
-
- DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_MQTT, SIG_FLAG_TOSERVER, 0,
- DetectEngineInspectBufferGeneric, GetData);
-
- DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
- GetData, ALPROTO_MQTT, 1);
-
- DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
-
- g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
-
- SCLogDebug("registering " BUFFER_NAME " rule option");
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_CONNECT_CLIENTID_H
-#define SURICATA_DETECT_MQTT_CONNECT_CLIENTID_H
-
-void DetectMQTTConnectClientIDRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_CONNECT_CLIENTID_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-#include "conf.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-mqtt-connect-flags.h"
-#include "util-unittest.h"
-
-#include "rust.h"
-
-#define PARSE_REGEX "(?: *,?!?(?:username|password|will|will_retain|clean_session))+"
-static DetectParseRegex parse_regex;
-
-static int mqtt_connect_flags_id = 0;
-
-static int DetectMQTTConnectFlagsMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx);
-static int DetectMQTTConnectFlagsSetup (DetectEngineCtx *, Signature *, const char *);
-void MQTTConnectFlagsRegisterTests(void);
-void DetectMQTTConnectFlagsFree(DetectEngineCtx *de_ctx, void *);
-
-typedef struct DetectMQTTConnectFlagsData_ {
- MQTTFlagState username,
- password,
- will,
- will_retain,
- clean_session;
-} DetectMQTTConnectFlagsData;
-
-/**
- * \brief Registration function for mqtt.connect.flags: keyword
- */
-void DetectMQTTConnectFlagsRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_CONNECT_FLAGS].name = "mqtt.connect.flags";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_FLAGS].desc = "match MQTT CONNECT variable header flags";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_FLAGS].url = "/rules/mqtt-keywords.html#mqtt-connect-flags";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_FLAGS].AppLayerTxMatch = DetectMQTTConnectFlagsMatch;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_FLAGS].Setup = DetectMQTTConnectFlagsSetup;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_FLAGS].Free = DetectMQTTConnectFlagsFree;
-#ifdef UNITTESTS
- sigmatch_table[DETECT_AL_MQTT_CONNECT_FLAGS].RegisterTests = MQTTConnectFlagsRegisterTests;
-#endif
-
- DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
-
- DetectAppLayerInspectEngineRegister("mqtt.connect.flags", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
- DetectEngineInspectGenericList, NULL);
-
- mqtt_connect_flags_id = DetectBufferTypeGetByName("mqtt.connect.flags");
-}
-
-/**
- * \internal
- * \brief Function to match variable header flags of an MQTT CONNECT Tx
- *
- * \param det_ctx Pointer to the pattern matcher thread.
- * \param f Pointer to the current flow.
- * \param flags Flags.
- * \param state App layer state.
- * \param txv Pointer to the transaction.
- * \param s Pointer to the Signature.
- * \param ctx Pointer to the sigmatch that we will cast into DetectMQTTConnectFlagsData.
- *
- * \retval 0 no match.
- * \retval 1 match.
- */
-static int DetectMQTTConnectFlagsMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx)
-{
- const DetectMQTTConnectFlagsData *de = (const DetectMQTTConnectFlagsData *)ctx;
-
- if (!de)
- return 0;
-
- return rs_mqtt_tx_has_connect_flags(txv, de->username, de->password, de->will,
- de->will_retain, de->clean_session);
- }
-
-/**
- * \internal
- * \brief This function is used to parse options passed via mqtt.connect.flags: keyword
- *
- * \param rawstr Pointer to the user provided options
- *
- * \retval de pointer to DetectMQTTConnectFlagsData on success
- * \retval NULL on failure
- */
-static DetectMQTTConnectFlagsData *DetectMQTTConnectFlagsParse(const char *rawstr)
-{
- char copy[strlen(rawstr) + 1];
-
- DetectMQTTConnectFlagsData *de = SCCalloc(1, sizeof(DetectMQTTConnectFlagsData));
- if (unlikely(de == NULL))
- return NULL;
-
- pcre2_match_data *match = NULL;
- int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
- if (ret < 1) {
- SCLogError("invalid flag definition: %s", rawstr);
- goto error;
- }
-
- de->username = de->password = de->will = MQTT_DONT_CARE;
- de->will_retain = de->clean_session = MQTT_DONT_CARE;
-
- strlcpy(copy, rawstr, sizeof(copy));
- char *xsaveptr = NULL;
- char *flagv = strtok_r(copy, ",", &xsaveptr);
- while (flagv != NULL) {
- while (*flagv != '\0' && isblank(*flagv)) {
- flagv++;
- }
- if (strlen(flagv) < 2) {
- SCLogError("malformed flag value: %s", flagv);
- goto error;
- } else {
- int offset = 0;
- MQTTFlagState fs_to_set = MQTT_MUST_BE_SET;
- if (flagv[0] == '!') {
- /* negated flag */
- offset = 1; /* skip negation operator during comparison */
- fs_to_set = MQTT_CANT_BE_SET;
- }
- if (strcmp(flagv+offset, "username") == 0) {
- if (de->username != MQTT_DONT_CARE) {
- SCLogError("duplicate flag definition: %s", flagv);
- goto error;
- }
- de->username = fs_to_set;
- } else if (strcmp(flagv+offset, "password") == 0) {
- if (de->password != MQTT_DONT_CARE) {
- SCLogError("duplicate flag definition: %s", flagv);
- goto error;
- }
- de->password = fs_to_set;
- } else if (strcmp(flagv+offset, "will") == 0) {
- if (de->will != MQTT_DONT_CARE) {
- SCLogError("duplicate flag definition: %s", flagv);
- goto error;
- }
- de->will = fs_to_set;
- } else if (strcmp(flagv+offset, "will_retain") == 0) {
- if (de->will_retain != MQTT_DONT_CARE) {
- SCLogError("duplicate flag definition: %s", flagv);
- goto error;
- }
- de->will_retain = fs_to_set;
- } else if (strcmp(flagv+offset, "clean_session") == 0) {
- if (de->clean_session != MQTT_DONT_CARE) {
- SCLogError("duplicate flag definition: %s", flagv);
- goto error;
- }
- de->clean_session = fs_to_set;
- } else {
- SCLogError("invalid flag definition: %s", flagv);
- goto error;
- }
- }
- flagv = strtok_r(NULL, ",", &xsaveptr);
- }
-
- pcre2_match_data_free(match);
- return de;
-
-error:
- if (match) {
- pcre2_match_data_free(match);
- }
- if (de)
- SCFree(de);
- return NULL;
-}
-
-/**
- * \internal
- * \brief this function is used to add the parsed type query into the current signature
- *
- * \param de_ctx pointer to the Detection Engine Context
- * \param s pointer to the Current Signature
- * \param rawstr pointer to the user provided options
- *
- * \retval 0 on Success
- * \retval -1 on Failure
- */
-static int DetectMQTTConnectFlagsSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
-{
- DetectMQTTConnectFlagsData *de = NULL;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- de = DetectMQTTConnectFlagsParse(rawstr);
- if (de == NULL)
- goto error;
-
- if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_MQTT_CONNECT_FLAGS, (SigMatchCtx *)de,
- mqtt_connect_flags_id) == NULL) {
- goto error;
- }
-
- return 0;
-
-error:
- if (de != NULL)
- SCFree(de);
- return -1;
-}
-
-/**
- * \internal
- * \brief this function will free memory associated with DetectMQTTConnectFlagsData
- *
- * \param de pointer to DetectMQTTConnectFlagsData
- */
-void DetectMQTTConnectFlagsFree(DetectEngineCtx *de_ctx, void *de_ptr)
-{
- if (de_ptr != NULL)
- SCFree(de_ptr);
-}
-
-/*
- * ONLY TESTS BELOW THIS COMMENT
- */
-
-#ifdef UNITTESTS
-/**
- * \test MQTTConnectFlagsTestParse01 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnectFlagsTestParse01 (void)
-{
- DetectMQTTConnectFlagsData *de = NULL;
- de = DetectMQTTConnectFlagsParse("username");
- FAIL_IF_NULL(de);
- DetectMQTTConnectFlagsFree(NULL, de);
-
- de = DetectMQTTConnectFlagsParse("username,password,will,will_retain,clean_session");
- FAIL_IF_NULL(de);
- DetectMQTTConnectFlagsFree(NULL, de);
-
- de = DetectMQTTConnectFlagsParse("!username,!password,!will,!will_retain,!clean_session");
- FAIL_IF_NULL(de);
- DetectMQTTConnectFlagsFree(NULL, de);
-
- de = DetectMQTTConnectFlagsParse(" username,password");
- FAIL_IF_NULL(de);
- DetectMQTTConnectFlagsFree(NULL, de);
-
- PASS;
-}
-
-/**
- * \test MQTTConnectFlagsTestParse02 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnectFlagsTestParse02 (void)
-{
- DetectMQTTConnectFlagsData *de = NULL;
- de = DetectMQTTConnectFlagsParse("foobar");
- if (de) {
- DetectMQTTConnectFlagsFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTConnectFlagsTestParse03 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnectFlagsTestParse03 (void)
-{
- DetectMQTTConnectFlagsData *de = NULL;
- de = DetectMQTTConnectFlagsParse("will,!");
- if (de) {
- DetectMQTTConnectFlagsFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTConnectFlagsTestParse04 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnectFlagsTestParse04 (void)
-{
- DetectMQTTConnectFlagsData *de = NULL;
- de = DetectMQTTConnectFlagsParse("");
- if (de) {
- DetectMQTTConnectFlagsFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTConnectFlagsTestParse05 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTConnectFlagsTestParse05 (void)
-{
- DetectMQTTConnectFlagsData *de = NULL;
- de = DetectMQTTConnectFlagsParse("username, username");
- if (de) {
- DetectMQTTConnectFlagsFree(NULL, de);
- FAIL;
- }
- de = DetectMQTTConnectFlagsParse("!username, username");
- if (de) {
- DetectMQTTConnectFlagsFree(NULL, de);
- FAIL;
- }
- de = DetectMQTTConnectFlagsParse("!username,password,!password");
- if (de) {
- DetectMQTTConnectFlagsFree(NULL, de);
- FAIL;
- }
- de = DetectMQTTConnectFlagsParse("will, username,password, !will, will");
- if (de) {
- DetectMQTTConnectFlagsFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-
-#endif /* UNITTESTS */
-
-/**
- * \brief this function registers unit tests for MQTTConnectFlags
- */
-void MQTTConnectFlagsRegisterTests(void)
-{
-#ifdef UNITTESTS
- UtRegisterTest("MQTTConnectFlagsTestParse01", MQTTConnectFlagsTestParse01);
- UtRegisterTest("MQTTConnectFlagsTestParse02", MQTTConnectFlagsTestParse02);
- UtRegisterTest("MQTTConnectFlagsTestParse03", MQTTConnectFlagsTestParse03);
- UtRegisterTest("MQTTConnectFlagsTestParse04", MQTTConnectFlagsTestParse04);
- UtRegisterTest("MQTTConnectFlagsTestParse05", MQTTConnectFlagsTestParse05);
-#endif /* UNITTESTS */
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_CONNECT_FLAGS_H
-#define SURICATA_DETECT_MQTT_CONNECT_FLAGS_H
-
-void DetectMQTTConnectFlagsRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_CONNECT_FLAGS_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- *
- * Implements the mqtt.connect.password sticky buffer
- */
-
-#include "suricata-common.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-connect-password.h"
-#include "rust.h"
-
-#define KEYWORD_NAME "mqtt.connect.password"
-#define KEYWORD_DOC "mqtt-keywords.html#mqtt-connect-password"
-#define BUFFER_NAME "mqtt.connect.password"
-#define BUFFER_DESC "MQTT CONNECT password"
-static int g_buffer_id = 0;
-
-static int DetectMQTTConnectPasswordSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
- return -1;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- return 0;
-}
-
-static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms,
- Flow *_f, const uint8_t _flow_flags,
- void *txv, const int list_id)
-{
- InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
- if (buffer->inspect == NULL) {
- const uint8_t *b = NULL;
- uint32_t b_len = 0;
-
- if (rs_mqtt_tx_get_connect_password(txv, &b, &b_len) != 1)
- return NULL;
- if (b == NULL || b_len == 0)
- return NULL;
-
- InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
- InspectionBufferApplyTransforms(buffer, transforms);
- }
- return buffer;
-}
-
-void DetectMQTTConnectPasswordRegister(void)
-{
- /* mqtt.connect.password sticky buffer */
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PASSWORD].name = KEYWORD_NAME;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PASSWORD].desc = "sticky buffer to match on the MQTT CONNECT password";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PASSWORD].url = "/rules/" KEYWORD_DOC;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PASSWORD].Setup = DetectMQTTConnectPasswordSetup;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PASSWORD].flags |= SIGMATCH_NOOPT;
-
- DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_MQTT, SIG_FLAG_TOSERVER, 0,
- DetectEngineInspectBufferGeneric, GetData);
-
- DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
- GetData, ALPROTO_MQTT, 1);
-
- DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
-
- g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
-
- SCLogDebug("registering " BUFFER_NAME " rule option");
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_CONNECT_PASSWORD_H
-#define SURICATA_DETECT_MQTT_CONNECT_PASSWORD_H
-
-void DetectMQTTConnectPasswordRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_CONNECT_PASSWORD_H */
+++ /dev/null
-/* Copyright (C) 2023 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.
- */
-
-/**
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- *
- * Implements the mqtt.connect.protocolstring sticky buffer
- */
-
-#include "suricata-common.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-connect-protocol-string.h"
-#include "rust.h"
-
-#define KEYWORD_NAME "mqtt.connect.protocol_string"
-#define KEYWORD_DOC "mqtt-keywords.html#mqtt-connect-protocol_string"
-#define BUFFER_NAME "mqtt.connect.protocol_string"
-#define BUFFER_DESC "MQTT CONNECT protocol string"
-static int g_buffer_id = 0;
-
-static int DetectMQTTConnectProtocolStringSetup(
- DetectEngineCtx *de_ctx, Signature *s, const char *arg)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
- return -1;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- return 0;
-}
-
-static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv,
- const int list_id)
-{
- InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
- if (buffer->inspect == NULL) {
- const uint8_t *b = NULL;
- uint32_t b_len = 0;
-
- if (rs_mqtt_tx_get_connect_protocol_string(txv, &b, &b_len) != 1)
- return NULL;
- if (b == NULL || b_len == 0)
- return NULL;
-
- InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
- InspectionBufferApplyTransforms(buffer, transforms);
- }
- return buffer;
-}
-
-void DetectMQTTConnectProtocolStringRegister(void)
-{
- /* mqtt.connect.protocol_string sticky buffer */
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PROTOCOL_STRING].name = KEYWORD_NAME;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PROTOCOL_STRING].desc =
- "sticky buffer to match on the MQTT CONNECT protocol string";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PROTOCOL_STRING].url = "/rules/" KEYWORD_DOC;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PROTOCOL_STRING].Setup =
- DetectMQTTConnectProtocolStringSetup;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_PROTOCOL_STRING].flags |= SIGMATCH_NOOPT;
-
- DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_MQTT, SIG_FLAG_TOSERVER, 0,
- DetectEngineInspectBufferGeneric, GetData);
-
- DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
- GetData, ALPROTO_MQTT, 1);
-
- DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
-
- g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
-
- SCLogDebug("registering " BUFFER_NAME " rule option");
-}
+++ /dev/null
-/* Copyright (C) 2023 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_CONNECT_PROTOCOLSTRING_H
-#define SURICATA_DETECT_MQTT_CONNECT_PROTOCOLSTRING_H
-
-void DetectMQTTConnectProtocolStringRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_CONNECT_PROTOCOLSTRING_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- *
- * Implements the mqtt.connect.username sticky buffer
- */
-
-#include "suricata-common.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-connect-username.h"
-#include "rust.h"
-
-#define KEYWORD_NAME "mqtt.connect.username"
-#define KEYWORD_DOC "mqtt-keywords.html#mqtt-connect-username"
-#define BUFFER_NAME "mqtt.connect.username"
-#define BUFFER_DESC "MQTT CONNECT username"
-static int g_buffer_id = 0;
-
-static int DetectMQTTConnectUsernameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
- return -1;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- return 0;
-}
-
-static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms,
- Flow *_f, const uint8_t _flow_flags,
- void *txv, const int list_id)
-{
- InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
- if (buffer->inspect == NULL) {
- const uint8_t *b = NULL;
- uint32_t b_len = 0;
-
- if (rs_mqtt_tx_get_connect_username(txv, &b, &b_len) != 1)
- return NULL;
- if (b == NULL || b_len == 0)
- return NULL;
-
- InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
- InspectionBufferApplyTransforms(buffer, transforms);
- }
- return buffer;
-}
-
-void DetectMQTTConnectUsernameRegister(void)
-{
- /* mqtt.connect.username sticky buffer */
- sigmatch_table[DETECT_AL_MQTT_CONNECT_USERNAME].name = KEYWORD_NAME;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_USERNAME].desc = "sticky buffer to match on the MQTT CONNECT username";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_USERNAME].url = "/rules/" KEYWORD_DOC;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_USERNAME].Setup = DetectMQTTConnectUsernameSetup;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_USERNAME].flags |= SIGMATCH_NOOPT;
-
- DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_MQTT, SIG_FLAG_TOSERVER, 0,
- DetectEngineInspectBufferGeneric, GetData);
-
- DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
- GetData, ALPROTO_MQTT, 1);
-
- DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
-
- g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
-
- SCLogDebug("registering " BUFFER_NAME " rule option");
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_CONNECT_USERNAME_H
-#define SURICATA_DETECT_MQTT_CONNECT_USERNAME_H
-
-void DetectMQTTConnectUsernameRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_CONNECT_USERNAME_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- *
- * Implements the mqtt.connect.willmessage sticky buffer
- */
-
-#include "suricata-common.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-connect-willmessage.h"
-#include "rust.h"
-
-#define KEYWORD_NAME "mqtt.connect.willmessage"
-#define KEYWORD_DOC "mqtt-keywords.html#mqtt-connect-willmessage"
-#define BUFFER_NAME "mqtt.connect.willmessage"
-#define BUFFER_DESC "MQTT CONNECT will message"
-static int g_buffer_id = 0;
-
-static int DetectMQTTConnectWillMessageSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
- return -1;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- return 0;
-}
-
-static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms,
- Flow *_f, const uint8_t _flow_flags,
- void *txv, const int list_id)
-{
- InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
- if (buffer->inspect == NULL) {
- const uint8_t *b = NULL;
- uint32_t b_len = 0;
-
- if (rs_mqtt_tx_get_connect_willmessage(txv, &b, &b_len) != 1)
- return NULL;
- if (b == NULL || b_len == 0)
- return NULL;
-
- InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
- InspectionBufferApplyTransforms(buffer, transforms);
- }
- return buffer;
-}
-
-void DetectMQTTConnectWillMessageRegister(void)
-{
- /* mqtt.connect.willmessage sticky buffer */
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLMESSAGE].name = KEYWORD_NAME;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLMESSAGE].desc = "sticky buffer to match on the MQTT CONNECT will message";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLMESSAGE].url = "/rules/" KEYWORD_DOC;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLMESSAGE].Setup = DetectMQTTConnectWillMessageSetup;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLMESSAGE].flags |= SIGMATCH_NOOPT;
-
- DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_MQTT, SIG_FLAG_TOSERVER, 0,
- DetectEngineInspectBufferGeneric, GetData);
-
- DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
- GetData, ALPROTO_MQTT, 1);
-
- DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
-
- g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
-
- SCLogDebug("registering " BUFFER_NAME " rule option");
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_CONNECT_WILLMESSAGE_H
-#define SURICATA_DETECT_MQTT_CONNECT_WILLMESSAGE_H
-
-void DetectMQTTConnectWillMessageRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_CONNECT_WILLMESSAGE_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- *
- * Implements the mqtt.connect.willtopic sticky buffer
- */
-
-#include "suricata-common.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-connect-willtopic.h"
-#include "rust.h"
-
-#define KEYWORD_NAME "mqtt.connect.willtopic"
-#define KEYWORD_DOC "mqtt-keywords.html#mqtt-connect-willtopic"
-#define BUFFER_NAME "mqtt.connect.willtopic"
-#define BUFFER_DESC "MQTT CONNECT will topic"
-static int g_buffer_id = 0;
-
-static int DetectMQTTConnectWillTopicSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
- return -1;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- return 0;
-}
-
-static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms,
- Flow *_f, const uint8_t _flow_flags,
- void *txv, const int list_id)
-{
- InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
- if (buffer->inspect == NULL) {
- const uint8_t *b = NULL;
- uint32_t b_len = 0;
-
- if (rs_mqtt_tx_get_connect_willtopic(txv, &b, &b_len) != 1)
- return NULL;
- if (b == NULL || b_len == 0)
- return NULL;
-
- InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
- InspectionBufferApplyTransforms(buffer, transforms);
- }
- return buffer;
-}
-
-void DetectMQTTConnectWillTopicRegister(void)
-{
- /* mqtt.connect.willtopic sticky buffer */
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLTOPIC].name = KEYWORD_NAME;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLTOPIC].desc = "sticky buffer to match on the MQTT CONNECT will topic";
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLTOPIC].url = "/rules/" KEYWORD_DOC;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLTOPIC].Setup = DetectMQTTConnectWillTopicSetup;
- sigmatch_table[DETECT_AL_MQTT_CONNECT_WILLTOPIC].flags |= SIGMATCH_NOOPT;
-
- DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_MQTT, SIG_FLAG_TOSERVER, 0,
- DetectEngineInspectBufferGeneric, GetData);
-
- DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
- GetData, ALPROTO_MQTT, 1);
-
- DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
-
- g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
-
- SCLogDebug("registering " BUFFER_NAME " rule option");
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_CONNECT_WILLTOPIC_H
-#define SURICATA_DETECT_MQTT_CONNECT_WILLTOPIC_H
-
-void DetectMQTTConnectWillTopicRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_CONNECT_WILLTOPIC_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-#include "conf.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-mqtt-flags.h"
-#include "util-unittest.h"
-
-#include "rust.h"
-
-#define PARSE_REGEX "(?: *,?!?(?:retain|dup))+"
-static DetectParseRegex parse_regex;
-
-static int mqtt_flags_id = 0;
-
-static int DetectMQTTFlagsMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx);
-static int DetectMQTTFlagsSetup (DetectEngineCtx *, Signature *, const char *);
-void MQTTFlagsRegisterTests(void);
-void DetectMQTTFlagsFree(DetectEngineCtx *de_ctx, void *);
-
-typedef struct DetectMQTTFlagsData_ {
- MQTTFlagState retain, dup;
-} DetectMQTTFlagsData;
-
-/**
- * \brief Registration function for mqtt.flags: keyword
- */
-void DetectMQTTFlagsRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_FLAGS].name = "mqtt.flags";
- sigmatch_table[DETECT_AL_MQTT_FLAGS].desc = "match MQTT fixed header flags";
- sigmatch_table[DETECT_AL_MQTT_FLAGS].url = "/rules/mqtt-keywords.html#mqtt-flags";
- sigmatch_table[DETECT_AL_MQTT_FLAGS].AppLayerTxMatch = DetectMQTTFlagsMatch;
- sigmatch_table[DETECT_AL_MQTT_FLAGS].Setup = DetectMQTTFlagsSetup;
- sigmatch_table[DETECT_AL_MQTT_FLAGS].Free = DetectMQTTFlagsFree;
-#ifdef UNITTESTS
- sigmatch_table[DETECT_AL_MQTT_FLAGS].RegisterTests = MQTTFlagsRegisterTests;
-#endif
-
- DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
-
- DetectAppLayerInspectEngineRegister(
- "mqtt.flags", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1, DetectEngineInspectGenericList, NULL);
-
- mqtt_flags_id = DetectBufferTypeGetByName("mqtt.flags");
-}
-
-/**
- * \internal
- * \brief Function to match fixed header flags of an MQTT Tx
- *
- * \param det_ctx Pointer to the pattern matcher thread.
- * \param f Pointer to the current flow.
- * \param flags Flags.
- * \param state App layer state.
- * \param txv Pointer to the transaction.
- * \param s Pointer to the Signature.
- * \param ctx Pointer to the sigmatch that we will cast into DetectMQTTFlagsData.
- *
- * \retval 0 no match.
- * \retval 1 match.
- */
-static int DetectMQTTFlagsMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx)
-{
- const DetectMQTTFlagsData *de = (const DetectMQTTFlagsData *)ctx;
-
- if (!de)
- return 0;
-
- return rs_mqtt_tx_has_flags(txv, de->retain, de->dup);
-}
-
-/**
- * \internal
- * \brief This function is used to parse options passed via mqtt.flags: keyword
- *
- * \param rawstr Pointer to the user provided options
- *
- * \retval de pointer to DetectMQTTFlagsData on success
- * \retval NULL on failure
- */
-static DetectMQTTFlagsData *DetectMQTTFlagsParse(const char *rawstr)
-{
-
- DetectMQTTFlagsData *de = SCCalloc(1, sizeof(DetectMQTTFlagsData));
- if (unlikely(de == NULL))
- return NULL;
-
- pcre2_match_data *match = NULL;
- int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
- if (ret < 1) {
- SCLogError("invalid flag definition: %s", rawstr);
- if (match) {
- pcre2_match_data_free(match);
- }
- SCFree(de);
- return NULL;
- }
-
- de->retain = de->dup = MQTT_DONT_CARE;
-
- char copy[strlen(rawstr)+1];
- strlcpy(copy, rawstr, sizeof(copy));
- char *xsaveptr = NULL;
-
- /* Iterate through comma-separated string... */
- char *flagv = strtok_r(copy, ",", &xsaveptr);
- while (flagv != NULL) {
- /* skip blanks */
- while (*flagv != '\0' && isblank(*flagv)) {
- flagv++;
- }
- if (strlen(flagv) < 2) {
- /* flags have a minimum length */
- SCLogError("malformed flag value: %s", flagv);
- goto error;
- } else {
- int offset = 0;
- MQTTFlagState fs_to_set = MQTT_MUST_BE_SET;
- if (flagv[0] == '!') {
- /* negated flag */
- offset = 1; /* skip negation operator during comparison */
- fs_to_set = MQTT_CANT_BE_SET;
- }
- if (strcmp(flagv+offset, "dup") == 0) {
- if (de->dup != MQTT_DONT_CARE) {
- SCLogError("duplicate flag definition: %s", flagv);
- goto error;
- }
- de->dup = fs_to_set;
- } else if (strcmp(flagv+offset, "retain") == 0) {
- if (de->retain != MQTT_DONT_CARE) {
- SCLogError("duplicate flag definition: %s", flagv);
- goto error;
- }
- de->retain = fs_to_set;
- } else {
- SCLogError("invalid flag definition: %s", flagv);
- goto error;
- }
- }
- flagv = strtok_r(NULL, ",", &xsaveptr);
- }
-
- pcre2_match_data_free(match);
- return de;
-
-error:
- if (match) {
- pcre2_match_data_free(match);
- }
- if (de)
- SCFree(de);
- return NULL;
-}
-
-/**
- * \internal
- * \brief this function is used to add the parsed type query into the current signature
- *
- * \param de_ctx pointer to the Detection Engine Context
- * \param s pointer to the Current Signature
- * \param rawstr pointer to the user provided options
- *
- * \retval 0 on Success
- * \retval -1 on Failure
- */
-static int DetectMQTTFlagsSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
-{
- DetectMQTTFlagsData *de = NULL;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- de = DetectMQTTFlagsParse(rawstr);
- if (de == NULL)
- goto error;
-
- if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_MQTT_FLAGS, (SigMatchCtx *)de, mqtt_flags_id) ==
- NULL) {
- goto error;
- }
-
- return 0;
-
-error:
- if (de != NULL)
- SCFree(de);
- return -1;
-}
-
-/**
- * \internal
- * \brief this function will free memory associated with DetectMQTTFlagsData
- *
- * \param de pointer to DetectMQTTFlagsData
- */
-void DetectMQTTFlagsFree(DetectEngineCtx *de_ctx, void *de_ptr)
-{
- if (de_ptr != NULL)
- SCFree(de_ptr);
-}
-
-/*
- * ONLY TESTS BELOW THIS COMMENT
- */
-
-#ifdef UNITTESTS
-/**
- * \test MQTTFlagsTestParse01 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTFlagsTestParse01 (void)
-{
- DetectMQTTFlagsData *de = NULL;
-
- de = DetectMQTTFlagsParse("retain");
- FAIL_IF_NULL(de);
- DetectMQTTFlagsFree(NULL, de);
-
- de = DetectMQTTFlagsParse("dup");
- FAIL_IF_NULL(de);
- DetectMQTTFlagsFree(NULL, de);
-
- de = DetectMQTTFlagsParse("retain,dup");
- FAIL_IF_NULL(de);
- DetectMQTTFlagsFree(NULL, de);
-
- de = DetectMQTTFlagsParse("dup, retain");
- FAIL_IF_NULL(de);
- DetectMQTTFlagsFree(NULL, de);
-
- PASS;
-}
-
-/**
- * \test MQTTFlagsTestParse02 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTFlagsTestParse02 (void)
-{
- DetectMQTTFlagsData *de = NULL;
- de = DetectMQTTFlagsParse("retain,!dup");
- FAIL_IF_NULL(de);
- DetectMQTTFlagsFree(NULL, de);
-
- PASS;
-}
-
-/**
- * \test MQTTFlagsTestParse03 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTFlagsTestParse03 (void)
-{
- DetectMQTTFlagsData *de = NULL;
- de = DetectMQTTFlagsParse("ref");
- if (de) {
- DetectMQTTFlagsFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTFlagsTestParse04 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTFlagsTestParse04 (void)
-{
- DetectMQTTFlagsData *de = NULL;
- de = DetectMQTTFlagsParse("dup,!");
- if (de) {
- DetectMQTTFlagsFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTFlagsTestParse05 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTFlagsTestParse05 (void)
-{
- DetectMQTTFlagsData *de = NULL;
- de = DetectMQTTFlagsParse("dup,!dup");
- if (de) {
- DetectMQTTFlagsFree(NULL, de);
- FAIL;
- }
-
- de = DetectMQTTFlagsParse("!retain,retain");
- if (de) {
- DetectMQTTFlagsFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-
-#endif /* UNITTESTS */
-
-/**
- * \brief this function registers unit tests for MQTTFlags
- */
-void MQTTFlagsRegisterTests(void)
-{
-#ifdef UNITTESTS
- UtRegisterTest("MQTTFlagsTestParse01", MQTTFlagsTestParse01);
- UtRegisterTest("MQTTFlagsTestParse02", MQTTFlagsTestParse02);
- UtRegisterTest("MQTTFlagsTestParse03", MQTTFlagsTestParse03);
- UtRegisterTest("MQTTFlagsTestParse04", MQTTFlagsTestParse04);
- UtRegisterTest("MQTTFlagsTestParse05", MQTTFlagsTestParse05);
-#endif /* UNITTESTS */
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_FLAGS_H
-#define SURICATA_DETECT_MQTT_FLAGS_H
-
-void DetectMQTTFlagsRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_FLAGS_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-#include "conf.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-engine-uint.h"
-#include "detect-mqtt-protocol-version.h"
-#include "util-byte.h"
-#include "util-unittest.h"
-
-#include "rust.h"
-
-static int mqtt_protocol_version_id = 0;
-
-static int DetectMQTTProtocolVersionMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx);
-static int DetectMQTTProtocolVersionSetup (DetectEngineCtx *, Signature *, const char *);
-void MQTTProtocolVersionRegisterTests(void);
-void DetectMQTTProtocolVersionFree(DetectEngineCtx *de_ctx, void *);
-
-/**
- * \brief Registration function for mqtt.protocol_version: keyword
- */
-void DetectMQTTProtocolVersionRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_PROTOCOL_VERSION].name = "mqtt.protocol_version";
- sigmatch_table[DETECT_AL_MQTT_PROTOCOL_VERSION].desc = "match MQTT protocol version";
- sigmatch_table[DETECT_AL_MQTT_PROTOCOL_VERSION].url = "/rules/mqtt-keywords.html#mqtt-protocol-version";
- sigmatch_table[DETECT_AL_MQTT_PROTOCOL_VERSION].AppLayerTxMatch = DetectMQTTProtocolVersionMatch;
- sigmatch_table[DETECT_AL_MQTT_PROTOCOL_VERSION].Setup = DetectMQTTProtocolVersionSetup;
- sigmatch_table[DETECT_AL_MQTT_PROTOCOL_VERSION].Free = DetectMQTTProtocolVersionFree;
-#ifdef UNITTESTS
- sigmatch_table[DETECT_AL_MQTT_PROTOCOL_VERSION].RegisterTests = MQTTProtocolVersionRegisterTests;
-#endif
-
- DetectAppLayerInspectEngineRegister("mqtt.protocol_version", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
- DetectEngineInspectGenericList, NULL);
-
- mqtt_protocol_version_id = DetectBufferTypeGetByName("mqtt.protocol_version");
-}
-
-/**
- * \internal
- * \brief Function to match protocol version of an MQTT Tx
- *
- * \param det_ctx Pointer to the pattern matcher thread.
- * \param f Pointer to the current flow.
- * \param flags Flags.
- * \param state App layer state.
- * \param txv Pointer to the transaction.
- * \param s Pointer to the Signature.
- * \param ctx Pointer to the sigmatch that we will cast into DetectMQTTProtocolVersionData.
- *
- * \retval 0 no match.
- * \retval 1 match.
- */
-static int DetectMQTTProtocolVersionMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx)
-{
- const DetectU8Data *de = (const DetectU8Data *)ctx;
- uint8_t version;
-
- version = rs_mqtt_tx_get_protocol_version(state);
-
- return DetectU8Match(version, de);
-}
-
-/**
- * \internal
- * \brief this function is used to add the parsed sigmatch into the current signature
- *
- * \param de_ctx pointer to the Detection Engine Context
- * \param s pointer to the Current Signature
- * \param rawstr pointer to the user provided options
- *
- * \retval 0 on Success
- * \retval -1 on Failure
- */
-static int DetectMQTTProtocolVersionSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
-{
- DetectU8Data *de = NULL;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- de = DetectU8Parse(rawstr);
- if (de == NULL)
- return -1;
-
- if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_MQTT_PROTOCOL_VERSION, (SigMatchCtx *)de,
- mqtt_protocol_version_id) == NULL) {
- goto error;
- }
-
- return 0;
-
-error:
- if (de != NULL)
- rs_detect_u8_free(de);
- return -1;
-}
-
-/**
- * \internal
- * \brief this function will free memory associated with DetectMQTTProtocolVersionData
- *
- * \param de pointer to DetectMQTTProtocolVersionData
- */
-void DetectMQTTProtocolVersionFree(DetectEngineCtx *de_ctx, void *de_ptr)
-{
- rs_detect_u8_free(de_ptr);
-}
-
-/*
- * ONLY TESTS BELOW THIS COMMENT
- */
-
-#ifdef UNITTESTS
-/**
- * \test MQTTProtocolVersionTestParse01 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTProtocolVersionTestParse01 (void)
-{
- DetectEngineCtx *de_ctx = DetectEngineCtxInit();
- FAIL_IF_NULL(de_ctx);
-
- Signature *sig = DetectEngineAppendSig(de_ctx,
- "alert ip any any -> any any (mqtt.protocol_version:3; sid:1; rev:1;)");
- FAIL_IF_NULL(sig);
-
- sig = DetectEngineAppendSig(de_ctx,
- "alert ip any any -> any any (mqtt.protocol_version:3; sid:2; rev:1;)");
- FAIL_IF_NULL(sig);
-
- DetectEngineCtxFree(de_ctx);
-
- PASS;
-}
-
-/**
- * \test MQTTProtocolVersionTestParse02 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTProtocolVersionTestParse02 (void)
-{
- DetectEngineCtx *de_ctx = DetectEngineCtxInit();
- FAIL_IF_NULL(de_ctx);
-
- Signature *sig = DetectEngineAppendSig(de_ctx,
- "alert ip any any -> any any (mqtt.protocol_version:>3; sid:1; rev:1;)");
- FAIL_IF_NULL(sig);
-
- sig = DetectEngineAppendSig(de_ctx,
- "alert ip any any -> any any (mqtt.protocol_version:<44; sid:2; rev:1;)");
- FAIL_IF_NULL(sig);
-
- DetectEngineCtxFree(de_ctx);
-
- PASS;
-}
-
-/**
- * \test MQTTProtocolVersionTestParse03 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTProtocolVersionTestParse03 (void)
-{
- DetectEngineCtx *de_ctx = DetectEngineCtxInit();
- FAIL_IF_NULL(de_ctx);
-
- Signature *sig = DetectEngineAppendSig(de_ctx,
- "alert ip any any -> any any (mqtt.protocol_version:; sid:1; rev:1;)");
- FAIL_IF_NOT_NULL(sig);
-
- DetectEngineCtxFree(de_ctx);
-
- PASS;
-}
-
-/**
- * \test MQTTProtocolVersionTestParse04 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTProtocolVersionTestParse04 (void)
-{
- DetectEngineCtx *de_ctx = DetectEngineCtxInit();
- FAIL_IF_NULL(de_ctx);
-
- Signature *sig = DetectEngineAppendSig(de_ctx,
- "alert ip any any -> any any (mqtt.protocol_version:<444; sid:1; rev:1;)");
- FAIL_IF_NOT_NULL(sig);
-
- DetectEngineCtxFree(de_ctx);
-
- PASS;
-}
-
-#endif /* UNITTESTS */
-
-/**
- * \brief this function registers unit tests for MQTTProtocolVersion
- */
-void MQTTProtocolVersionRegisterTests(void)
-{
-#ifdef UNITTESTS
- UtRegisterTest("MQTTProtocolVersionTestParse01", MQTTProtocolVersionTestParse01);
- UtRegisterTest("MQTTProtocolVersionTestParse02", MQTTProtocolVersionTestParse02);
- UtRegisterTest("MQTTProtocolVersionTestParse03", MQTTProtocolVersionTestParse03);
- UtRegisterTest("MQTTProtocolVersionTestParse04", MQTTProtocolVersionTestParse04);
-#endif /* UNITTESTS */
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_PROTOCOL_VERSION_H
-#define SURICATA_DETECT_MQTT_PROTOCOL_VERSION_H
-
-void DetectMQTTProtocolVersionRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_PROTOCOL_VERSION_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- *
- * Implements the mqtt.publish.message sticky buffer
- */
-
-#include "suricata-common.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-publish-message.h"
-#include "rust.h"
-
-#define KEYWORD_NAME "mqtt.publish.message"
-#define KEYWORD_DOC "mqtt-keywords.html#mqtt-publish-message"
-#define BUFFER_NAME "mqtt.publish.message"
-#define BUFFER_DESC "MQTT PUBLISH message"
-static int g_buffer_id = 0;
-
-static int DetectMQTTPublishMessageSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
- return -1;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- return 0;
-}
-
-static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms,
- Flow *_f, const uint8_t _flow_flags,
- void *txv, const int list_id)
-{
- InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
- if (buffer->inspect == NULL) {
- const uint8_t *b = NULL;
- uint32_t b_len = 0;
-
- if (rs_mqtt_tx_get_publish_message(txv, &b, &b_len) != 1)
- return NULL;
- if (b == NULL || b_len == 0)
- return NULL;
-
- InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
- InspectionBufferApplyTransforms(buffer, transforms);
- }
- return buffer;
-}
-
-void DetectMQTTPublishMessageRegister(void)
-{
- /* mqtt.publish.message sticky buffer */
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_MESSAGE].name = KEYWORD_NAME;
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_MESSAGE].desc = "sticky buffer to match on the MQTT PUBLISH message";
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_MESSAGE].url = "/rules/" KEYWORD_DOC;
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_MESSAGE].Setup = DetectMQTTPublishMessageSetup;
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_MESSAGE].flags |= SIGMATCH_NOOPT;
-
- DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_MQTT, SIG_FLAG_TOSERVER, 0,
- DetectEngineInspectBufferGeneric, GetData);
-
- DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
- GetData, ALPROTO_MQTT, 1);
-
- DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
-
- g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
-
- SCLogDebug("registering " BUFFER_NAME " rule option");
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_PUBLISH_MESSAGE_H
-#define SURICATA_DETECT_MQTT_PUBLISH_MESSAGE_H
-
-void DetectMQTTPublishMessageRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_PUBLISH_MESSAGE_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- *
- * Implements the mqtt.publish.topic sticky buffer
- */
-
-#include "suricata-common.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-publish-topic.h"
-#include "rust.h"
-
-#define KEYWORD_NAME "mqtt.publish.topic"
-#define KEYWORD_DOC "mqtt-keywords.html#mqtt-publish-topic"
-#define BUFFER_NAME "mqtt.publish.topic"
-#define BUFFER_DESC "MQTT PUBLISH topic"
-static int g_buffer_id = 0;
-
-static int DetectMQTTPublishTopicSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
- return -1;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- return 0;
-}
-
-static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms,
- Flow *_f, const uint8_t _flow_flags,
- void *txv, const int list_id)
-{
- InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
- if (buffer->inspect == NULL) {
- const uint8_t *b = NULL;
- uint32_t b_len = 0;
-
- if (rs_mqtt_tx_get_publish_topic(txv, &b, &b_len) != 1)
- return NULL;
- if (b == NULL || b_len == 0)
- return NULL;
-
- InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
- InspectionBufferApplyTransforms(buffer, transforms);
- }
- return buffer;
-}
-
-void DetectMQTTPublishTopicRegister(void)
-{
- /* mqtt.publish.topic sticky buffer */
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_TOPIC].name = KEYWORD_NAME;
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_TOPIC].desc = "sticky buffer to match on the MQTT PUBLISH topic";
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_TOPIC].url = "/rules/" KEYWORD_DOC;
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_TOPIC].Setup = DetectMQTTPublishTopicSetup;
- sigmatch_table[DETECT_AL_MQTT_PUBLISH_TOPIC].flags |= SIGMATCH_NOOPT;
-
- DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_MQTT, SIG_FLAG_TOSERVER, 0,
- DetectEngineInspectBufferGeneric, GetData);
-
- DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
- GetData, ALPROTO_MQTT, 1);
-
- DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC);
-
- g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
-
- SCLogDebug("registering " BUFFER_NAME " rule option");
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_PUBLISH_TOPIC_H
-#define SURICATA_DETECT_MQTT_PUBLISH_TOPIC_H
-
-void DetectMQTTPublishTopicRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_PUBLISH_TOPIC_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-#include "conf.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-mqtt-qos.h"
-#include "util-byte.h"
-#include "util-unittest.h"
-
-#include "rust.h"
-
-static int mqtt_qos_id = 0;
-
-static int DetectMQTTQosMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx);
-static int DetectMQTTQosSetup (DetectEngineCtx *, Signature *, const char *);
-void MQTTQosRegisterTests(void);
-void DetectMQTTQosFree(DetectEngineCtx *de_ctx, void *);
-
-/**
- * \brief Registration function for mqtt.qos: keyword
- */
-void DetectMQTTQosRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_QOS].name = "mqtt.qos";
- sigmatch_table[DETECT_AL_MQTT_QOS].desc = "match MQTT fixed header QOS level";
- sigmatch_table[DETECT_AL_MQTT_QOS].url = "/rules/mqtt-keywords.html#mqtt-qos";
- sigmatch_table[DETECT_AL_MQTT_QOS].AppLayerTxMatch = DetectMQTTQosMatch;
- sigmatch_table[DETECT_AL_MQTT_QOS].Setup = DetectMQTTQosSetup;
- sigmatch_table[DETECT_AL_MQTT_QOS].Free = DetectMQTTQosFree;
-#ifdef UNITTESTS
- sigmatch_table[DETECT_AL_MQTT_QOS].RegisterTests = MQTTQosRegisterTests;
-#endif
-
- DetectAppLayerInspectEngineRegister(
- "mqtt.qos", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1, DetectEngineInspectGenericList, NULL);
-
- mqtt_qos_id = DetectBufferTypeGetByName("mqtt.qos");
-}
-
-/**
- * \internal
- * \brief Function to match fixed header QOS field of an MQTT Tx
- *
- * \param det_ctx Pointer to the pattern matcher thread.
- * \param f Pointer to the current flow.
- * \param flags Flags.
- * \param state App layer state.
- * \param txv Pointer to the transaction.
- * \param s Pointer to the Signature.
- * \param ctx Pointer to the sigmatch that we will cast into uint8_t.
- *
- * \retval 0 no match.
- * \retval 1 match.
- */
-static int DetectMQTTQosMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx)
-{
- const uint8_t *de = (const uint8_t *)ctx;
-
- if (!de)
- return 0;
-
- return rs_mqtt_tx_has_qos(txv, *de);
-}
-
-/**
- * \internal
- * \brief This function is used to parse options passed via mqtt.qos: keyword
- *
- * \param rawstr Pointer to the user provided options
- *
- * \retval de pointer to DetectMQTTQosData on success
- * \retval NULL on failure
- */
-static uint8_t *DetectMQTTQosParse(const char *rawstr)
-{
- uint8_t *de = NULL;
- int ret = 0;
- uint8_t val;
-
- ret = StringParseU8RangeCheck(&val, 10, 0, rawstr, 0, 2);
- if (ret < 0) {
- SCLogError("invalid MQTT QOS level: %s", rawstr);
- return NULL;
- }
-
- de = SCMalloc(sizeof(uint8_t));
- if (unlikely(de == NULL))
- return NULL;
- *de = val;
-
- return de;
-}
-
-/**
- * \internal
- * \brief this function is used to add the parsed sigmatch into the current signature
- *
- * \param de_ctx pointer to the Detection Engine Context
- * \param s pointer to the Current Signature
- * \param rawstr pointer to the user provided options
- *
- * \retval 0 on Success
- * \retval -1 on Failure
- */
-static int DetectMQTTQosSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
-{
- uint8_t *de = NULL;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- de = DetectMQTTQosParse(rawstr);
- if (de == NULL)
- goto error;
-
- if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_MQTT_QOS, (SigMatchCtx *)de, mqtt_qos_id) ==
- NULL) {
- goto error;
- }
-
- return 0;
-
-error:
- if (de != NULL)
- SCFree(de);
- return -1;
-}
-
-/**
- * \internal
- * \brief this function will free memory associated with DetectMQTTQosData
- *
- * \param de pointer to DetectMQTTQosData
- */
-void DetectMQTTQosFree(DetectEngineCtx *de_ctx, void *de_ptr)
-{
- if (de_ptr != NULL)
- SCFree(de_ptr);
-}
-
-/*
- * ONLY TESTS BELOW THIS COMMENT
- */
-
-#ifdef UNITTESTS
-/**
- * \test MQTTQosTestParse01 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTQosTestParse01 (void)
-{
- uint8_t *de = NULL;
-
- de = DetectMQTTQosParse("0");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 0);
- DetectMQTTQosFree(NULL, de);
-
- de = DetectMQTTQosParse(" 0");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 0);
- DetectMQTTQosFree(NULL, de);
-
- de = DetectMQTTQosParse("1");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 1);
- DetectMQTTQosFree(NULL, de);
-
- de = DetectMQTTQosParse("2");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 2);
- DetectMQTTQosFree(NULL, de);
-
- PASS;
-}
-
-/**
- * \test MQTTQosTestParse02 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTQosTestParse02 (void)
-{
- uint8_t *de = NULL;
- de = DetectMQTTQosParse("3");
- if (de) {
- DetectMQTTQosFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTQosTestParse04 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTQosTestParse03 (void)
-{
- uint8_t *de = NULL;
- de = DetectMQTTQosParse("12");
- if (de) {
- DetectMQTTQosFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-
-#endif /* UNITTESTS */
-
-/**
- * \brief this function registers unit tests for MQTTQos
- */
-void MQTTQosRegisterTests(void)
-{
-#ifdef UNITTESTS
- UtRegisterTest("MQTTQosTestParse01", MQTTQosTestParse01);
- UtRegisterTest("MQTTQosTestParse02", MQTTQosTestParse02);
- UtRegisterTest("MQTTQosTestParse03", MQTTQosTestParse03);
-#endif /* UNITTESTS */
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_QOS_H
-#define SURICATA_DETECT_MQTT_QOS_H
-
-void DetectMQTTQosRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_QOS_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-#include "conf.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-mqtt-reason-code.h"
-#include "util-byte.h"
-#include "util-unittest.h"
-
-#include "rust.h"
-
-#define PARSE_REGEX "^\\s*\\d+\\s*$"
-static DetectParseRegex parse_regex;
-
-static int mqtt_reason_code_id = 0;
-
-static int DetectMQTTReasonCodeMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx);
-static int DetectMQTTReasonCodeSetup (DetectEngineCtx *, Signature *, const char *);
-void MQTTReasonCodeRegisterTests(void);
-void DetectMQTTReasonCodeFree(DetectEngineCtx *de_ctx, void *);
-
-/**
- * \brief Registration function for mqtt.reason_code: keyword
- */
-void DetectMQTTReasonCodeRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_REASON_CODE].name = "mqtt.reason_code";
- sigmatch_table[DETECT_AL_MQTT_REASON_CODE].alias = "mqtt.connack.return_code";
- sigmatch_table[DETECT_AL_MQTT_REASON_CODE].desc = "match MQTT 5.0+ reason code";
- sigmatch_table[DETECT_AL_MQTT_REASON_CODE].url = "/rules/mqtt-keywords.html#mqtt-reason-code";
- sigmatch_table[DETECT_AL_MQTT_REASON_CODE].AppLayerTxMatch = DetectMQTTReasonCodeMatch;
- sigmatch_table[DETECT_AL_MQTT_REASON_CODE].Setup = DetectMQTTReasonCodeSetup;
- sigmatch_table[DETECT_AL_MQTT_REASON_CODE].Free = DetectMQTTReasonCodeFree;
-#ifdef UNITTESTS
- sigmatch_table[DETECT_AL_MQTT_REASON_CODE].RegisterTests = MQTTReasonCodeRegisterTests;
-#endif
-
- DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
-
- DetectAppLayerInspectEngineRegister("mqtt.reason_code", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
- DetectEngineInspectGenericList, NULL);
-
- mqtt_reason_code_id = DetectBufferTypeGetByName("mqtt.reason_code");
-}
-
-/**
- * \internal
- * \brief Function to match reason code of an MQTT 5.0 Tx
- *
- * \param det_ctx Pointer to the pattern matcher thread.
- * \param f Pointer to the current flow.
- * \param flags Flags.
- * \param state App layer state.
- * \param txv Pointer to the transaction.
- * \param s Pointer to the Signature.
- * \param ctx Pointer to the sigmatch that we will cast into DetectMQTTReasonCodeData.
- *
- * \retval 0 no match.
- * \retval 1 match.
- */
-static int DetectMQTTReasonCodeMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx)
-{
- const uint8_t *de = (const uint8_t *)ctx;
- uint8_t code;
-
- if (!de)
- return 0;
-
- if (rs_mqtt_tx_get_reason_code(txv, &code) == 0) {
- /* this function does not return a code that needs to be compared,
- so we can just return the result of the check implemented in
- Rust */
- return rs_mqtt_tx_unsuback_has_reason_code(txv, *de);
- } else {
- if (code == *de)
- return 1;
- }
- return 0;
-}
-
-/**
- * \internal
- * \brief This function is used to parse options passed via mqtt.reason_code: keyword
- *
- * \param rawstr Pointer to the user provided options
- *
- * \retval de pointer to DetectMQTTReasonCodeData on success
- * \retval NULL on failure
- */
-static uint8_t *DetectMQTTReasonCodeParse(const char *rawstr)
-{
- uint8_t *de = NULL;
- int ret = 0;
- uint8_t val;
-
- ret = StringParseUint8(&val, 10, 0, rawstr);
- if (ret < 0) {
- SCLogError("invalid MQTT reason code: %s", rawstr);
- return NULL;
- }
-
- de = SCMalloc(sizeof(uint8_t));
- if (unlikely(de == NULL))
- return NULL;
- *de = (uint8_t) val;
-
- return de;
-}
-
-/**
- * \internal
- * \brief this function is used to add the parsed sigmatch into the current signature
- *
- * \param de_ctx pointer to the Detection Engine Context
- * \param s pointer to the Current Signature
- * \param rawstr pointer to the user provided options
- *
- * \retval 0 on Success
- * \retval -1 on Failure
- */
-static int DetectMQTTReasonCodeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
-{
- uint8_t *de = NULL;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- de = DetectMQTTReasonCodeParse(rawstr);
- if (de == NULL)
- goto error;
-
- if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_MQTT_REASON_CODE, (SigMatchCtx *)de,
- mqtt_reason_code_id) == NULL) {
- goto error;
- }
-
- return 0;
-
-error:
- if (de != NULL)
- SCFree(de);
- return -1;
-}
-
-/**
- * \internal
- * \brief this function will free memory associated with DetectMQTTReasonCodeData
- *
- * \param de pointer to DetectMQTTReasonCodeData
- */
-void DetectMQTTReasonCodeFree(DetectEngineCtx *de_ctx, void *de_ptr)
-{
- if (de_ptr != NULL)
- SCFree(de_ptr);
-}
-
-/*
- * ONLY TESTS BELOW THIS COMMENT
- */
-
-#ifdef UNITTESTS
-/**
- * \test MQTTReasonCodeTestParse01 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTReasonCodeTestParse01 (void)
-{
- uint8_t *de = NULL;
-
- de = DetectMQTTReasonCodeParse("3");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 3);
- DetectMQTTReasonCodeFree(NULL, de);
-
- de = DetectMQTTReasonCodeParse(" 4");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 4);
- DetectMQTTReasonCodeFree(NULL, de);
-
- de = DetectMQTTReasonCodeParse(" 5");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 5);
- DetectMQTTReasonCodeFree(NULL, de);
-
- de = DetectMQTTReasonCodeParse("255");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 255);
- DetectMQTTReasonCodeFree(NULL, de);
-
- PASS;
-}
-
-/**
- * \test MQTTReasonCodeTestParse02 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTReasonCodeTestParse02 (void)
-{
- uint8_t *de = NULL;
- de = DetectMQTTReasonCodeParse("6X");
- if (de) {
- DetectMQTTReasonCodeFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTReasonCodeTestParse03 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTReasonCodeTestParse03 (void)
-{
- uint8_t *de = NULL;
- de = DetectMQTTReasonCodeParse("");
- if (de) {
- DetectMQTTReasonCodeFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-/**
- * \test MQTTReasonCodeTestParse04 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTReasonCodeTestParse04 (void)
-{
- uint8_t *de = NULL;
- de = DetectMQTTReasonCodeParse("256");
- if (de) {
- DetectMQTTReasonCodeFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-
-
-#endif /* UNITTESTS */
-
-/**
- * \brief this function registers unit tests for MQTTReasonCode
- */
-void MQTTReasonCodeRegisterTests(void)
-{
-#ifdef UNITTESTS
- UtRegisterTest("MQTTReasonCodeTestParse01", MQTTReasonCodeTestParse01);
- UtRegisterTest("MQTTReasonCodeTestParse02", MQTTReasonCodeTestParse02);
- UtRegisterTest("MQTTReasonCodeTestParse03", MQTTReasonCodeTestParse03);
- UtRegisterTest("MQTTReasonCodeTestParse04", MQTTReasonCodeTestParse04);
-#endif /* UNITTESTS */
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_REASON_CODE_H
-#define SURICATA_DETECT_MQTT_REASON_CODE_H
-
-void DetectMQTTReasonCodeRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_REASON_CODE_H */
+++ /dev/null
-/* Copyright (C) 2020-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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-
-#include "app-layer.h"
-#include "app-layer-parser.h"
-
-#include "conf.h"
-#include "decode.h"
-#include "detect.h"
-#include "detect-content.h"
-#include "detect-parse.h"
-#include "detect-pcre.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-subscribe-topic.h"
-#include "util-unittest.h"
-#include "util-unittest-helper.h"
-
-#include "rust-bindings.h"
-
-#include "threads.h"
-
-#include "flow.h"
-#include "flow-util.h"
-#include "flow-var.h"
-
-#include "util-debug.h"
-#include "util-spm.h"
-#include "util-print.h"
-#include "util-profiling.h"
-
-static int DetectMQTTSubscribeTopicSetup(DetectEngineCtx *, Signature *, const char *);
-
-static int g_mqtt_subscribe_topic_buffer_id = 0;
-
-static uint32_t subscribe_topic_match_limit = 100;
-
-static InspectionBuffer *MQTTSubscribeTopicGetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
- int list_id, uint32_t local_id)
-{
- SCEnter();
-
- if (subscribe_topic_match_limit > 0 && local_id >= subscribe_topic_match_limit)
- return NULL;
-
- InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
- if (buffer == NULL)
- return NULL;
- if (buffer->initialized)
- return buffer;
-
- const uint8_t *data;
- uint32_t data_len;
- if (rs_mqtt_tx_get_subscribe_topic(txv, local_id, &data, &data_len) == 0) {
- InspectionBufferSetupMultiEmpty(buffer);
- return NULL;
- }
-
- InspectionBufferSetupMulti(buffer, transforms, data, data_len);
- buffer->flags = DETECT_CI_FLAGS_SINGLE;
-
- SCReturnPtr(buffer, "InspectionBuffer");
-}
-
-/**
- * \brief Registration function for keyword: mqtt.subscribe.topic
- */
-void DetectMQTTSubscribeTopicRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_SUBSCRIBE_TOPIC].name = "mqtt.subscribe.topic";
- sigmatch_table[DETECT_AL_MQTT_SUBSCRIBE_TOPIC].desc = "sticky buffer to match MQTT SUBSCRIBE topic";
- sigmatch_table[DETECT_AL_MQTT_SUBSCRIBE_TOPIC].url = "/rules/mqtt-keywords.html#mqtt-subscribe-topic";
- sigmatch_table[DETECT_AL_MQTT_SUBSCRIBE_TOPIC].Setup = DetectMQTTSubscribeTopicSetup;
- sigmatch_table[DETECT_AL_MQTT_SUBSCRIBE_TOPIC].flags |= SIGMATCH_NOOPT;
- sigmatch_table[DETECT_AL_MQTT_SUBSCRIBE_TOPIC].flags |= SIGMATCH_INFO_STICKY_BUFFER;
-
- intmax_t val = 0;
- if (ConfGetInt("app-layer.protocols.mqtt.subscribe-topic-match-limit", &val)) {
- subscribe_topic_match_limit = val;
- }
- if (subscribe_topic_match_limit <= 0) {
- SCLogDebug("Using unrestricted MQTT SUBSCRIBE topic matching");
- } else {
- SCLogDebug("Using MQTT SUBSCRIBE topic match-limit setting of: %u",
- subscribe_topic_match_limit);
- }
-
- DetectAppLayerMultiRegister("mqtt.subscribe.topic", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
- MQTTSubscribeTopicGetData, 1, 1);
-
- DetectBufferTypeSetDescriptionByName("mqtt.subscribe.topic",
- "subscribe topic query");
-
- g_mqtt_subscribe_topic_buffer_id = DetectBufferTypeGetByName("mqtt.subscribe.topic");
-
- DetectBufferTypeSupportsMultiInstance("mqtt.subscribe.topic");
-}
-
-/**
- * \brief setup the sticky buffer keyword used in the rule
- *
- * \param de_ctx Pointer to the Detection Engine Context
- * \param s Pointer to the Signature to which the current keyword belongs
- * \param str Should hold an empty string always
- *
- * \retval 0 On success
- * \retval -1 On failure
- */
-
-static int DetectMQTTSubscribeTopicSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_mqtt_subscribe_topic_buffer_id) < 0)
- return -1;
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
- return 0;
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_SUBSCRIBE_TOPIC_H
-#define SURICATA_DETECT_MQTT_SUBSCRIBE_TOPIC_H
-
-void DetectMQTTSubscribeTopicRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_SUBSCRIBE_TOPIC_H */
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-#include "conf.h"
-#include "detect.h"
-#include "detect-parse.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-mqtt-type.h"
-#include "util-unittest.h"
-
-#include "rust.h"
-
-static int mqtt_type_id = 0;
-
-static int DetectMQTTTypeMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx);
-static int DetectMQTTTypeSetup (DetectEngineCtx *, Signature *, const char *);
-void MQTTTypeRegisterTests(void);
-void DetectMQTTTypeFree(DetectEngineCtx *de_ctx, void *);
-
-/**
- * \brief Registration function for mqtt.type: keyword
- */
-void DetectMQTTTypeRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_TYPE].name = "mqtt.type";
- sigmatch_table[DETECT_AL_MQTT_TYPE].desc = "match MQTT control packet type";
- sigmatch_table[DETECT_AL_MQTT_TYPE].url = "/rules/mqtt-keywords.html#mqtt-type";
- sigmatch_table[DETECT_AL_MQTT_TYPE].AppLayerTxMatch = DetectMQTTTypeMatch;
- sigmatch_table[DETECT_AL_MQTT_TYPE].Setup = DetectMQTTTypeSetup;
- sigmatch_table[DETECT_AL_MQTT_TYPE].Free = DetectMQTTTypeFree;
-#ifdef UNITTESTS
- sigmatch_table[DETECT_AL_MQTT_TYPE].RegisterTests = MQTTTypeRegisterTests;
-#endif
-
- DetectAppLayerInspectEngineRegister(
- "mqtt.type", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1, DetectEngineInspectGenericList, NULL);
-
- mqtt_type_id = DetectBufferTypeGetByName("mqtt.type");
-}
-
-/**
- * \internal
- * \brief Function to match control packet type of an MQTT Tx
- *
- * \param det_ctx Pointer to the pattern matcher thread.
- * \param f Pointer to the current flow.
- * \param flags Flags.
- * \param state App layer state.
- * \param txv Pointer to the transaction.
- * \param s Pointer to the Signature.
- * \param ctx Pointer to the sigmatch that we will cast into DetectMQTTTypeData.
- *
- * \retval 0 no match.
- * \retval 1 match.
- */
-static int DetectMQTTTypeMatch(DetectEngineThreadCtx *det_ctx,
- Flow *f, uint8_t flags, void *state,
- void *txv, const Signature *s,
- const SigMatchCtx *ctx)
-{
- const uint8_t *de = (const uint8_t *)ctx;
-
- if (!de)
- return 0;
-
- return rs_mqtt_tx_has_type(txv, *de);
-}
-
-/**
- * \internal
- * \brief This function is used to parse options passed via mqtt.type: keyword
- *
- * \param rawstr Pointer to the user provided options
- *
- * \retval de pointer to DetectMQTTTypeData on success
- * \retval NULL on failure
- */
-static uint8_t *DetectMQTTTypeParse(const char *rawstr)
-{
- uint8_t *de = NULL;
- int ret = 0;
-
- ret = rs_mqtt_cstr_message_code(rawstr);
- // negative value denotes invalid input
- if(ret < 0) {
- SCLogError("unknown mqtt.type value %s", rawstr);
- goto error;
- }
-
- de = SCMalloc(sizeof(uint8_t));
- if (unlikely(de == NULL))
- goto error;
-
- *de = (uint8_t) ret;
-
- return de;
-
-error:
- if (de != NULL)
- SCFree(de);
- return NULL;
-}
-
-/**
- * \internal
- * \brief this function is used to add the parsed type query into the current signature
- *
- * \param de_ctx pointer to the Detection Engine Context
- * \param s pointer to the Current Signature
- * \param rawstr pointer to the user provided options
- *
- * \retval 0 on Success
- * \retval -1 on Failure
- */
-static int DetectMQTTTypeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
-{
- uint8_t *de = NULL;
-
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
-
- de = DetectMQTTTypeParse(rawstr);
- if (de == NULL)
- goto error;
-
- if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_MQTT_TYPE, (SigMatchCtx *)de, mqtt_type_id) ==
- NULL) {
- goto error;
- }
-
- return 0;
-
-error:
- if (de != NULL)
- SCFree(de);
- return -1;
-}
-
-/**
- * \internal
- * \brief this function will free memory associated with DetectMQTTTypeData
- *
- * \param de pointer to DetectMQTTTypeData
- */
-void DetectMQTTTypeFree(DetectEngineCtx *de_ctx, void *de_ptr)
-{
- if (de_ptr != NULL)
- SCFree(de_ptr);
-}
-
-/*
- * ONLY TESTS BELOW THIS COMMENT
- */
-
-#ifdef UNITTESTS
-/**
- * \test MQTTTypeTestParse01 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTTypeTestParse01 (void)
-{
- uint8_t *de = NULL;
- de = DetectMQTTTypeParse("CONNECT");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 1);
- DetectMQTTTypeFree(NULL, de);
-
- de = DetectMQTTTypeParse("PINGRESP");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 13);
- DetectMQTTTypeFree(NULL, de);
-
- PASS;
-}
-
-/**
- * \test MQTTTypeTestParse02 is a test for a valid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTTypeTestParse02 (void)
-{
- uint8_t *de = NULL;
- de = DetectMQTTTypeParse("auth");
- FAIL_IF_NULL(de);
- FAIL_IF_NOT(*de == 15);
- DetectMQTTTypeFree(NULL, de);
-
- PASS;
-}
-
-/**
- * \test MQTTTypeTestParse03 is a test for an invalid value
- *
- * \retval 1 on success
- * \retval 0 on failure
- */
-static int MQTTTypeTestParse03 (void)
-{
- uint8_t *de = NULL;
- de = DetectMQTTTypeParse("invalidopt");
- if (de) {
- DetectMQTTTypeFree(NULL, de);
- FAIL;
- }
-
- de = DetectMQTTTypeParse("unassigned");
- if (de) {
- DetectMQTTTypeFree(NULL, de);
- FAIL;
- }
-
- PASS;
-}
-
-#endif /* UNITTESTS */
-
-/**
- * \brief this function registers unit tests for MQTTType
- */
-void MQTTTypeRegisterTests(void)
-{
-#ifdef UNITTESTS
- UtRegisterTest("MQTTTypeTestParse01", MQTTTypeTestParse01);
- UtRegisterTest("MQTTTypeTestParse02", MQTTTypeTestParse02);
- UtRegisterTest("MQTTTypeTestParse03", MQTTTypeTestParse03);
-#endif /* UNITTESTS */
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_TYPE_H
-#define SURICATA_DETECT_MQTT_TYPE_H
-
-void DetectMQTTTypeRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_TYPE_H */
+++ /dev/null
-/* Copyright (C) 2020-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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#include "suricata-common.h"
-
-#include "app-layer.h"
-#include "app-layer-parser.h"
-
-#include "conf.h"
-#include "decode.h"
-#include "detect.h"
-#include "detect-content.h"
-#include "detect-parse.h"
-#include "detect-pcre.h"
-#include "detect-engine.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-engine-mpm.h"
-#include "detect-engine-prefilter.h"
-#include "detect-mqtt-unsubscribe-topic.h"
-#include "util-unittest.h"
-#include "util-unittest-helper.h"
-
-#include "rust-bindings.h"
-
-#include "threads.h"
-
-#include "flow.h"
-#include "flow-util.h"
-#include "flow-var.h"
-
-#include "util-debug.h"
-#include "util-spm.h"
-#include "util-print.h"
-#include "util-profiling.h"
-
-static int DetectMQTTUnsubscribeTopicSetup(DetectEngineCtx *, Signature *, const char *);
-
-static int g_mqtt_unsubscribe_topic_buffer_id = 0;
-
-static uint32_t unsubscribe_topic_match_limit = 100;
-
-static InspectionBuffer *MQTTUnsubscribeTopicGetData(DetectEngineThreadCtx *det_ctx,
- const DetectEngineTransforms *transforms, Flow *f, const uint8_t flags, void *txv,
- int list_id, uint32_t local_id)
-{
- SCEnter();
-
- if (unsubscribe_topic_match_limit > 0 && local_id >= unsubscribe_topic_match_limit)
- return NULL;
-
- InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id);
- if (buffer == NULL)
- return NULL;
- if (buffer->initialized)
- return buffer;
-
- const uint8_t *data;
- uint32_t data_len;
- if (rs_mqtt_tx_get_unsubscribe_topic(txv, local_id, &data, &data_len) == 0) {
- InspectionBufferSetupMultiEmpty(buffer);
- return NULL;
- }
-
- InspectionBufferSetupMulti(buffer, transforms, data, data_len);
- buffer->flags = DETECT_CI_FLAGS_SINGLE;
-
- SCReturnPtr(buffer, "InspectionBuffer");
-}
-
-/**
- * \brief Registration function for keyword: mqtt.unsubscribe.topic
- */
-void DetectMQTTUnsubscribeTopicRegister (void)
-{
- sigmatch_table[DETECT_AL_MQTT_UNSUBSCRIBE_TOPIC].name = "mqtt.unsubscribe.topic";
- sigmatch_table[DETECT_AL_MQTT_UNSUBSCRIBE_TOPIC].desc = "sticky buffer to match MQTT UNSUBSCRIBE topic";
- sigmatch_table[DETECT_AL_MQTT_UNSUBSCRIBE_TOPIC].url = "/rules/mqtt-keywords.html#mqtt-unsubscribe-topic";
- sigmatch_table[DETECT_AL_MQTT_UNSUBSCRIBE_TOPIC].Setup = DetectMQTTUnsubscribeTopicSetup;
- sigmatch_table[DETECT_AL_MQTT_UNSUBSCRIBE_TOPIC].flags |= SIGMATCH_NOOPT;
- sigmatch_table[DETECT_AL_MQTT_UNSUBSCRIBE_TOPIC].flags |= SIGMATCH_INFO_STICKY_BUFFER;
-
- intmax_t val = 0;
- if (ConfGetInt("app-layer.protocols.mqtt.unsubscribe-topic-match-limit", &val)) {
- unsubscribe_topic_match_limit = val;
- }
- if (unsubscribe_topic_match_limit <= 0) {
- SCLogDebug("Using unrestricted MQTT UNSUBSCRIBE topic matching");
- } else {
- SCLogDebug("Using MQTT UNSUBSCRIBE topic match-limit setting of: %i",
- unsubscribe_topic_match_limit);
- }
-
- DetectAppLayerMultiRegister("mqtt.unsubscribe.topic", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
- MQTTUnsubscribeTopicGetData, 1, 1);
-
- DetectBufferTypeSetDescriptionByName("mqtt.unsubscribe.topic",
- "unsubscribe topic query");
-
- g_mqtt_unsubscribe_topic_buffer_id = DetectBufferTypeGetByName("mqtt.unsubscribe.topic");
-
- DetectBufferTypeSupportsMultiInstance("mqtt.unsubscribe.topic");
-}
-
-/**
- * \brief setup the sticky buffer keyword used in the rule
- *
- * \param de_ctx Pointer to the Detection Engine Context
- * \param s Pointer to the Signature to which the current keyword belongs
- * \param str Should hold an empty string always
- *
- * \retval 0 On success
- * \retval -1 On failure
- */
-
-static int DetectMQTTUnsubscribeTopicSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
-{
- if (DetectBufferSetActiveList(de_ctx, s, g_mqtt_unsubscribe_topic_buffer_id) < 0)
- return -1;
- if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
- return -1;
- return 0;
-}
+++ /dev/null
-/* Copyright (C) 2020 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.
- */
-
-/**
- * \file
- *
- * \author Sascha Steinbiss <sascha@steinbiss.name>
- */
-
-#ifndef SURICATA_DETECT_MQTT_UNSUBSCRIBE_TOPIC_H
-#define SURICATA_DETECT_MQTT_UNSUBSCRIBE_TOPIC_H
-
-void DetectMQTTUnsubscribeTopicRegister(void);
-
-#endif /* SURICATA_DETECT_MQTT_UNSUBSCRIBE_TOPIC_H */