From 0d07b0d5a8b89348653fa5218f3f5cbbc3ca4352 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Mon, 19 Oct 2020 10:30:29 -0600 Subject: [PATCH 01/18] rust/applayer: define AppLayerEvent trait The derive macro will implement this trait for app-layer event enums. --- rust/src/applayer.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rust/src/applayer.rs b/rust/src/applayer.rs index 58bb36723eea..084e8d0bf9ca 100644 --- a/rust/src/applayer.rs +++ b/rust/src/applayer.rs @@ -415,3 +415,19 @@ macro_rules!export_tx_set_detect_state { } ) } + +/// AppLayerEvent trait that will be implemented on enums that +/// derive AppLayerEvent. +pub trait AppLayerEvent { + /// Return the enum variant of the given ID. + fn from_id(id: i32) -> Option where Self: std::marker::Sized; + + /// Convert the enum variant to a C-style string (suffixed with \0). + fn to_cstring(&self) -> &str; + + /// Return the enum variant for the given name (as a CStr). + fn from_cstring(s: &std::ffi::CStr) -> Option where Self: std::marker::Sized; + + /// Return the ID value of the enum variant. + fn as_i32(&self) -> i32; +} From 0a2ce27dd6e0cb4ccbd54a1da8ed255f877f49e3 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Sun, 12 Jan 2020 22:56:47 -0600 Subject: [PATCH 02/18] rust: derive crate: for custom derives Currently has one derive, AppLayerEvent to be used like: #[derive(AppLayerEvent)] pub enum DNSEvent { MalformedData, NotRequest, NotResponse, ZFlagSet, } Code will be generated to: - Convert enum to a c type string - Convert string to enum variant - Convert id to enum variant --- configure.ac | 2 +- rust/.gitignore | 2 +- rust/Cargo.toml.in | 5 ++ rust/Makefile.am | 2 +- rust/derive/.gitignore | 1 + rust/derive/Cargo.toml.in | 13 ++++ rust/derive/src/applayerevent.rs | 108 +++++++++++++++++++++++++++++++ rust/derive/src/lib.rs | 42 ++++++++++++ 8 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 rust/derive/.gitignore create mode 100644 rust/derive/Cargo.toml.in create mode 100644 rust/derive/src/applayerevent.rs create mode 100644 rust/derive/src/lib.rs diff --git a/configure.ac b/configure.ac index 30d2b4f09300..5d9411a46d8f 100644 --- a/configure.ac +++ b/configure.ac @@ -2694,7 +2694,7 @@ AC_SUBST(enable_non_bundled_htp) AM_CONDITIONAL([BUILD_SHARED_LIBRARY], [test "x$enable_shared" = "xyes"] && [test "x$can_build_shared_library" = "xyes"]) -AC_CONFIG_FILES(Makefile src/Makefile rust/Makefile rust/Cargo.toml rust/.cargo/config) +AC_CONFIG_FILES(Makefile src/Makefile rust/Makefile rust/Cargo.toml rust/derive/Cargo.toml rust/.cargo/config) AC_CONFIG_FILES(qa/Makefile qa/coccinelle/Makefile) AC_CONFIG_FILES(rules/Makefile doc/Makefile doc/userguide/Makefile doc/devguide/Makefile) AC_CONFIG_FILES(contrib/Makefile contrib/file_processor/Makefile contrib/file_processor/Action/Makefile contrib/file_processor/Processor/Makefile) diff --git a/rust/.gitignore b/rust/.gitignore index 09a7c19e6a66..1c81617b24f1 100644 --- a/rust/.gitignore +++ b/rust/.gitignore @@ -1,6 +1,6 @@ !Cargo.toml.in +Cargo.toml /.cargo/config -/Cargo.toml /Cargo.lock /target /vendor diff --git a/rust/Cargo.toml.in b/rust/Cargo.toml.in index 9681b6ac0cc0..60feabb1d8b4 100644 --- a/rust/Cargo.toml.in +++ b/rust/Cargo.toml.in @@ -3,6 +3,9 @@ name = "suricata" version = "@PACKAGE_VERSION@" edition = "2018" +[workspace] +members = [".", "./derive"] + [lib] crate-type = ["staticlib", "rlib"] path = "@e_rustdir@/src/lib.rs" @@ -50,5 +53,7 @@ md-5 = "~0.9.1" regex = "~1.4.2" lazy_static = "~1.4.0" +suricata-derive = { path = "./derive" } + [dev-dependencies] test-case = "~1.1.0" diff --git a/rust/Makefile.am b/rust/Makefile.am index a8c360e42343..8efd135efcac 100644 --- a/rust/Makefile.am +++ b/rust/Makefile.am @@ -73,7 +73,7 @@ maintainerclean-local: check: CARGO_HOME="$(CARGO_HOME)" @rustup_home@ \ CARGO_TARGET_DIR="$(abs_top_builddir)/rust/target" \ - $(CARGO) test $(RELEASE) --features "$(RUST_FEATURES)" + $(CARGO) test --all $(RELEASE) --features "$(RUST_FEATURES)" if HAVE_CARGO_VENDOR vendor: diff --git a/rust/derive/.gitignore b/rust/derive/.gitignore new file mode 100644 index 000000000000..ea8c4bf7f35f --- /dev/null +++ b/rust/derive/.gitignore @@ -0,0 +1 @@ +/target diff --git a/rust/derive/Cargo.toml.in b/rust/derive/Cargo.toml.in new file mode 100644 index 000000000000..b60ab198f3ba --- /dev/null +++ b/rust/derive/Cargo.toml.in @@ -0,0 +1,13 @@ +[package] +name = "suricata-derive" +version = "@PACKAGE_VERSION@" +edition = "2018" + +[lib] +proc-macro = true +path = "@e_rustdir@/derive/src/lib.rs" + +[dependencies] +proc-macro2 = "1.0" +quote = "1.0" +syn = "1.0" diff --git a/rust/derive/src/applayerevent.rs b/rust/derive/src/applayerevent.rs new file mode 100644 index 000000000000..999fa2ea9cd9 --- /dev/null +++ b/rust/derive/src/applayerevent.rs @@ -0,0 +1,108 @@ +/* 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. + */ + +extern crate proc_macro; +use proc_macro::TokenStream; +use quote::quote; +use syn::{self, parse_macro_input, DeriveInput}; + +pub fn derive_app_layer_event(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = input.ident; + + let mut fields = Vec::new(); + let mut vals = Vec::new(); + let mut cstrings = Vec::new(); + let mut names = Vec::new(); + + match input.data { + syn::Data::Enum(ref data) => { + for (i, v) in (&data.variants).into_iter().enumerate() { + fields.push(v.ident.clone()); + let name = transform_name(&v.ident.to_string()); + let cname = format!("{}\0", name); + names.push(name); + cstrings.push(cname); + vals.push(i as i32); + } + } + _ => panic!("AppLayerEvent can only be derived for enums"), + } + + let expanded = quote! { + impl crate::applayer::AppLayerEvent for #name { + fn from_id(id: i32) -> Option<#name> { + match id { + #( #vals => Some(#name::#fields) ,)* + _ => None, + } + } + + fn as_i32(&self) -> i32 { + match *self { + #( #name::#fields => #vals ,)* + } + } + + fn to_cstring(&self) -> &str { + match *self { + #( #name::#fields => #cstrings ,)* + } + } + + fn from_string(s: &str) -> Option<#name> { + match s { + #( #names => Some(#name::#fields) ,)* + _ => None + } + } + } + }; + + proc_macro::TokenStream::from(expanded) +} + +/// Transform names such as "OneTwoThree" to "one_two_three". +pub fn transform_name(in_name: &str) -> String { + let mut out = String::new(); + for (i, c) in in_name.chars().enumerate() { + if i == 0 { + out.push_str(&c.to_lowercase().to_string()); + } else if c.is_uppercase() { + out.push('_'); + out.push_str(&c.to_lowercase().to_string()); + } else { + out.push(c); + } + } + out +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_transform_name() { + assert_eq!(transform_name("One"), "one".to_string()); + assert_eq!(transform_name("SomeEvent"), "some_event".to_string()); + assert_eq!( + transform_name("UnassignedMsgType"), + "unassigned_msg_type".to_string() + ); + } +} diff --git a/rust/derive/src/lib.rs b/rust/derive/src/lib.rs new file mode 100644 index 000000000000..8d0601701e7c --- /dev/null +++ b/rust/derive/src/lib.rs @@ -0,0 +1,42 @@ +/* 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. + */ + +extern crate proc_macro; + +use proc_macro::TokenStream; + +mod applayerevent; + +/// The `AppLayerEvent` derive macro generates a `AppLayerEvent` trait +/// implementation for enums that define AppLayerEvents. +/// +/// Example usage (DNS app-layer events): +/// +/// #[derive(AppLayerEvent)] +/// enum { +/// MalformedData, +/// NotRequest, +/// NotResponse, +/// ZFlagSet, +/// } +/// +/// The enum variants must follow the naming convention of OneTwoThree +/// for proper conversion to the name used in rules (one_tow_three). +#[proc_macro_derive(AppLayerEvent)] +pub fn derive_app_layer_event(input: TokenStream) -> TokenStream { + applayerevent::derive_app_layer_event(input) +} From 8dd1b5449b192475506f56896d247c0910e754c2 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 11:57:22 -0600 Subject: [PATCH 03/18] rust/applayer: provide generic event info functions Provide generic functions for get_event_info and get_event_info_by_id. These functions can be used by any app-layer event enum that implements AppLayerEvent. Unfortunately the parser registration cannot use these functions directly as generic functions cannot be #[no_mangle]. So they do need small extern "C" wrappers around them. --- rust/src/applayer.rs | 59 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/rust/src/applayer.rs b/rust/src/applayer.rs index 084e8d0bf9ca..008610dec2f8 100644 --- a/rust/src/applayer.rs +++ b/rust/src/applayer.rs @@ -18,11 +18,12 @@ //! Parser registration functions and common interface use std; -use crate::core::{DetectEngineState,Flow,AppLayerEventType,AppLayerDecoderEvents,AppProto}; +use crate::core::{self,DetectEngineState,Flow,AppLayerEventType,AppLayerDecoderEvents,AppProto}; use crate::filecontainer::FileContainer; use crate::applayer; use std::os::raw::{c_void,c_char,c_int}; use crate::core::SC; +use std::ffi::CStr; #[repr(C)] #[derive(Default, Debug,PartialEq)] @@ -425,9 +426,61 @@ pub trait AppLayerEvent { /// Convert the enum variant to a C-style string (suffixed with \0). fn to_cstring(&self) -> &str; - /// Return the enum variant for the given name (as a CStr). - fn from_cstring(s: &std::ffi::CStr) -> Option where Self: std::marker::Sized; + /// Return the enum variant for the given name. + fn from_string(s: &str) -> Option where Self: std::marker::Sized; /// Return the ID value of the enum variant. fn as_i32(&self) -> i32; } + +/// Generic `get_info_info` implementation for enums implementing +/// AppLayerEvent. +/// +/// Normally usage of this function will be generated by +/// derive(AppLayerEvent), for example: +/// +/// #[derive(AppLayerEvent)] +/// enum AppEvent { +/// EventOne, +/// EventTwo, +/// } +/// +/// get_event_info::(...) +#[inline(always)] +pub fn get_event_info( + event_name: *const std::os::raw::c_char, + event_id: *mut std::os::raw::c_int, + event_type: *mut core::AppLayerEventType, +) -> std::os::raw::c_int { + if event_name == std::ptr::null() { + return -1; + } + + unsafe { + let event = match CStr::from_ptr(event_name).to_str().map(T::from_string) { + Ok(Some(event)) => event.as_i32(), + _ => -1, + }; + *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; + *event_id = event as std::os::raw::c_int; + return 0; + } +} + +/// Generic `get_info_info_by_id` implementation for enums implementing +/// AppLayerEvent. +#[inline(always)] +pub fn get_event_info_by_id( + event_id: std::os::raw::c_int, + event_name: *mut *const std::os::raw::c_char, + event_type: *mut core::AppLayerEventType, +) -> i8 { + if let Some(e) = T::from_id(event_id as i32) { + unsafe { + *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char; + *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; + } + return 0; + } + return -1; +} From 2ed4c0cacacc59a0b74562fca9a2db6c3089e43f Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Mon, 19 Oct 2020 11:17:48 -0600 Subject: [PATCH 04/18] applayerevent: derive get_event_info and get_event_info_by_id Add generation of wrapper functions for get_event_info and get_event_info_by_id to the derive macro. Eliminates the need for the wrapper method to be created by the parser author. --- rust/derive/src/applayerevent.rs | 17 ++++++++++++++ rust/src/applayer.rs | 38 +++++++++++++++++++------------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/rust/derive/src/applayerevent.rs b/rust/derive/src/applayerevent.rs index 999fa2ea9cd9..88339d6dd844 100644 --- a/rust/derive/src/applayerevent.rs +++ b/rust/derive/src/applayerevent.rs @@ -70,6 +70,23 @@ pub fn derive_app_layer_event(input: TokenStream) -> TokenStream { _ => None } } + + unsafe extern "C" fn get_event_info( + event_name: *const std::os::raw::c_char, + event_id: *mut std::os::raw::c_int, + event_type: *mut crate::core::AppLayerEventType, + ) -> std::os::raw::c_int { + crate::applayer::get_event_info::<#name>(event_name, event_id, event_type) + } + + unsafe extern "C" fn get_event_info_by_id( + event_id: std::os::raw::c_int, + event_name: *mut *const std::os::raw::c_char, + event_type: *mut crate::core::AppLayerEventType, + ) -> i8 { + crate::applayer::get_event_info_by_id::<#name>(event_id, event_name, event_type) + } + } }; diff --git a/rust/src/applayer.rs b/rust/src/applayer.rs index 008610dec2f8..5568fb71d5a8 100644 --- a/rust/src/applayer.rs +++ b/rust/src/applayer.rs @@ -431,6 +431,18 @@ pub trait AppLayerEvent { /// Return the ID value of the enum variant. fn as_i32(&self) -> i32; + + unsafe extern "C" fn get_event_info( + event_name: *const std::os::raw::c_char, + event_id: *mut std::os::raw::c_int, + event_type: *mut core::AppLayerEventType, + ) -> std::os::raw::c_int; + + unsafe extern "C" fn get_event_info_by_id( + event_id: std::os::raw::c_int, + event_name: *mut *const std::os::raw::c_char, + event_type: *mut core::AppLayerEventType, + ) -> i8; } /// Generic `get_info_info` implementation for enums implementing @@ -447,7 +459,7 @@ pub trait AppLayerEvent { /// /// get_event_info::(...) #[inline(always)] -pub fn get_event_info( +pub unsafe fn get_event_info( event_name: *const std::os::raw::c_char, event_id: *mut std::os::raw::c_int, event_type: *mut core::AppLayerEventType, @@ -456,30 +468,26 @@ pub fn get_event_info( return -1; } - unsafe { - let event = match CStr::from_ptr(event_name).to_str().map(T::from_string) { - Ok(Some(event)) => event.as_i32(), - _ => -1, - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - return 0; - } + let event = match CStr::from_ptr(event_name).to_str().map(T::from_string) { + Ok(Some(event)) => event.as_i32(), + _ => -1, + }; + *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; + *event_id = event as std::os::raw::c_int; + return 0; } /// Generic `get_info_info_by_id` implementation for enums implementing /// AppLayerEvent. #[inline(always)] -pub fn get_event_info_by_id( +pub unsafe fn get_event_info_by_id( event_id: std::os::raw::c_int, event_name: *mut *const std::os::raw::c_char, event_type: *mut core::AppLayerEventType, ) -> i8 { if let Some(e) = T::from_id(event_id as i32) { - unsafe { - *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - } + *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char; + *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; return 0; } return -1; From 982827e8b6001b973bc96151d5a73885baa5423a Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Sun, 12 Jan 2020 23:13:54 -0600 Subject: [PATCH 05/18] dns: use derive macro for DNSEvent --- rust/Makefile.am | 2 +- rust/src/dns/dns.rs | 110 ++++++++++++-------------------------------- rust/src/lib.rs | 3 ++ 3 files changed, 33 insertions(+), 82 deletions(-) diff --git a/rust/Makefile.am b/rust/Makefile.am index 8efd135efcac..aa2b571789e4 100644 --- a/rust/Makefile.am +++ b/rust/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = src \ +EXTRA_DIST = src derive \ .cargo/config.in \ cbindgen.toml \ dist/rust-bindings.h diff --git a/rust/src/dns/dns.rs b/rust/src/dns/dns.rs index 467c5a9acb0d..3e0031e3e968 100644 --- a/rust/src/dns/dns.rs +++ b/rust/src/dns/dns.rs @@ -115,84 +115,12 @@ pub const DNS_RCODE_BADTRUNC: u16 = 22; static mut ALPROTO_DNS: AppProto = ALPROTO_UNKNOWN; -#[repr(u32)] +#[derive(Debug, PartialEq, AppLayerEvent)] pub enum DNSEvent { - MalformedData = 0, - NotRequest = 1, - NotResponse = 2, - ZFlagSet = 3, -} - -impl DNSEvent { - pub fn to_cstring(&self) -> &str { - match *self { - DNSEvent::MalformedData => "MALFORMED_DATA\0", - DNSEvent::NotRequest => "NOT_A_REQUEST\0", - DNSEvent::NotResponse => "NOT_A_RESPONSE\0", - DNSEvent::ZFlagSet => "Z_FLAG_SET\0", - } - } - - pub fn from_id(id: u32) -> Option { - match id { - 0 => Some(DNSEvent::MalformedData), - 1 => Some(DNSEvent::NotRequest), - 2 => Some(DNSEvent::NotResponse), - 4 => Some(DNSEvent::ZFlagSet), - _ => None, - } - } - - pub fn from_string(s: &str) -> Option { - match s.to_lowercase().as_ref() { - "malformed_data" => Some(DNSEvent::MalformedData), - "not_a_request" => Some(DNSEvent::NotRequest), - "not_a_response" => Some(DNSEvent::NotRequest), - "z_flag_set" => Some(DNSEvent::ZFlagSet), - _ => None - } - } -} - -#[no_mangle] -pub unsafe extern "C" fn rs_dns_state_get_event_info_by_id( - event_id: std::os::raw::c_int, - event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType, -) -> i8 { - if let Some(e) = DNSEvent::from_id(event_id as u32) { - *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - return 0; - } - return -1; -} - -#[no_mangle] -pub unsafe extern "C" fn rs_dns_state_get_event_info( - event_name: *const std::os::raw::c_char, - event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType -) -> std::os::raw::c_int { - if event_name == std::ptr::null() { - return -1; - } - - let event_name = std::ffi::CStr::from_ptr(event_name); - if let Ok(event_name) = event_name.to_str() { - if let Some(event) = DNSEvent::from_string(event_name) { - *event_id = event as std::os::raw::c_int; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - } else { - // Unknown event... - return -1; - } - } else { - // UTF-8 conversion failed. Should not happen. - return -1; - } - - return 0; + MalformedData, + NotRequest, + NotResponse, + ZFlagSet, } #[derive(Debug,PartialEq)] @@ -1058,8 +986,8 @@ pub unsafe extern "C" fn rs_dns_udp_register_parser() { tx_comp_st_tc: 1, tx_get_progress: rs_dns_tx_get_alstate_progress, get_events: Some(rs_dns_state_get_events), - get_eventinfo: Some(rs_dns_state_get_event_info), - get_eventinfo_byid: Some(rs_dns_state_get_event_info_by_id), + get_eventinfo: Some(DNSEvent::get_event_info), + get_eventinfo_byid: Some(DNSEvent::get_event_info_by_id), localstorage_new: None, localstorage_free: None, get_files: None, @@ -1104,8 +1032,8 @@ pub unsafe extern "C" fn rs_dns_tcp_register_parser() { tx_comp_st_tc: 1, tx_get_progress: rs_dns_tx_get_alstate_progress, get_events: Some(rs_dns_state_get_events), - get_eventinfo: Some(rs_dns_state_get_event_info), - get_eventinfo_byid: Some(rs_dns_state_get_event_info_by_id), + get_eventinfo: Some(DNSEvent::get_event_info), + get_eventinfo_byid: Some(DNSEvent::get_event_info_by_id), localstorage_new: None, localstorage_free: None, get_files: None, @@ -1532,4 +1460,24 @@ mod tests { state.parse_request_tcp(buf3) ); } + + #[test] + fn test_dns_event_from_id() { + assert_eq!(DNSEvent::from_id(0), Some(DNSEvent::MalformedData)); + assert_eq!(DNSEvent::from_id(3), Some(DNSEvent::ZFlagSet)); + assert_eq!(DNSEvent::from_id(9), None); + } + + #[test] + fn test_dns_event_to_cstring() { + assert_eq!(DNSEvent::MalformedData.to_cstring(), "malformed_data\0"); + } + + #[test] + fn test_dns_event_from_string() { + let name = "malformed_data"; + let event = DNSEvent::from_string(&name).unwrap(); + assert_eq!(event, DNSEvent::MalformedData); + assert_eq!(event.to_cstring(), format!("{}\0", name)); + } } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index f27f76b94dd3..f1b38edd5d0f 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -85,6 +85,9 @@ extern crate kerberos_parser; extern crate tls_parser; extern crate x509_parser; +#[macro_use] +extern crate suricata_derive; + #[macro_use] pub mod log; From 3bd51a76c06ec9375664f92595a07d106d223364 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Fri, 16 Oct 2020 15:45:37 -0600 Subject: [PATCH 06/18] mqtt: derive AppLayerEvent for MQTTEvent --- rust/src/mqtt/mqtt.rs | 72 +++++-------------------------------------- 1 file changed, 7 insertions(+), 65 deletions(-) diff --git a/rust/src/mqtt/mqtt.rs b/rust/src/mqtt/mqtt.rs index 7403245f2ac0..15e62920cdec 100644 --- a/rust/src/mqtt/mqtt.rs +++ b/rust/src/mqtt/mqtt.rs @@ -22,10 +22,9 @@ use super::parser::*; use crate::applayer::{self, LoggerFlags}; use crate::applayer::*; use crate::core::{self, AppProto, Flow, ALPROTO_FAILED, ALPROTO_UNKNOWN, IPPROTO_TCP}; -use num_traits::FromPrimitive; use nom; use std; -use std::ffi::{CStr,CString}; +use std::ffi::CString; // Used as a special pseudo packet identifier to denote the first CONNECT // packet in a connection. Note that there is no risk of collision with a @@ -38,10 +37,9 @@ static mut MAX_MSG_LEN: u32 = 1048576; static mut ALPROTO_MQTT: AppProto = ALPROTO_UNKNOWN; -#[derive(FromPrimitive, Debug)] -#[repr(u32)] +#[derive(FromPrimitive, Debug, AppLayerEvent)] pub enum MQTTEvent { - MissingConnect = 0, + MissingConnect, MissingPublish, MissingSubscribe, MissingUnsubscribe, @@ -49,7 +47,7 @@ pub enum MQTTEvent { UnintroducedMessage, InvalidQosLevel, MissingMsgId, - UnassignedMsgtype, + UnassignedMsgType, } #[derive(Debug)] @@ -368,7 +366,7 @@ impl MQTTState { MQTTOperation::UNASSIGNED => { let mut tx = self.new_tx(msg, toclient); tx.complete = true; - MQTTState::set_event(&mut tx, MQTTEvent::UnassignedMsgtype); + MQTTState::set_event(&mut tx, MQTTEvent::UnassignedMsgType); self.transactions.push(tx); }, MQTTOperation::TRUNCATED(_) => { @@ -702,62 +700,6 @@ pub unsafe extern "C" fn rs_mqtt_state_get_events( return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_mqtt_state_get_event_info_by_id(event_id: std::os::raw::c_int, - event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType) - -> i8 -{ - if let Some(e) = FromPrimitive::from_i32(event_id as i32) { - let estr = match e { - MQTTEvent::MissingConnect => { "missing_connect\0" }, - MQTTEvent::MissingPublish => { "missing_publish\0" }, - MQTTEvent::MissingSubscribe => { "missing_subscribe\0" }, - MQTTEvent::MissingUnsubscribe => { "missing_unsubscribe\0" }, - MQTTEvent::DoubleConnect => { "double_connect\0" }, - MQTTEvent::UnintroducedMessage => { "unintroduced_message\0" }, - MQTTEvent::InvalidQosLevel => { "invalid_qos_level\0" }, - MQTTEvent::MissingMsgId => { "missing_msg_id\0" }, - MQTTEvent::UnassignedMsgtype => { "unassigned_msg_type\0" }, - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} - -#[no_mangle] -pub unsafe extern "C" fn rs_mqtt_state_get_event_info(event_name: *const std::os::raw::c_char, - event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType) - -> std::os::raw::c_int -{ - if event_name == std::ptr::null() { return -1; } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "missing_connect" => MQTTEvent::MissingConnect as i32, - "missing_publish" => MQTTEvent::MissingPublish as i32, - "missing_subscribe" => MQTTEvent::MissingSubscribe as i32, - "missing_unsubscribe" => MQTTEvent::MissingUnsubscribe as i32, - "double_connect" => MQTTEvent::DoubleConnect as i32, - "unintroduced_message" => MQTTEvent::UnintroducedMessage as i32, - "invalid_qos_level" => MQTTEvent::InvalidQosLevel as i32, - "missing_msg_id" => MQTTEvent::MissingMsgId as i32, - "unassigned_msg_type" => MQTTEvent::UnassignedMsgtype as i32, - _ => -1, // unknown event - } - }, - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} - #[no_mangle] pub unsafe extern "C" fn rs_mqtt_state_get_tx_iterator( _ipproto: u8, @@ -811,8 +753,8 @@ pub unsafe extern "C" fn rs_mqtt_register_parser(cfg_max_msg_len: u32) { get_de_state: rs_mqtt_tx_get_detect_state, set_de_state: rs_mqtt_tx_set_detect_state, get_events: Some(rs_mqtt_state_get_events), - get_eventinfo: Some(rs_mqtt_state_get_event_info), - get_eventinfo_byid: Some(rs_mqtt_state_get_event_info_by_id), + get_eventinfo: Some(MQTTEvent::get_event_info), + get_eventinfo_byid: Some(MQTTEvent::get_event_info_by_id), localstorage_new: None, localstorage_free: None, get_files: None, From aa1463d91740b9a6bea09cfbd57dd425634b3434 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Mon, 19 Oct 2020 12:28:15 -0600 Subject: [PATCH 07/18] smb: use derived get_event_info/get_event_info_by_id --- rust/src/smb/events.rs | 49 +++++++---------------------------- rust/src/smb/smb.rs | 58 ++++++++++-------------------------------- 2 files changed, 23 insertions(+), 84 deletions(-) diff --git a/rust/src/smb/events.rs b/rust/src/smb/events.rs index 1b29da7d4394..8fb27a0cc69f 100644 --- a/rust/src/smb/events.rs +++ b/rust/src/smb/events.rs @@ -18,47 +18,16 @@ use crate::core::*; use crate::smb::smb::*; -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum SMBEvent { - InternalError = 0, - MalformedData = 1, - RecordOverflow = 2, - MalformedNtlmsspRequest = 3, - MalformedNtlmsspResponse = 4, - DuplicateNegotiate = 5, - NegotiateMalformedDialects = 6, - FileOverlap = 7, -} - -impl SMBEvent { - pub fn from_i32(value: i32) -> Option { - match value { - 0 => Some(SMBEvent::InternalError), - 1 => Some(SMBEvent::MalformedData), - 2 => Some(SMBEvent::RecordOverflow), - 3 => Some(SMBEvent::MalformedNtlmsspRequest), - 4 => Some(SMBEvent::MalformedNtlmsspResponse), - 5 => Some(SMBEvent::DuplicateNegotiate), - 6 => Some(SMBEvent::NegotiateMalformedDialects), - 7 => Some(SMBEvent::FileOverlap), - _ => None, - } - } -} - -pub fn smb_str_to_event(instr: &str) -> i32 { - SCLogDebug!("checking {}", instr); - match instr { - "internal_error" => SMBEvent::InternalError as i32, - "malformed_data" => SMBEvent::MalformedData as i32, - "record_overflow" => SMBEvent::RecordOverflow as i32, - "malformed_ntlmssp_request" => SMBEvent::MalformedNtlmsspRequest as i32, - "malformed_ntlmssp_response" => SMBEvent::MalformedNtlmsspResponse as i32, - "duplicate_negotiate" => SMBEvent::DuplicateNegotiate as i32, - "negotiate_malformed_dialects" => SMBEvent::NegotiateMalformedDialects as i32, - "file_overlap" => SMBEvent::FileOverlap as i32, - _ => -1, - } + InternalError, + MalformedData, + RecordOverflow, + MalformedNtlmsspRequest, + MalformedNtlmsspResponse, + DuplicateNegotiate, + NegotiateMalformedDialects, + FileOverlap, } impl SMBTransaction { diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index 44e8b7c101fe..bd563efc4b42 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -27,7 +27,7 @@ use std; use std::str; -use std::ffi::{self, CStr, CString}; +use std::ffi::{self, CString}; use std::collections::HashMap; @@ -38,6 +38,7 @@ use crate::applayer; use crate::applayer::*; use crate::conf::*; use crate::filecontainer::*; +use crate::applayer::{AppLayerResult, AppLayerTxData, AppLayerEvent}; use crate::smb::nbss_records::*; use crate::smb::smb1_records::*; @@ -2137,52 +2138,21 @@ pub unsafe extern "C" fn rs_smb_state_get_events(tx: *mut std::os::raw::c_void) } #[no_mangle] -pub unsafe extern "C" fn rs_smb_state_get_event_info_by_id(event_id: std::os::raw::c_int, - event_name: *mut *const std::os::raw::c_char, - event_type: *mut AppLayerEventType) - -> i8 -{ - if let Some(e) = SMBEvent::from_i32(event_id as i32) { - let estr = match e { - SMBEvent::InternalError => { "internal_error\0" }, - SMBEvent::MalformedData => { "malformed_data\0" }, - SMBEvent::RecordOverflow => { "record_overflow\0" }, - SMBEvent::MalformedNtlmsspRequest => { "malformed_ntlmssp_request\0" }, - SMBEvent::MalformedNtlmsspResponse => { "malformed_ntlmssp_response\0" }, - SMBEvent::DuplicateNegotiate => { "duplicate_negotiate\0" }, - SMBEvent::NegotiateMalformedDialects => { "netogiate_malformed_dialects\0" }, - SMBEvent::FileOverlap => { "file_overlap\0" }, - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } +pub unsafe extern "C" fn rs_smb_state_get_event_info_by_id( + event_id: std::os::raw::c_int, + event_name: *mut *const std::os::raw::c_char, + event_type: *mut AppLayerEventType, +) -> i8 { + SMBEvent::get_event_info_by_id(event_id, event_name, event_type) } #[no_mangle] -pub unsafe extern "C" fn rs_smb_state_get_event_info(event_name: *const std::os::raw::c_char, - event_id: *mut std::os::raw::c_int, - event_type: *mut AppLayerEventType) - -> i32 -{ - if event_name == std::ptr::null() { - return -1; - } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - smb_str_to_event(s) - }, - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - if event == -1 { - return -1; - } - 0 +pub unsafe extern "C" fn rs_smb_state_get_event_info( + event_name: *const std::os::raw::c_char, + event_id: *mut std::os::raw::c_int, + event_type: *mut AppLayerEventType, +) -> std::os::raw::c_int { + SMBEvent::get_event_info(event_name, event_id, event_type) } pub unsafe extern "C" fn smb3_probe_tcp(f: *const Flow, dir: u8, input: *const u8, len: u32, rdir: *mut u8) -> u16 { From d10d7dd4027d6a886de5e4ca0730ab0ff0b58b67 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 15:57:53 -0600 Subject: [PATCH 08/18] dhcp: use derived app-layer event --- rust/src/dhcp/dhcp.rs | 64 ++++--------------------------------------- 1 file changed, 5 insertions(+), 59 deletions(-) diff --git a/rust/src/dhcp/dhcp.rs b/rust/src/dhcp/dhcp.rs index 73b1679ed771..7d8ce68943f7 100644 --- a/rust/src/dhcp/dhcp.rs +++ b/rust/src/dhcp/dhcp.rs @@ -21,7 +21,7 @@ use crate::core::{ALPROTO_UNKNOWN, AppProto, Flow, IPPROTO_UDP}; use crate::core::{sc_detect_engine_state_free, sc_app_layer_decoder_events_free_events}; use crate::dhcp::parser::*; use std; -use std::ffi::{CStr,CString}; +use std::ffi::CString; static mut ALPROTO_DHCP: AppProto = ALPROTO_UNKNOWN; @@ -67,22 +67,12 @@ pub const DHCP_PARAM_NTP_SERVER: u8 = 42; pub const DHCP_PARAM_TFTP_SERVER_NAME: u8 = 66; pub const DHCP_PARAM_TFTP_SERVER_IP: u8 = 150; -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum DHCPEvent { - TruncatedOptions = 0, + TruncatedOptions, MalformedOptions, } -impl DHCPEvent { - fn from_i32(value: i32) -> Option { - match value { - 0 => Some(DHCPEvent::TruncatedOptions), - 1 => Some(DHCPEvent::MalformedOptions), - _ => None, - } - } -} - /// The concept of a transaction is more to satisfy the Suricata /// app-layer. This DHCP parser is actually stateless where each /// message is its own transaction. @@ -306,24 +296,6 @@ pub unsafe extern "C" fn rs_dhcp_state_free(state: *mut std::os::raw::c_void) { std::mem::drop(Box::from_raw(state as *mut DHCPState)); } -#[no_mangle] -pub unsafe extern "C" fn rs_dhcp_state_get_event_info_by_id(event_id: std::os::raw::c_int, - event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType) - -> i8 -{ - if let Some(e) = DHCPEvent::from_i32(event_id as i32) { - let estr = match e { - DHCPEvent::TruncatedOptions => { "truncated_options\0" }, - DHCPEvent::MalformedOptions => { "malformed_options\0" }, - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} #[no_mangle] pub unsafe extern "C" fn rs_dhcp_state_get_events(tx: *mut std::os::raw::c_void) -> *mut core::AppLayerDecoderEvents @@ -332,32 +304,6 @@ pub unsafe extern "C" fn rs_dhcp_state_get_events(tx: *mut std::os::raw::c_void) return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_dhcp_state_get_event_info( - event_name: *const std::os::raw::c_char, - event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType) - -> std::os::raw::c_int -{ - if event_name == std::ptr::null() { - return -1; - } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "malformed_options" => DHCPEvent::MalformedOptions as i32, - "truncated_options" => DHCPEvent::TruncatedOptions as i32, - _ => -1, // unknown event - } - }, - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} - #[no_mangle] pub unsafe extern "C" fn rs_dhcp_state_get_tx_iterator( _ipproto: u8, @@ -411,8 +357,8 @@ pub unsafe extern "C" fn rs_dhcp_register_parser() { get_de_state : rs_dhcp_tx_get_detect_state, set_de_state : rs_dhcp_tx_set_detect_state, get_events : Some(rs_dhcp_state_get_events), - get_eventinfo : Some(rs_dhcp_state_get_event_info), - get_eventinfo_byid : None, + get_eventinfo : Some(DHCPEvent::get_event_info), + get_eventinfo_byid : Some(DHCPEvent::get_event_info_by_id), localstorage_new : None, localstorage_free : None, get_files : None, From 050d634ccaec3b54f7e70e2495ba20bfe988e143 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 16:01:04 -0600 Subject: [PATCH 09/18] ssh: use derived app-layer event --- rust/src/ssh/ssh.rs | 68 ++++----------------------------------------- 1 file changed, 5 insertions(+), 63 deletions(-) diff --git a/rust/src/ssh/ssh.rs b/rust/src/ssh/ssh.rs index 0ebad5cb10c2..23e74a4dbd8d 100644 --- a/rust/src/ssh/ssh.rs +++ b/rust/src/ssh/ssh.rs @@ -19,7 +19,7 @@ use super::parser; use crate::applayer::*; use crate::core::STREAM_TOSERVER; use crate::core::{self, AppProto, Flow, ALPROTO_UNKNOWN, IPPROTO_TCP}; -use std::ffi::{CStr, CString}; +use std::ffi::CString; use std::sync::atomic::{AtomicBool, Ordering}; static mut ALPROTO_SSH: AppProto = ALPROTO_UNKNOWN; @@ -29,26 +29,14 @@ fn hassh_is_enabled() -> bool { HASSH_ENABLED.load(Ordering::Relaxed) } -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum SSHEvent { - InvalidBanner = 0, + InvalidBanner, LongBanner, InvalidRecord, LongKexRecord, } -impl SSHEvent { - fn from_i32(value: i32) -> Option { - match value { - 0 => Some(SSHEvent::InvalidBanner), - 1 => Some(SSHEvent::LongBanner), - 2 => Some(SSHEvent::InvalidRecord), - 3 => Some(SSHEvent::LongKexRecord), - _ => None, - } - } -} - #[repr(u8)] #[derive(Copy, Clone, PartialOrd, PartialEq)] pub enum SSHConnectionState { @@ -376,52 +364,6 @@ pub unsafe extern "C" fn rs_ssh_state_get_events( return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_ssh_state_get_event_info( - event_name: *const std::os::raw::c_char, event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType, -) -> std::os::raw::c_int { - if event_name == std::ptr::null() { - return -1; - } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "invalid_banner" => SSHEvent::InvalidBanner as i32, - "long_banner" => SSHEvent::LongBanner as i32, - "invalid_record" => SSHEvent::InvalidRecord as i32, - "long_kex_record" => SSHEvent::LongKexRecord as i32, - _ => -1, // unknown event - } - } - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} - -#[no_mangle] -pub unsafe extern "C" fn rs_ssh_state_get_event_info_by_id( - event_id: std::os::raw::c_int, event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType, -) -> i8 { - if let Some(e) = SSHEvent::from_i32(event_id as i32) { - let estr = match e { - SSHEvent::InvalidBanner => "invalid_banner\0", - SSHEvent::LongBanner => "long_banner\0", - SSHEvent::InvalidRecord => "invalid_record\0", - SSHEvent::LongKexRecord => "long_kex_record\0", - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} - #[no_mangle] pub extern "C" fn rs_ssh_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void { let state = SSHState::new(); @@ -547,8 +489,8 @@ pub unsafe extern "C" fn rs_ssh_register_parser() { get_de_state: rs_ssh_tx_get_detect_state, set_de_state: rs_ssh_tx_set_detect_state, get_events: Some(rs_ssh_state_get_events), - get_eventinfo: Some(rs_ssh_state_get_event_info), - get_eventinfo_byid: Some(rs_ssh_state_get_event_info_by_id), + get_eventinfo: Some(SSHEvent::get_event_info), + get_eventinfo_byid: Some(SSHEvent::get_event_info_by_id), localstorage_new: None, localstorage_free: None, get_files: None, From a1424c26fd7f897b099a6b4f61772d6bb0e6b0f9 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 16:03:50 -0600 Subject: [PATCH 10/18] snmp: use derived app-layer event --- rust/src/snmp/snmp.rs | 64 ++++--------------------------------------- 1 file changed, 5 insertions(+), 59 deletions(-) diff --git a/rust/src/snmp/snmp.rs b/rust/src/snmp/snmp.rs index aee0b373e0ee..2789ef185ee2 100644 --- a/rust/src/snmp/snmp.rs +++ b/rust/src/snmp/snmp.rs @@ -22,7 +22,7 @@ use crate::core; use crate::core::{AppProto,Flow,ALPROTO_UNKNOWN,ALPROTO_FAILED,STREAM_TOSERVER,STREAM_TOCLIENT}; use crate::applayer::{self, *}; use std; -use std::ffi::{CStr,CString}; +use std::ffi::CString; use der_parser::ber::BerObjectContent; use der_parser::der::parse_der_sequence; @@ -31,23 +31,13 @@ use nom; use nom::IResult; use nom::error::ErrorKind; -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum SNMPEvent { - MalformedData = 0, + MalformedData, UnknownSecurityModel, VersionMismatch, } -impl SNMPEvent { - fn from_i32(value: i32) -> Option { - match value { - 0 => Some(SNMPEvent::MalformedData), - 1 => Some(SNMPEvent::UnknownSecurityModel), - _ => None, - } - } -} - pub struct SNMPState<'a> { /// SNMP protocol version pub version: u32, @@ -403,50 +393,6 @@ pub unsafe extern "C" fn rs_snmp_state_get_events(tx: *mut std::os::raw::c_void) return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_snmp_state_get_event_info_by_id(event_id: std::os::raw::c_int, - event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType) - -> i8 -{ - if let Some(e) = SNMPEvent::from_i32(event_id as i32) { - let estr = match e { - SNMPEvent::MalformedData => { "malformed_data\0" }, - SNMPEvent::UnknownSecurityModel => { "unknown_security_model\0" }, - SNMPEvent::VersionMismatch => { "version_mismatch\0" }, - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} - -#[no_mangle] -pub unsafe extern "C" fn rs_snmp_state_get_event_info(event_name: *const std::os::raw::c_char, - event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType) - -> std::os::raw::c_int -{ - if event_name == std::ptr::null() { return -1; } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "malformed_data" => SNMPEvent::MalformedData as i32, - "unknown_security_model" => SNMPEvent::UnknownSecurityModel as i32, - "version_mismatch" => SNMPEvent::VersionMismatch as i32, - _ => -1, // unknown event - } - }, - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} - // for use with the C API call StateGetTxIterator #[no_mangle] pub extern "C" fn rs_snmp_state_get_tx_iterator( @@ -563,8 +509,8 @@ pub unsafe extern "C" fn rs_register_snmp_parser() { get_de_state : rs_snmp_state_get_tx_detect_state, set_de_state : rs_snmp_state_set_tx_detect_state, get_events : Some(rs_snmp_state_get_events), - get_eventinfo : Some(rs_snmp_state_get_event_info), - get_eventinfo_byid : Some(rs_snmp_state_get_event_info_by_id), + get_eventinfo : Some(SNMPEvent::get_event_info), + get_eventinfo_byid : Some(SNMPEvent::get_event_info_by_id), localstorage_new : None, localstorage_free : None, get_files : None, From dd5d8d97f0a17e67a9fbfdecde9e8f9a76c5b3b9 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 16:07:52 -0600 Subject: [PATCH 11/18] sip: use derived app-layer event --- rust/src/sip/sip.rs | 64 ++++----------------------------------------- 1 file changed, 5 insertions(+), 59 deletions(-) diff --git a/rust/src/sip/sip.rs b/rust/src/sip/sip.rs index 0a83e845818e..e9b155507814 100755 --- a/rust/src/sip/sip.rs +++ b/rust/src/sip/sip.rs @@ -24,24 +24,14 @@ use crate::core; use crate::core::{sc_detect_engine_state_free, AppProto, Flow, ALPROTO_UNKNOWN}; use crate::sip::parser::*; use std; -use std::ffi::{CStr, CString}; +use std::ffi::CString; -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum SIPEvent { - IncompleteData = 0, + IncompleteData, InvalidData, } -impl SIPEvent { - fn from_i32(value: i32) -> Option { - match value { - 0 => Some(SIPEvent::IncompleteData), - 1 => Some(SIPEvent::InvalidData), - _ => None, - } - } -} - pub struct SIPState { transactions: Vec, tx_id: u64, @@ -242,50 +232,6 @@ pub unsafe extern "C" fn rs_sip_state_get_events( return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_sip_state_get_event_info( - event_name: *const std::os::raw::c_char, - event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType, -) -> std::os::raw::c_int { - if event_name == std::ptr::null() { - return -1; - } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "incomplete_data" => SIPEvent::IncompleteData as i32, - "invalid_data" => SIPEvent::InvalidData as i32, - _ => -1, // unknown event - } - } - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} - -#[no_mangle] -pub unsafe extern "C" fn rs_sip_state_get_event_info_by_id( - event_id: std::os::raw::c_int, - event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType, -) -> i8 { - if let Some(e) = SIPEvent::from_i32(event_id as i32) { - let estr = match e { - SIPEvent::IncompleteData => "incomplete_data\0", - SIPEvent::InvalidData => "invalid_data\0", - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} - static mut ALPROTO_SIP: AppProto = ALPROTO_UNKNOWN; #[no_mangle] @@ -376,8 +322,8 @@ pub unsafe extern "C" fn rs_sip_register_parser() { get_de_state: rs_sip_state_get_tx_detect_state, set_de_state: rs_sip_state_set_tx_detect_state, get_events: Some(rs_sip_state_get_events), - get_eventinfo: Some(rs_sip_state_get_event_info), - get_eventinfo_byid: Some(rs_sip_state_get_event_info_by_id), + get_eventinfo: Some(SIPEvent::get_event_info), + get_eventinfo_byid: Some(SIPEvent::get_event_info_by_id), localstorage_new: None, localstorage_free: None, get_files: None, From 2d1b70b04efd02faecec3a7ab608e902d1cc909e Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 16:11:48 -0600 Subject: [PATCH 12/18] rfb: register None for get_event_info/get_event_info_by_id Implementations are not required if they're just going to return -1. We allow None to be registered for that. --- rust/src/rfb/rfb.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/rust/src/rfb/rfb.rs b/rust/src/rfb/rfb.rs index 0059c7bd18cb..da211cb7cfc5 100644 --- a/rust/src/rfb/rfb.rs +++ b/rust/src/rfb/rfb.rs @@ -612,22 +612,6 @@ pub unsafe extern "C" fn rs_rfb_state_get_events( return tx.events; } -#[no_mangle] -pub extern "C" fn rs_rfb_state_get_event_info( - _event_name: *const std::os::raw::c_char, - _event_id: *mut std::os::raw::c_int, - _event_type: *mut core::AppLayerEventType, -) -> std::os::raw::c_int { - return -1; -} - -#[no_mangle] -pub extern "C" fn rs_rfb_state_get_event_info_by_id(_event_id: std::os::raw::c_int, - _event_name: *mut *const std::os::raw::c_char, - _event_type: *mut core::AppLayerEventType -) -> i8 { - return -1; -} #[no_mangle] pub unsafe extern "C" fn rs_rfb_state_get_tx_iterator( _ipproto: u8, @@ -683,8 +667,8 @@ pub unsafe extern "C" fn rs_rfb_register_parser() { get_de_state: rs_rfb_tx_get_detect_state, set_de_state: rs_rfb_tx_set_detect_state, get_events: Some(rs_rfb_state_get_events), - get_eventinfo: Some(rs_rfb_state_get_event_info), - get_eventinfo_byid : Some(rs_rfb_state_get_event_info_by_id), + get_eventinfo: None, + get_eventinfo_byid: None, localstorage_new: None, localstorage_free: None, get_files: None, From 8e2416545b6a06e537234460724729ca5774abd4 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 16:14:14 -0600 Subject: [PATCH 13/18] ntp: use derived app-layer event --- rust/src/ntp/ntp.rs | 66 ++++----------------------------------------- 1 file changed, 5 insertions(+), 61 deletions(-) diff --git a/rust/src/ntp/ntp.rs b/rust/src/ntp/ntp.rs index 6b0de9705aee..9b8b6abf6a47 100644 --- a/rust/src/ntp/ntp.rs +++ b/rust/src/ntp/ntp.rs @@ -23,30 +23,18 @@ use crate::core; use crate::core::{AppProto,Flow,ALPROTO_UNKNOWN,ALPROTO_FAILED}; use crate::applayer::{self, *}; use std; -use std::ffi::{CStr,CString}; +use std::ffi::CString; use nom; -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum NTPEvent { - UnsolicitedResponse = 0, + UnsolicitedResponse , MalformedData, NotRequest, NotResponse, } -impl NTPEvent { - fn from_i32(value: i32) -> Option { - match value { - 0 => Some(NTPEvent::UnsolicitedResponse), - 1 => Some(NTPEvent::MalformedData), - 2 => Some(NTPEvent::NotRequest), - 3 => Some(NTPEvent::NotResponse), - _ => None, - } - } -} - pub struct NTPState { /// List of transactions for this session transactions: Vec, @@ -279,27 +267,6 @@ pub unsafe extern "C" fn rs_ntp_state_get_tx_detect_state( } } -#[no_mangle] -pub unsafe extern "C" fn rs_ntp_state_get_event_info_by_id(event_id: std::os::raw::c_int, - event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType) - -> i8 -{ - if let Some(e) = NTPEvent::from_i32(event_id as i32) { - let estr = match e { - NTPEvent::UnsolicitedResponse => { "unsolicited_response\0" }, - NTPEvent::MalformedData => { "malformed_data\0" }, - NTPEvent::NotRequest => { "not_request\0" }, - NTPEvent::NotResponse => { "not_response\0" }, - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} - #[no_mangle] pub unsafe extern "C" fn rs_ntp_state_get_events(tx: *mut std::os::raw::c_void) -> *mut core::AppLayerDecoderEvents @@ -308,29 +275,6 @@ pub unsafe extern "C" fn rs_ntp_state_get_events(tx: *mut std::os::raw::c_void) return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_ntp_state_get_event_info(event_name: *const std::os::raw::c_char, - event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType) - -> std::os::raw::c_int -{ - if event_name == std::ptr::null() { return -1; } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "malformed_data" => NTPEvent::MalformedData as i32, - _ => -1, // unknown event - } - }, - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} - - static mut ALPROTO_NTP : AppProto = ALPROTO_UNKNOWN; #[no_mangle] @@ -386,8 +330,8 @@ pub unsafe extern "C" fn rs_register_ntp_parser() { get_de_state : rs_ntp_state_get_tx_detect_state, set_de_state : rs_ntp_state_set_tx_detect_state, get_events : Some(rs_ntp_state_get_events), - get_eventinfo : Some(rs_ntp_state_get_event_info), - get_eventinfo_byid : Some(rs_ntp_state_get_event_info_by_id), + get_eventinfo : Some(NTPEvent::get_event_info), + get_eventinfo_byid : Some(NTPEvent::get_event_info_by_id), localstorage_new : None, localstorage_free : None, get_files : None, From 9c44aa0d146baf3c56036da313bdfb1ac0812b38 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 16:17:31 -0600 Subject: [PATCH 14/18] krb5: use derived app-layer event --- rust/src/krb/krb5.rs | 61 ++++---------------------------------------- 1 file changed, 5 insertions(+), 56 deletions(-) diff --git a/rust/src/krb/krb5.rs b/rust/src/krb/krb5.rs index 733e0d1e35f8..8d6bdd5ea833 100644 --- a/rust/src/krb/krb5.rs +++ b/rust/src/krb/krb5.rs @@ -18,7 +18,7 @@ // written by Pierre Chifflier use std; -use std::ffi::{CStr,CString}; +use std::ffi::CString; use nom; use nom::IResult; use nom::number::streaming::be_u32; @@ -30,22 +30,12 @@ use crate::applayer::{self, *}; use crate::core; use crate::core::{AppProto,Flow,ALPROTO_FAILED,ALPROTO_UNKNOWN,STREAM_TOCLIENT,STREAM_TOSERVER,sc_detect_engine_state_free}; -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum KRB5Event { - MalformedData = 0, + MalformedData, WeakEncryption, } -impl KRB5Event { - fn from_i32(value: i32) -> Option { - match value { - 0 => Some(KRB5Event::MalformedData), - 1 => Some(KRB5Event::WeakEncryption), - _ => None, - } - } -} - pub struct KRB5State { pub req_id: u8, @@ -345,25 +335,6 @@ pub unsafe extern "C" fn rs_krb5_state_get_tx_detect_state( } } -#[no_mangle] -pub unsafe extern "C" fn rs_krb5_state_get_event_info_by_id(event_id: std::os::raw::c_int, - event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType) - -> i8 -{ - if let Some(e) = KRB5Event::from_i32(event_id as i32) { - let estr = match e { - KRB5Event::MalformedData => { "malformed_data\0" }, - KRB5Event::WeakEncryption => { "weak_encryption\0" }, - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} - #[no_mangle] pub unsafe extern "C" fn rs_krb5_state_get_events(tx: *mut std::os::raw::c_void) -> *mut core::AppLayerDecoderEvents @@ -372,28 +343,6 @@ pub unsafe extern "C" fn rs_krb5_state_get_events(tx: *mut std::os::raw::c_void) return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_krb5_state_get_event_info(event_name: *const std::os::raw::c_char, - event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType) - -> std::os::raw::c_int -{ - if event_name == std::ptr::null() { return -1; } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "malformed_data" => KRB5Event::MalformedData as i32, - "weak_encryption" => KRB5Event::WeakEncryption as i32, - _ => -1, // unknown event - } - }, - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} static mut ALPROTO_KRB5 : AppProto = ALPROTO_UNKNOWN; #[no_mangle] @@ -636,8 +585,8 @@ pub unsafe extern "C" fn rs_register_krb5_parser() { get_de_state : rs_krb5_state_get_tx_detect_state, set_de_state : rs_krb5_state_set_tx_detect_state, get_events : Some(rs_krb5_state_get_events), - get_eventinfo : Some(rs_krb5_state_get_event_info), - get_eventinfo_byid : Some(rs_krb5_state_get_event_info_by_id), + get_eventinfo : Some(KRB5Event::get_event_info), + get_eventinfo_byid : Some(KRB5Event::get_event_info_by_id), localstorage_new : None, localstorage_free : None, get_files : None, From 393335671e18f09ab6fcac2df7f20db6501c89b2 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 16:23:49 -0600 Subject: [PATCH 15/18] http2: use derived app-layer event --- rust/src/http2/http2.rs | 85 +++-------------------------------------- 1 file changed, 5 insertions(+), 80 deletions(-) diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs index 313ced7595c4..efb60937dea9 100644 --- a/rust/src/http2/http2.rs +++ b/rust/src/http2/http2.rs @@ -26,7 +26,7 @@ use crate::filecontainer::*; use crate::filetracker::*; use nom; use std; -use std::ffi::{CStr, CString}; +use std::ffi::CString; use std::fmt; use std::io; @@ -299,9 +299,9 @@ impl Drop for HTTP2Transaction { } } -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum HTTP2Event { - InvalidFrameHeader = 0, + InvalidFrameHeader, InvalidClientMagic, InvalidFrameData, InvalidHeader, @@ -313,24 +313,6 @@ pub enum HTTP2Event { FailedDecompression, } -impl HTTP2Event { - fn from_i32(value: i32) -> Option { - match value { - 0 => Some(HTTP2Event::InvalidFrameHeader), - 1 => Some(HTTP2Event::InvalidClientMagic), - 2 => Some(HTTP2Event::InvalidFrameData), - 3 => Some(HTTP2Event::InvalidHeader), - 4 => Some(HTTP2Event::InvalidFrameLength), - 5 => Some(HTTP2Event::ExtraHeaderData), - 6 => Some(HTTP2Event::LongFrameData), - 7 => Some(HTTP2Event::StreamIdReuse), - 8 => Some(HTTP2Event::InvalidHTTP1Settings), - 9 => Some(HTTP2Event::FailedDecompression), - _ => None, - } - } -} - pub struct HTTP2DynTable { pub table: Vec, pub current_size: usize, @@ -1095,63 +1077,6 @@ pub unsafe extern "C" fn rs_http2_state_get_events( return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_http2_state_get_event_info( - event_name: *const std::os::raw::c_char, event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType, -) -> std::os::raw::c_int { - if event_name == std::ptr::null() { - return -1; - } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "invalid_frame_header" => HTTP2Event::InvalidFrameHeader as i32, - "invalid_client_magic" => HTTP2Event::InvalidClientMagic as i32, - "invalid_frame_data" => HTTP2Event::InvalidFrameData as i32, - "invalid_header" => HTTP2Event::InvalidHeader as i32, - "invalid_frame_length" => HTTP2Event::InvalidFrameLength as i32, - "extra_header_data" => HTTP2Event::ExtraHeaderData as i32, - "long_frame_data" => HTTP2Event::LongFrameData as i32, - "stream_id_reuse" => HTTP2Event::StreamIdReuse as i32, - "invalid_http1_settings" => HTTP2Event::InvalidHTTP1Settings as i32, - "failed_decompression" => HTTP2Event::FailedDecompression as i32, - _ => -1, // unknown event - } - } - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} - -#[no_mangle] -pub unsafe extern "C" fn rs_http2_state_get_event_info_by_id( - event_id: std::os::raw::c_int, event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType, -) -> i8 { - if let Some(e) = HTTP2Event::from_i32(event_id as i32) { - let estr = match e { - HTTP2Event::InvalidFrameHeader => "invalid_frame_header\0", - HTTP2Event::InvalidClientMagic => "invalid_client_magic\0", - HTTP2Event::InvalidFrameData => "invalid_frame_data\0", - HTTP2Event::InvalidHeader => "invalid_header\0", - HTTP2Event::InvalidFrameLength => "invalid_frame_length\0", - HTTP2Event::ExtraHeaderData => "extra_header_data\0", - HTTP2Event::LongFrameData => "long_frame_data\0", - HTTP2Event::StreamIdReuse => "stream_id_reuse\0", - HTTP2Event::InvalidHTTP1Settings => "invalid_http1_settings\0", - HTTP2Event::FailedDecompression => "failed_decompression\0", - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} #[no_mangle] pub unsafe extern "C" fn rs_http2_state_get_tx_iterator( _ipproto: u8, _alproto: AppProto, state: *mut std::os::raw::c_void, min_tx_id: u64, @@ -1209,8 +1134,8 @@ pub unsafe extern "C" fn rs_http2_register_parser() { get_de_state: rs_http2_tx_get_detect_state, set_de_state: rs_http2_tx_set_detect_state, get_events: Some(rs_http2_state_get_events), - get_eventinfo: Some(rs_http2_state_get_event_info), - get_eventinfo_byid: Some(rs_http2_state_get_event_info_by_id), + get_eventinfo: Some(HTTP2Event::get_event_info), + get_eventinfo_byid: Some(HTTP2Event::get_event_info_by_id), localstorage_new: None, localstorage_free: None, get_files: Some(rs_http2_getfiles), From 2c2e75419ba33c92c2a06502654347ec478fcd32 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 18 Nov 2020 16:26:18 -0600 Subject: [PATCH 16/18] app-layer template: use derived app-layer event --- rust/src/applayertemplate/template.rs | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/rust/src/applayertemplate/template.rs b/rust/src/applayertemplate/template.rs index 8524061b23ac..5c6e87e1ba1d 100644 --- a/rust/src/applayertemplate/template.rs +++ b/rust/src/applayertemplate/template.rs @@ -24,6 +24,9 @@ use super::parser; static mut ALPROTO_TEMPLATE: AppProto = ALPROTO_UNKNOWN; +#[derive(AppLayerEvent)] +enum TemplateEvent {} + pub struct TemplateTransaction { tx_id: u64, pub request: Option, @@ -422,22 +425,6 @@ pub unsafe extern "C" fn rs_template_state_get_events( return tx.events; } -#[no_mangle] -pub extern "C" fn rs_template_state_get_event_info( - _event_name: *const std::os::raw::c_char, - _event_id: *mut std::os::raw::c_int, - _event_type: *mut core::AppLayerEventType, -) -> std::os::raw::c_int { - return -1; -} - -#[no_mangle] -pub extern "C" fn rs_template_state_get_event_info_by_id(_event_id: std::os::raw::c_int, - _event_name: *mut *const std::os::raw::c_char, - _event_type: *mut core::AppLayerEventType -) -> i8 { - return -1; -} #[no_mangle] pub unsafe extern "C" fn rs_template_state_get_tx_iterator( _ipproto: u8, @@ -534,8 +521,8 @@ pub unsafe extern "C" fn rs_template_register_parser() { get_de_state: rs_template_tx_get_detect_state, set_de_state: rs_template_tx_set_detect_state, get_events: Some(rs_template_state_get_events), - get_eventinfo: Some(rs_template_state_get_event_info), - get_eventinfo_byid : Some(rs_template_state_get_event_info_by_id), + get_eventinfo: Some(TemplateEvent::get_event_info), + get_eventinfo_byid : Some(TemplateEvent::get_event_info_by_id), localstorage_new: None, localstorage_free: None, get_files: None, From 9c250eb04efb773b461f6b96942608ab9177b1b1 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Mon, 30 Aug 2021 15:45:15 -0600 Subject: [PATCH 17/18] modbus: use derive macro from app-layer events --- rust/src/modbus/modbus.rs | 100 ++------------------------------------ 1 file changed, 4 insertions(+), 96 deletions(-) diff --git a/rust/src/modbus/modbus.rs b/rust/src/modbus/modbus.rs index 5fc6df4ad97c..ef2f05b45cfa 100644 --- a/rust/src/modbus/modbus.rs +++ b/rust/src/modbus/modbus.rs @@ -18,7 +18,6 @@ use crate::applayer::*; use crate::core::{self, AppProto, ALPROTO_FAILED, ALPROTO_UNKNOWN, IPPROTO_TCP}; use std::ffi::CString; -use std::str::FromStr; use sawp::error::Error as SawpError; use sawp::error::ErrorKind as SawpErrorKind; @@ -31,8 +30,9 @@ pub const MODBUS_PARSER: sawp_modbus::Modbus = sawp_modbus::Modbus {}; static mut ALPROTO_MODBUS: AppProto = ALPROTO_UNKNOWN; +#[derive(AppLayerEvent)] enum ModbusEvent { - UnsolicitedResponse = 0, + UnsolicitedResponse, InvalidFunctionCode, InvalidLength, InvalidValue, @@ -41,53 +41,6 @@ enum ModbusEvent { Flooded, InvalidProtocolId, } - -impl FromStr for ModbusEvent { - type Err = (); - fn from_str(name: &str) -> Result { - match name { - "unsolicited_response" => Ok(ModbusEvent::UnsolicitedResponse), - "invalid_function_code" => Ok(ModbusEvent::InvalidFunctionCode), - "invalid_length" => Ok(ModbusEvent::InvalidLength), - "invalid_value" => Ok(ModbusEvent::InvalidValue), - "invalid_exception_code" => Ok(ModbusEvent::InvalidExceptionCode), - "value_mismatch" => Ok(ModbusEvent::ValueMismatch), - "flooded" => Ok(ModbusEvent::Flooded), - "invalid_protocol_id" => Ok(ModbusEvent::InvalidProtocolId), - _ => Err(()), - } - } -} - -impl ModbusEvent { - pub fn to_str(&self) -> &str { - match *self { - ModbusEvent::UnsolicitedResponse => "unsolicited_response", - ModbusEvent::InvalidFunctionCode => "invalid_function_code", - ModbusEvent::InvalidLength => "invalid_length", - ModbusEvent::InvalidValue => "invalid_value", - ModbusEvent::InvalidExceptionCode => "invalid_exception_code", - ModbusEvent::ValueMismatch => "value_mismatch", - ModbusEvent::Flooded => "flooded", - ModbusEvent::InvalidProtocolId => "invalid_protocol_id", - } - } - - pub fn from_id(id: u32) -> Option { - match id { - 0 => Some(ModbusEvent::UnsolicitedResponse), - 1 => Some(ModbusEvent::InvalidFunctionCode), - 2 => Some(ModbusEvent::InvalidLength), - 3 => Some(ModbusEvent::InvalidValue), - 4 => Some(ModbusEvent::InvalidExceptionCode), - 5 => Some(ModbusEvent::ValueMismatch), - 6 => Some(ModbusEvent::Flooded), - 7 => Some(ModbusEvent::InvalidProtocolId), - _ => None, - } - } -} - pub struct ModbusTransaction { pub id: u64, @@ -425,51 +378,6 @@ pub unsafe extern "C" fn rs_modbus_state_get_events( tx.events } -#[no_mangle] -pub unsafe extern "C" fn rs_modbus_state_get_event_info( - event_name: *const std::os::raw::c_char, event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType, -) -> std::os::raw::c_int { - if event_name.is_null() { - return -1; - } - - let event_name = std::ffi::CStr::from_ptr(event_name); - if let Ok(event_name) = event_name.to_str() { - match ModbusEvent::from_str(event_name) { - Ok(event) => { - *event_id = event as std::os::raw::c_int; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - }, - Err(_) => { - SCLogError!( - "event {} not present in modbus's enum map table.", - event_name - ); - -1 - } - } - } else { - -1 - } -} - -#[no_mangle] -pub unsafe extern "C" fn rs_modbus_state_get_event_info_by_id( - event_id: std::os::raw::c_int, event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType, -) -> i8 { - if let Some(e) = ModbusEvent::from_id(event_id as u32) { - *event_name = e.to_str().as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - SCLogError!("event {} not present in modbus's enum map table.", event_id); - -1 - } -} - #[no_mangle] pub unsafe extern "C" fn rs_modbus_state_get_tx_detect_state( tx: *mut std::os::raw::c_void, @@ -520,8 +428,8 @@ pub unsafe extern "C" fn rs_modbus_register_parser() { tx_comp_st_tc: 1, tx_get_progress: rs_modbus_tx_get_alstate_progress, get_events: Some(rs_modbus_state_get_events), - get_eventinfo: Some(rs_modbus_state_get_event_info), - get_eventinfo_byid: Some(rs_modbus_state_get_event_info_by_id), + get_eventinfo: Some(ModbusEvent::get_event_info), + get_eventinfo_byid: Some(ModbusEvent::get_event_info_by_id), localstorage_new: None, localstorage_free: None, get_files: None, From d9a18ff5f1841ef306611f7e70295f104a552fa9 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Mon, 30 Aug 2021 15:49:58 -0600 Subject: [PATCH 18/18] ike: use derive macro from app-layer events --- rust/src/ike/ike.rs | 98 ++++--------------------------------------- rust/src/ike/ikev2.rs | 6 +-- 2 files changed, 11 insertions(+), 93 deletions(-) diff --git a/rust/src/ike/ike.rs b/rust/src/ike/ike.rs index 38aefeb01bf7..cc30b428136a 100644 --- a/rust/src/ike/ike.rs +++ b/rust/src/ike/ike.rs @@ -31,17 +31,17 @@ use crate::ike::parser::*; use nom; use std; use std::collections::HashSet; -use std::ffi::{CStr, CString}; +use std::ffi::CString; -#[repr(u32)] +#[derive(AppLayerEvent)] pub enum IkeEvent { - MalformedData = 0, + MalformedData, NoEncryption, WeakCryptoEnc, - WeakCryptoPRF, - WeakCryptoDH, + WeakCryptoPrf, + WeakCryptoDh, WeakCryptoAuth, - WeakCryptoNoDH, + WeakCryptoNoDh, WeakCryptoNoAuth, InvalidProposal, UnknownProposal, @@ -49,26 +49,6 @@ pub enum IkeEvent { MultipleServerProposal, } -impl IkeEvent { - pub fn from_i32(value: i32) -> Option { - match value { - 0 => Some(IkeEvent::MalformedData), - 1 => Some(IkeEvent::NoEncryption), - 2 => Some(IkeEvent::WeakCryptoEnc), - 3 => Some(IkeEvent::WeakCryptoPRF), - 4 => Some(IkeEvent::WeakCryptoDH), - 5 => Some(IkeEvent::WeakCryptoAuth), - 6 => Some(IkeEvent::WeakCryptoNoDH), - 7 => Some(IkeEvent::WeakCryptoNoAuth), - 8 => Some(IkeEvent::InvalidProposal), - 9 => Some(IkeEvent::UnknownProposal), - 10 => Some(IkeEvent::PayloadExtraData), - 11 => Some(IkeEvent::MultipleServerProposal), - _ => None, - } - } -} - pub struct IkeHeaderWrapper { pub spi_initiator: String, pub spi_responder: String, @@ -439,68 +419,6 @@ pub unsafe extern "C" fn rs_ike_state_get_events( return tx.events; } -#[no_mangle] -pub unsafe extern "C" fn rs_ike_state_get_event_info_by_id( - event_id: std::os::raw::c_int, event_name: *mut *const std::os::raw::c_char, - event_type: *mut core::AppLayerEventType, -) -> i8 { - if let Some(e) = IkeEvent::from_i32(event_id as i32) { - let estr = match e { - IkeEvent::MalformedData => "malformed_data\0", - IkeEvent::NoEncryption => "no_encryption\0", - IkeEvent::WeakCryptoEnc => "weak_crypto_enc\0", - IkeEvent::WeakCryptoPRF => "weak_crypto_prf\0", - IkeEvent::WeakCryptoDH => "weak_crypto_dh\0", - IkeEvent::WeakCryptoAuth => "weak_crypto_auth\0", - IkeEvent::WeakCryptoNoDH => "weak_crypto_nodh\0", - IkeEvent::WeakCryptoNoAuth => "weak_crypto_noauth\0", - IkeEvent::InvalidProposal => "invalid_proposal\0", - IkeEvent::UnknownProposal => "unknown_proposal\0", - IkeEvent::PayloadExtraData => "payload_extra_data\0", - IkeEvent::MultipleServerProposal => "multiple_server_proposal\0", - }; - *event_name = estr.as_ptr() as *const std::os::raw::c_char; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - 0 - } else { - -1 - } -} - -#[no_mangle] -pub unsafe extern "C" fn rs_ike_state_get_event_info( - event_name: *const std::os::raw::c_char, event_id: *mut std::os::raw::c_int, - event_type: *mut core::AppLayerEventType, -) -> std::os::raw::c_int { - if event_name == std::ptr::null() { - return -1; - } - let c_event_name: &CStr = CStr::from_ptr(event_name); - let event = match c_event_name.to_str() { - Ok(s) => { - match s { - "malformed_data" => IkeEvent::MalformedData as i32, - "no_encryption" => IkeEvent::NoEncryption as i32, - "weak_crypto_enc" => IkeEvent::WeakCryptoEnc as i32, - "weak_crypto_prf" => IkeEvent::WeakCryptoPRF as i32, - "weak_crypto_auth" => IkeEvent::WeakCryptoAuth as i32, - "weak_crypto_dh" => IkeEvent::WeakCryptoDH as i32, - "weak_crypto_nodh" => IkeEvent::WeakCryptoNoDH as i32, - "weak_crypto_noauth" => IkeEvent::WeakCryptoNoAuth as i32, - "invalid_proposal" => IkeEvent::InvalidProposal as i32, - "unknown_proposal" => IkeEvent::UnknownProposal as i32, - "payload_extra_data" => IkeEvent::PayloadExtraData as i32, - "multiple_server_proposal" => IkeEvent::MultipleServerProposal as i32, - _ => -1, // unknown event - } - } - Err(_) => -1, // UTF-8 conversion failed - }; - *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; - *event_id = event as std::os::raw::c_int; - 0 -} - static mut ALPROTO_IKE : AppProto = ALPROTO_UNKNOWN; #[no_mangle] @@ -551,8 +469,8 @@ pub unsafe extern "C" fn rs_ike_register_parser() { get_de_state : rs_ike_tx_get_detect_state, set_de_state : rs_ike_tx_set_detect_state, get_events : Some(rs_ike_state_get_events), - get_eventinfo : Some(rs_ike_state_get_event_info), - get_eventinfo_byid : Some(rs_ike_state_get_event_info_by_id), + get_eventinfo : Some(IkeEvent::get_event_info), + get_eventinfo_byid : Some(IkeEvent::get_event_info_by_id), localstorage_new : None, localstorage_free : None, get_files : None, diff --git a/rust/src/ike/ikev2.rs b/rust/src/ike/ikev2.rs index 6a597c9e8e2c..6082a5beea16 100644 --- a/rust/src/ike/ikev2.rs +++ b/rust/src/ike/ikev2.rs @@ -246,7 +246,7 @@ fn add_proposals(state: &mut IKEState, prop: &Vec, direction: u8) } IkeTransformPRFType::PRF_HMAC_MD5 | IkeTransformPRFType::PRF_HMAC_SHA1 => { SCLogDebug!("Weak PRF: {:?}", prf); - state.set_event(IkeEvent::WeakCryptoPRF); + state.set_event(IkeEvent::WeakCryptoPrf); } _ => (), }, @@ -279,7 +279,7 @@ fn add_proposals(state: &mut IKEState, prop: &Vec, direction: u8) | IkeTransformDHType::Modp1024s160 | IkeTransformDHType::Modp1536 => { SCLogDebug!("Weak DH: {:?}", dh); - state.set_event(IkeEvent::WeakCryptoDH); + state.set_event(IkeEvent::WeakCryptoDh); } _ => (), }, @@ -296,7 +296,7 @@ fn add_proposals(state: &mut IKEState, prop: &Vec, direction: u8) _ => false, }) { SCLogDebug!("No DH transform found"); - state.set_event(IkeEvent::WeakCryptoNoDH); + state.set_event(IkeEvent::WeakCryptoNoDh); } // Rule 3: check if proposing AH ([RFC7296] section 3.3.1) if p.protocol_id == ProtocolID::AH {