From f71a078c8abe5e11d23ef451a4a6bae6e3dad9fe Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:40:16 +0200 Subject: Merging upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- rust/derive/Cargo.toml | 2 +- rust/dist/rust-bindings.h | 2 ++ rust/src/applayertemplate/template.rs | 20 +++++++++++++++++++- rust/src/dhcp/logger.rs | 4 ++-- rust/src/dns/log.rs | 2 +- rust/src/ike/ikev1.rs | 2 +- rust/src/jsonbuilder.rs | 16 ++++++++++++++++ rust/src/mqtt/mqtt.rs | 8 ++++---- rust/src/nfs/nfs.rs | 2 +- rust/src/smb/log.rs | 4 ++-- rust/src/ssh/logger.rs | 10 +++++----- rust/src/ssh/ssh.rs | 6 ++++-- 12 files changed, 58 insertions(+), 20 deletions(-) (limited to 'rust') diff --git a/rust/derive/Cargo.toml b/rust/derive/Cargo.toml index 4aa81b4..c697f68 100644 --- a/rust/derive/Cargo.toml +++ b/rust/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "suricata-derive" -version = "7.0.3" +version = "7.0.4" edition = "2021" [lib] diff --git a/rust/dist/rust-bindings.h b/rust/dist/rust-bindings.h index 77afc3b..56f350c 100644 --- a/rust/dist/rust-bindings.h +++ b/rust/dist/rust-bindings.h @@ -4424,6 +4424,8 @@ #define RS_MIME_MAX_TOKEN_LEN 255 +#define SSH_MAX_BANNER_LEN 256 + #define HTTP2_DECOMPRESSION_CHUNK_SIZE 4096 #define HTTP2_STATIC_HEADERS_NUMBER 61 diff --git a/rust/src/applayertemplate/template.rs b/rust/src/applayertemplate/template.rs index acc6c26..dbbc784 100644 --- a/rust/src/applayertemplate/template.rs +++ b/rust/src/applayertemplate/template.rs @@ -17,6 +17,7 @@ use super::parser; use crate::applayer::{self, *}; +use crate::conf::conf_get; use crate::core::{AppProto, Flow, ALPROTO_UNKNOWN, IPPROTO_TCP}; use nom7 as nom; use std; @@ -24,10 +25,14 @@ use std::collections::VecDeque; use std::ffi::CString; use std::os::raw::{c_char, c_int, c_void}; +static mut TEMPLATE_MAX_TX: usize = 256; + static mut ALPROTO_TEMPLATE: AppProto = ALPROTO_UNKNOWN; #[derive(AppLayerEvent)] -enum TemplateEvent {} +enum TemplateEvent { + TooManyTransactions, +} pub struct TemplateTransaction { tx_id: u64, @@ -145,7 +150,13 @@ impl TemplateState { SCLogNotice!("Request: {}", request); let mut tx = self.new_tx(); tx.request = Some(request); + if self.transactions.len() >= unsafe {TEMPLATE_MAX_TX} { + tx.tx_data.set_event(TemplateEvent::TooManyTransactions as u8); + } self.transactions.push_back(tx); + if self.transactions.len() >= unsafe {TEMPLATE_MAX_TX} { + return AppLayerResult::err(); + } } Err(nom::Err::Incomplete(_)) => { // Not enough data. This parser doesn't give us a good indication @@ -429,6 +440,13 @@ pub unsafe extern "C" fn rs_template_register_parser() { if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { let _ = AppLayerRegisterParser(&parser, alproto); } + if let Some(val) = conf_get("app-layer.protocols.template.max-tx") { + if let Ok(v) = val.parse::() { + TEMPLATE_MAX_TX = v; + } else { + SCLogError!("Invalid value for template.max-tx"); + } + } SCLogNotice!("Rust template parser registered."); } else { SCLogNotice!("Protocol detector and parser disabled for TEMPLATE."); diff --git a/rust/src/dhcp/logger.rs b/rust/src/dhcp/logger.rs index b29e215..3c86b1b 100644 --- a/rust/src/dhcp/logger.rs +++ b/rust/src/dhcp/logger.rs @@ -229,7 +229,7 @@ impl DHCPLogger { fn log_opt_dns_server(&self, js: &mut JsonBuilder, option: &DHCPOptGeneric) -> Result<(), JsonError> { js.open_array("dns_servers")?; for i in 0..(option.data.len() / 4) { - let val = dns_print_addr(&option.data[(i * 4)..(i * 4) + 4].to_vec()); + let val = dns_print_addr(&option.data[(i * 4)..(i * 4) + 4]); js.append_string(&val)?; } js.close()?; @@ -239,7 +239,7 @@ impl DHCPLogger { fn log_opt_routers(&self, js: &mut JsonBuilder, option: &DHCPOptGeneric) -> Result<(), JsonError> { js.open_array("routers")?; for i in 0..(option.data.len() / 4) { - let val = dns_print_addr(&option.data[(i * 4)..(i * 4) + 4].to_vec()); + let val = dns_print_addr(&option.data[(i * 4)..(i * 4) + 4]); js.append_string(&val)?; } js.close()?; diff --git a/rust/src/dns/log.rs b/rust/src/dns/log.rs index 5212b1a..86325d5 100644 --- a/rust/src/dns/log.rs +++ b/rust/src/dns/log.rs @@ -368,7 +368,7 @@ pub fn dns_rcode_string(flags: u16) -> String { } /// Format bytes as an IP address string. -pub fn dns_print_addr(addr: &Vec) -> std::string::String { +pub fn dns_print_addr(addr: &[u8]) -> std::string::String { if addr.len() == 4 { return format!("{}.{}.{}.{}", addr[0], addr[1], addr[2], addr[3]); } else if addr.len() == 16 { diff --git a/rust/src/ike/ikev1.rs b/rust/src/ike/ikev1.rs index 1e79c29..6f598f9 100644 --- a/rust/src/ike/ikev1.rs +++ b/rust/src/ike/ikev1.rs @@ -53,7 +53,7 @@ impl Ikev1ParticipantData { } pub fn update( - &mut self, key_exchange: &str, nonce: &str, transforms: &Vec>, + &mut self, key_exchange: &str, nonce: &str, transforms: &[Vec], ) { self.key_exchange = key_exchange.to_string(); self.nonce = nonce.to_string(); diff --git a/rust/src/jsonbuilder.rs b/rust/src/jsonbuilder.rs index 9ff6234..7264be5 100644 --- a/rust/src/jsonbuilder.rs +++ b/rust/src/jsonbuilder.rs @@ -527,6 +527,22 @@ impl JsonBuilder { } } + /// Set a key and a string value (from bytes) on an object, with a limited size + pub fn set_string_from_bytes_limited(&mut self, key: &str, val: &[u8], limit: usize) -> Result<&mut Self, JsonError> { + let mut valtrunc = Vec::new(); + let val = if val.len() > limit { + valtrunc.extend_from_slice(&val[..limit]); + valtrunc.extend_from_slice(b"[truncated]"); + &valtrunc + } else { + val + }; + match std::str::from_utf8(val) { + Ok(s) => self.set_string(key, s), + Err(_) => self.set_string(key, &try_string_from_bytes(val)?), + } + } + /// Set a key and a string field as the base64 encoded string of the value. pub fn set_base64(&mut self, key: &str, val: &[u8]) -> Result<&mut Self, JsonError> { match self.current_state() { diff --git a/rust/src/mqtt/mqtt.rs b/rust/src/mqtt/mqtt.rs index 3f110df..8260251 100644 --- a/rust/src/mqtt/mqtt.rs +++ b/rust/src/mqtt/mqtt.rs @@ -433,8 +433,8 @@ impl MQTTState { let _pdu = Frame::new( flow, &stream_slice, - input, - current.len() as i64, + current, + (current.len() - rem.len()) as i64, MQTTFrameType::Pdu as u8, ); SCLogDebug!("request msg {:?}", msg); @@ -518,8 +518,8 @@ impl MQTTState { let _pdu = Frame::new( flow, &stream_slice, - input, - input.len() as i64, + current, + (current.len() - rem.len()) as i64, MQTTFrameType::Pdu as u8, ); diff --git a/rust/src/nfs/nfs.rs b/rust/src/nfs/nfs.rs index dfb5e0e..4a1c362 100644 --- a/rust/src/nfs/nfs.rs +++ b/rust/src/nfs/nfs.rs @@ -497,7 +497,7 @@ impl NFSState { } // TODO maybe not enough users to justify a func - pub fn mark_response_tx_done(&mut self, xid: u32, rpc_status: u32, nfs_status: u32, resp_handle: &Vec) + pub fn mark_response_tx_done(&mut self, xid: u32, rpc_status: u32, nfs_status: u32, resp_handle: &[u8]) { if let Some(mytx) = self.get_tx_by_xid(xid) { mytx.response_done = true; diff --git a/rust/src/smb/log.rs b/rust/src/smb/log.rs index 8496574..e242d02 100644 --- a/rust/src/smb/log.rs +++ b/rust/src/smb/log.rs @@ -38,7 +38,7 @@ fn debug_add_progress(jsb: &mut JsonBuilder, tx: &SMBTransaction) -> Result<(), /// take in a file GUID (16 bytes) or FID (2 bytes). Also deal /// with our frankenFID (2 bytes + 4 user_id) -fn fuid_to_string(fuid: &Vec) -> String { +fn fuid_to_string(fuid: &[u8]) -> String { let fuid_len = fuid.len(); if fuid_len == 16 { guid_to_string(fuid) @@ -52,7 +52,7 @@ fn fuid_to_string(fuid: &Vec) -> String { } } -fn guid_to_string(guid: &Vec) -> String { +fn guid_to_string(guid: &[u8]) -> String { if guid.len() == 16 { let output = format!("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", guid[3], guid[2], guid[1], guid[0], diff --git a/rust/src/ssh/logger.rs b/rust/src/ssh/logger.rs index 9bc7d7c..e83d288 100644 --- a/rust/src/ssh/logger.rs +++ b/rust/src/ssh/logger.rs @@ -15,7 +15,7 @@ * 02110-1301, USA. */ -use super::ssh::SSHTransaction; +use super::ssh::{SSHTransaction, SSH_MAX_BANNER_LEN}; use crate::jsonbuilder::{JsonBuilder, JsonError}; fn log_ssh(tx: &SSHTransaction, js: &mut JsonBuilder) -> Result { @@ -24,9 +24,9 @@ fn log_ssh(tx: &SSHTransaction, js: &mut JsonBuilder) -> Result } if !tx.cli_hdr.protover.is_empty() { js.open_object("client")?; - js.set_string_from_bytes("proto_version", &tx.cli_hdr.protover)?; + js.set_string_from_bytes_limited("proto_version", &tx.cli_hdr.protover, SSH_MAX_BANNER_LEN)?; if !tx.cli_hdr.swver.is_empty() { - js.set_string_from_bytes("software_version", &tx.cli_hdr.swver)?; + js.set_string_from_bytes_limited("software_version", &tx.cli_hdr.swver, SSH_MAX_BANNER_LEN)?; } if !tx.cli_hdr.hassh.is_empty() || !tx.cli_hdr.hassh_string.is_empty() { js.open_object("hassh")?; @@ -42,9 +42,9 @@ fn log_ssh(tx: &SSHTransaction, js: &mut JsonBuilder) -> Result } if !tx.srv_hdr.protover.is_empty() { js.open_object("server")?; - js.set_string_from_bytes("proto_version", &tx.srv_hdr.protover)?; + js.set_string_from_bytes_limited("proto_version", &tx.srv_hdr.protover, SSH_MAX_BANNER_LEN)?; if !tx.srv_hdr.swver.is_empty() { - js.set_string_from_bytes("software_version", &tx.srv_hdr.swver)?; + js.set_string_from_bytes_limited("software_version", &tx.srv_hdr.swver, SSH_MAX_BANNER_LEN)?; } if !tx.srv_hdr.hassh.is_empty() || !tx.srv_hdr.hassh_string.is_empty() { js.open_object("hassh")?; diff --git a/rust/src/ssh/ssh.rs b/rust/src/ssh/ssh.rs index 6280e0b..a058689 100644 --- a/rust/src/ssh/ssh.rs +++ b/rust/src/ssh/ssh.rs @@ -46,7 +46,7 @@ pub enum SSHConnectionState { SshStateFinished = 3, } -const SSH_MAX_BANNER_LEN: usize = 256; +pub const SSH_MAX_BANNER_LEN: usize = 256; const SSH_RECORD_HEADER_LEN: usize = 6; const SSH_MAX_REASSEMBLED_RECORD_LEN: usize = 65535; @@ -256,7 +256,9 @@ impl SSHState { return r; } Err(Err::Incomplete(_)) => { - return AppLayerResult::incomplete(0_u32, (input.len() + 1) as u32); + // we do not need to retain these bytes + // we parsed them, we skip them + return AppLayerResult::ok(); } Err(_e) => { SCLogDebug!("SSH invalid banner {}", _e); -- cgit v1.2.3