diff options
Diffstat (limited to 'rust/src/mqtt/mqtt_property.rs')
-rw-r--r-- | rust/src/mqtt/mqtt_property.rs | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/rust/src/mqtt/mqtt_property.rs b/rust/src/mqtt/mqtt_property.rs new file mode 100644 index 0000000..a716c4b --- /dev/null +++ b/rust/src/mqtt/mqtt_property.rs @@ -0,0 +1,269 @@ +/* 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. + */ + +// written by Sascha Steinbiss <sascha@steinbiss.name> + +use crate::jsonbuilder::{JsonBuilder, JsonError}; +use crate::mqtt::parser::*; +use nom7::number::streaming::*; +use nom7::IResult; + +// TODO: It might be useful to also add detection on property presence and +// content, e.g. mqtt.property: AUTHENTICATION_METHOD. +#[derive(Debug, PartialEq, PartialOrd)] +#[allow(non_camel_case_types)] +pub enum MQTTProperty { + UNKNOWN, + PAYLOAD_FORMAT_INDICATOR(u8), + MESSAGE_EXPIRY_INTERVAL(u32), + CONTENT_TYPE(String), + RESPONSE_TOPIC(String), + CORRELATION_DATA(Vec<u8>), + SUBSCRIPTION_IDENTIFIER(u32), + SESSION_EXPIRY_INTERVAL(u32), + ASSIGNED_CLIENT_IDENTIFIER(String), + SERVER_KEEP_ALIVE(u16), + AUTHENTICATION_METHOD(String), + AUTHENTICATION_DATA(Vec<u8>), + REQUEST_PROBLEM_INFORMATION(u8), + WILL_DELAY_INTERVAL(u32), + REQUEST_RESPONSE_INFORMATION(u8), + RESPONSE_INFORMATION(String), + SERVER_REFERENCE(String), + REASON_STRING(String), + RECEIVE_MAXIMUM(u16), + TOPIC_ALIAS_MAXIMUM(u16), + TOPIC_ALIAS(u16), + MAXIMUM_QOS(u8), + RETAIN_AVAILABLE(u8), + USER_PROPERTY((String, String)), + MAXIMUM_PACKET_SIZE(u32), + WILDCARD_SUBSCRIPTION_AVAILABLE(u8), + SUBSCRIPTION_IDENTIFIER_AVAILABLE(u8), + SHARED_SUBSCRIPTION_AVAILABLE(u8), +} + +impl crate::mqtt::mqtt_property::MQTTProperty { + pub fn set_json(&self, js: &mut JsonBuilder) -> Result<(), JsonError> { + match self { + crate::mqtt::mqtt_property::MQTTProperty::PAYLOAD_FORMAT_INDICATOR(v) => { + js.set_uint("payload_format_indicator", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::MESSAGE_EXPIRY_INTERVAL(v) => { + js.set_uint("message_expiry_interval", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::CONTENT_TYPE(v) => { + js.set_string("content_type", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::RESPONSE_TOPIC(v) => { + js.set_string("response_topic", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::CORRELATION_DATA(v) => { + js.set_string_from_bytes("correlation_data", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::SUBSCRIPTION_IDENTIFIER(v) => { + js.set_uint("subscription_identifier", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::SESSION_EXPIRY_INTERVAL(v) => { + js.set_uint("session_expiry_interval", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::ASSIGNED_CLIENT_IDENTIFIER(v) => { + js.set_string("assigned_client_identifier", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::SERVER_KEEP_ALIVE(v) => { + js.set_uint("server_keep_alive", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::AUTHENTICATION_METHOD(v) => { + js.set_string("authentication_method", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::AUTHENTICATION_DATA(v) => { + js.set_string_from_bytes("authentication_data", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::REQUEST_PROBLEM_INFORMATION(v) => { + js.set_uint("request_problem_information", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::WILL_DELAY_INTERVAL(v) => { + js.set_uint("will_delay_interval", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::REQUEST_RESPONSE_INFORMATION(v) => { + js.set_uint("request_response_information", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::RESPONSE_INFORMATION(v) => { + js.set_string("response_information", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::SERVER_REFERENCE(v) => { + js.set_string("server_reference", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::REASON_STRING(v) => { + js.set_string("reason_string", v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::RECEIVE_MAXIMUM(v) => { + js.set_uint("receive_maximum", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::TOPIC_ALIAS_MAXIMUM(v) => { + js.set_uint("topic_alias_maximum", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::TOPIC_ALIAS(v) => { + js.set_uint("topic_alias", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::MAXIMUM_QOS(v) => { + js.set_uint("maximum_qos", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::RETAIN_AVAILABLE(v) => { + js.set_uint("retain_available", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::USER_PROPERTY((k, v)) => { + js.set_string(k, v)?; + } + crate::mqtt::mqtt_property::MQTTProperty::MAXIMUM_PACKET_SIZE(v) => { + js.set_uint("maximum_packet_size", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::WILDCARD_SUBSCRIPTION_AVAILABLE(v) => { + js.set_uint("wildcard_subscription_available", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::SUBSCRIPTION_IDENTIFIER_AVAILABLE(v) => { + js.set_uint("subscription_identifier_available", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::SHARED_SUBSCRIPTION_AVAILABLE(v) => { + js.set_uint("shared_subscription_available", *v as u64)?; + } + crate::mqtt::mqtt_property::MQTTProperty::UNKNOWN => { + // pass + } + } + Ok(()) + } +} + +#[inline] +pub fn parse_qualified_property(input: &[u8], identifier: u32) -> IResult<&[u8], MQTTProperty> { + match identifier { + 1 => match be_u8(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::PAYLOAD_FORMAT_INDICATOR(val))), + Err(e) => return Err(e), + }, + 2 => match be_u32(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::MESSAGE_EXPIRY_INTERVAL(val))), + Err(e) => return Err(e), + }, + 3 => match parse_mqtt_string(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::CONTENT_TYPE(val))), + Err(e) => return Err(e), + }, + 8 => match parse_mqtt_string(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::RESPONSE_TOPIC(val))), + Err(e) => return Err(e), + }, + 9 => match parse_mqtt_binary_data(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::CORRELATION_DATA(val))), + Err(e) => return Err(e), + }, + 11 => match parse_mqtt_variable_integer(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::SUBSCRIPTION_IDENTIFIER(val))), + Err(e) => return Err(e), + }, + 17 => match be_u32(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::SESSION_EXPIRY_INTERVAL(val))), + Err(e) => return Err(e), + }, + 18 => match parse_mqtt_string(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::ASSIGNED_CLIENT_IDENTIFIER(val))), + Err(e) => return Err(e), + }, + 19 => match be_u16(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::SERVER_KEEP_ALIVE(val))), + Err(e) => return Err(e), + }, + 21 => match parse_mqtt_string(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::AUTHENTICATION_METHOD(val))), + Err(e) => return Err(e), + }, + 22 => match parse_mqtt_binary_data(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::AUTHENTICATION_DATA(val))), + Err(e) => return Err(e), + }, + 23 => match be_u8(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::REQUEST_PROBLEM_INFORMATION(val))), + Err(e) => return Err(e), + }, + 24 => match be_u32(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::WILL_DELAY_INTERVAL(val))), + Err(e) => return Err(e), + }, + 25 => match be_u8(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::REQUEST_RESPONSE_INFORMATION(val))), + Err(e) => return Err(e), + }, + 26 => match parse_mqtt_string(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::RESPONSE_INFORMATION(val))), + Err(e) => return Err(e), + }, + 28 => match parse_mqtt_string(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::SERVER_REFERENCE(val))), + Err(e) => return Err(e), + }, + 31 => match parse_mqtt_string(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::REASON_STRING(val))), + Err(e) => return Err(e), + }, + 33 => match be_u16(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::RECEIVE_MAXIMUM(val))), + Err(e) => return Err(e), + }, + 34 => match be_u16(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::TOPIC_ALIAS_MAXIMUM(val))), + Err(e) => return Err(e), + }, + 35 => match be_u16(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::TOPIC_ALIAS(val))), + Err(e) => return Err(e), + }, + 36 => match be_u8(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::MAXIMUM_QOS(val))), + Err(e) => return Err(e), + }, + 37 => match be_u8(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::RETAIN_AVAILABLE(val))), + Err(e) => return Err(e), + }, + 38 => match parse_mqtt_string_pair(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::USER_PROPERTY(val))), + Err(e) => return Err(e), + }, + 39 => match be_u32(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::MAXIMUM_PACKET_SIZE(val))), + Err(e) => return Err(e), + }, + 40 => match be_u8(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::WILDCARD_SUBSCRIPTION_AVAILABLE(val))), + Err(e) => return Err(e), + }, + 41 => match be_u8(input) { + Ok((rem, val)) => { + return Ok((rem, MQTTProperty::SUBSCRIPTION_IDENTIFIER_AVAILABLE(val))) + } + Err(e) => return Err(e), + }, + 42 => match be_u8(input) { + Ok((rem, val)) => return Ok((rem, MQTTProperty::SHARED_SUBSCRIPTION_AVAILABLE(val))), + Err(e) => return Err(e), + }, + _ => { + return Ok((input, MQTTProperty::UNKNOWN)); + } + } +} |