From 667f8b2eb77fff159ac097321e590da9e1c32983 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 5 Feb 2026 09:37:19 +0100 Subject: [PATCH] detect/smb: move smb ntlmssp keywords to rust Ticket: 8267 --- rust/src/smb/detect.rs | 97 ++++++++++++++++++---- rust/src/smb/smb.rs | 2 +- src/Makefile.am | 2 - src/detect-engine-register.c | 4 +- src/detect-engine-register.h | 2 - src/detect-smb-ntlmssp.c | 150 ----------------------------------- src/detect-smb-ntlmssp.h | 30 ------- 7 files changed, 83 insertions(+), 204 deletions(-) delete mode 100644 src/detect-smb-ntlmssp.c delete mode 100644 src/detect-smb-ntlmssp.h diff --git a/rust/src/smb/detect.rs b/rust/src/smb/detect.rs index 217411644d..fbfca8be7e 100644 --- a/rust/src/smb/detect.rs +++ b/rust/src/smb/detect.rs @@ -15,14 +15,21 @@ * 02110-1301, USA. */ +use super::smb::ALPROTO_SMB; +use crate::core::STREAM_TOSERVER; use crate::dcerpc::dcerpc::DCERPC_TYPE_REQUEST; use crate::dcerpc::detect::{DCEIfaceData, DCEOpnumData, DETECT_DCE_OPNUM_RANGE_UNINITIALIZED}; use crate::detect::uint::detect_match_uint; +use crate::detect::{helper_keyword_register_sticky_buffer, SigTableElmtStickyBuffer}; use crate::direction::Direction; use crate::smb::smb::*; use std::ffi::CStr; -use std::os::raw::{c_char, c_void}; +use std::os::raw::{c_char, c_int, c_void}; use std::ptr; +use suricata_sys::sys::{ + DetectEngineCtx, SCDetectBufferSetActiveList, SCDetectHelperBufferMpmRegister, + SCDetectSignatureSetAppProto, Signature, +}; #[no_mangle] pub unsafe extern "C" fn SCSmbTxGetShare( @@ -83,9 +90,7 @@ pub unsafe extern "C" fn SCSmbTxGetStubData( } #[no_mangle] -pub extern "C" fn SCSmbTxMatchDceOpnum( - tx: &SMBTransaction, dce_data: &mut DCEOpnumData, -) -> u8 { +pub extern "C" fn SCSmbTxMatchDceOpnum(tx: &SMBTransaction, dce_data: &mut DCEOpnumData) -> u8 { SCLogDebug!("SCSmbTxMatchDceOpnum: start"); if let Some(SMBTransactionTypeData::DCERPC(ref x)) = tx.type_data { if x.req_cmd == DCERPC_TYPE_REQUEST { @@ -150,38 +155,38 @@ pub extern "C" fn SCSmbTxGetDceIface( return 0; } -#[no_mangle] -pub unsafe extern "C" fn SCSmbTxGetNtlmsspUser( - tx: &SMBTransaction, buffer: *mut *const u8, buffer_len: *mut u32, -) -> u8 { +unsafe extern "C" fn smb_tx_get_ntlmssp_user( + tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, SMBTransaction); if let Some(SMBTransactionTypeData::SESSIONSETUP(ref x)) = tx.type_data { if let Some(ref ntlmssp) = x.ntlmssp { *buffer = ntlmssp.user.as_ptr(); *buffer_len = ntlmssp.user.len() as u32; - return 1; + return true; } } *buffer = ptr::null(); *buffer_len = 0; - return 0; + return false; } -#[no_mangle] -pub unsafe extern "C" fn SCSmbTxGetNtlmsspDomain( - tx: &SMBTransaction, buffer: *mut *const u8, buffer_len: *mut u32, -) -> u8 { +unsafe extern "C" fn smb_tx_get_ntlmssp_domain( + tx: *const c_void, _flags: u8, buffer: *mut *const u8, buffer_len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, SMBTransaction); if let Some(SMBTransactionTypeData::SESSIONSETUP(ref x)) = tx.type_data { if let Some(ref ntlmssp) = x.ntlmssp { *buffer = ntlmssp.domain.as_ptr(); *buffer_len = ntlmssp.domain.len() as u32; - return 1; + return true; } } *buffer = ptr::null(); *buffer_len = 0; - return 0; + return false; } #[no_mangle] @@ -228,6 +233,66 @@ pub unsafe extern "C" fn SCSmbVersionFree(ptr: *mut c_void) { std::mem::drop(Box::from_raw(ptr as *mut u8)); } +unsafe extern "C" fn smb_ntlmssp_user_setup( + de: *mut DetectEngineCtx, s: *mut Signature, _raw: *const std::os::raw::c_char, +) -> c_int { + if SCDetectSignatureSetAppProto(s, ALPROTO_SMB) != 0 { + return -1; + } + if SCDetectBufferSetActiveList(de, s, G_SMB_NTLMSSP_USER_BUFFER_ID) < 0 { + return -1; + } + return 0; +} + +unsafe extern "C" fn smb_ntlmssp_domain_setup( + de: *mut DetectEngineCtx, s: *mut Signature, _raw: *const std::os::raw::c_char, +) -> c_int { + if SCDetectSignatureSetAppProto(s, ALPROTO_SMB) != 0 { + return -1; + } + if SCDetectBufferSetActiveList(de, s, G_SMB_NTLMSSP_DOMAIN_BUFFER_ID) < 0 { + return -1; + } + return 0; +} + +static mut G_SMB_NTLMSSP_USER_BUFFER_ID: c_int = 0; +static mut G_SMB_NTLMSSP_DOMAIN_BUFFER_ID: c_int = 0; + +#[no_mangle] +pub unsafe extern "C" fn SCDetectSmbRegister() { + let kw_user = SigTableElmtStickyBuffer { + name: String::from("smb.ntlmssp_user"), + desc: String::from("sticky buffer to match on SMB ntlmssp user in session setup"), + url: String::from("/rules/smb-keywords.html#smb-ntlmssp-user"), + setup: smb_ntlmssp_user_setup, + }; + helper_keyword_register_sticky_buffer(&kw_user); + G_SMB_NTLMSSP_USER_BUFFER_ID = SCDetectHelperBufferMpmRegister( + b"smb_ntlmssp_user\0".as_ptr() as *const libc::c_char, + b"smb ntlmssp user\0".as_ptr() as *const libc::c_char, + ALPROTO_SMB, + STREAM_TOSERVER, + Some(smb_tx_get_ntlmssp_user), + ); + + let kw_domain = SigTableElmtStickyBuffer { + name: String::from("smb.ntlmssp_domain"), + desc: String::from("sticky buffer to match on SMB ntlmssp domain in session setup"), + url: String::from("/rules/smb-keywords.html#smb-ntlmssp-domain"), + setup: smb_ntlmssp_domain_setup, + }; + helper_keyword_register_sticky_buffer(&kw_domain); + G_SMB_NTLMSSP_DOMAIN_BUFFER_ID = SCDetectHelperBufferMpmRegister( + b"smb_ntlmssp_domain\0".as_ptr() as *const libc::c_char, + b"smb ntlmssp domain\0".as_ptr() as *const libc::c_char, + ALPROTO_SMB, + STREAM_TOSERVER, + Some(smb_tx_get_ntlmssp_domain), + ); +} + #[cfg(test)] mod tests { use super::*; diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index b49e583f05..76054df0c9 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -103,7 +103,7 @@ pub static mut SMB_CFG_MAX_SSN2VEC_CACHE_SIZE: usize = 512; pub static mut SMB_DCERPC_MAX_STUB_SIZE: u32 = 1048576; -static mut ALPROTO_SMB: AppProto = ALPROTO_UNKNOWN; +pub(super) static mut ALPROTO_SMB: AppProto = ALPROTO_UNKNOWN; static mut SMB_MAX_TX: usize = 1024; diff --git a/src/Makefile.am b/src/Makefile.am index 129b22a2c6..bb7deae3a0 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -274,7 +274,6 @@ noinst_HEADERS = \ detect-sid.h \ detect-sip-method.h \ detect-sip-uri.h \ - detect-smb-ntlmssp.h \ detect-smb-share.h \ detect-smb-version.h \ detect-smtp.h \ @@ -861,7 +860,6 @@ libsuricata_c_a_SOURCES = \ detect-sid.c \ detect-sip-method.c \ detect-sip-uri.c \ - detect-smb-ntlmssp.c \ detect-smb-share.c \ detect-smb-version.c \ detect-smtp.c \ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 01aa08e647..35e7dc9d7e 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -21,7 +21,6 @@ * \author Victor Julien */ -#include "detect-smb-ntlmssp.h" #include "suricata-common.h" #include "suricata.h" #include "detect.h" @@ -689,8 +688,6 @@ void SigTableSetup(void) DetectDceStubDataRegister(); DetectSmbNamedPipeRegister(); DetectSmbShareRegister(); - DetectSmbNtlmsspUserRegister(); - DetectSmbNtlmsspDomainRegister(); DetectSmbVersionRegister(); DetectTlsRegister(); DetectTlsValidityRegister(); @@ -779,6 +776,7 @@ void SigTableSetup(void) SCDetectPgsqlRegister(); SCDetectSshRegister(); SCDetectQuicRegister(); + SCDetectSmbRegister(); for (size_t i = 0; i < preregistered_callbacks_nb; i++) { PreregisteredCallbacks[i](); diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index 890f110b64..9ab462a996 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -211,8 +211,6 @@ enum DetectKeywordId { DETECT_DCE_STUB_DATA, DETECT_SMB_NAMED_PIPE, DETECT_SMB_SHARE, - DETECT_SMB_NTLMSSP_USER, - DETECT_SMB_NTLMSSP_DOMAIN, DETECT_SMB_VERSION, DETECT_ENGINE_EVENT, diff --git a/src/detect-smb-ntlmssp.c b/src/detect-smb-ntlmssp.c deleted file mode 100644 index 2a94d21f66..0000000000 --- a/src/detect-smb-ntlmssp.c +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright (C) 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 Eric Leblond - * - */ - -#include "suricata-common.h" -#include "detect-engine-register.h" - -#include "detect.h" -#include "detect-parse.h" - -#include "detect-engine.h" -#include "detect-engine-buffer.h" -#include "detect-engine-mpm.h" -#include "detect-engine-state.h" -#include "detect-engine-prefilter.h" -#include "detect-engine-content-inspection.h" - -#include "detect-smb-ntlmssp.h" -#include "rust.h" - -#define BUFFER_NAME "smb_ntlmssp_user" -#define KEYWORD_NAME "smb.ntlmssp_user" -#define KEYWORD_ID DETECT_SMB_NTLMSSP_USER - -static int g_smb_nltmssp_user_buffer_id = 0; - -static int DetectSmbNtlmsspUserSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) -{ - if (SCDetectBufferSetActiveList(de_ctx, s, g_smb_nltmssp_user_buffer_id) < 0) - return -1; - - if (SCDetectSignatureSetAppProto(s, ALPROTO_SMB) < 0) - return -1; - - return 0; -} - -static InspectionBuffer *GetNtlmsspUserData(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) { - uint32_t b_len = 0; - const uint8_t *b = NULL; - - if (SCSmbTxGetNtlmsspUser(txv, &b, &b_len) != 1) - return NULL; - if (b == NULL || b_len == 0) - return NULL; - - InspectionBufferSetupAndApplyTransforms(det_ctx, list_id, buffer, b, b_len, transforms); - } - return buffer; -} - -void DetectSmbNtlmsspUserRegister(void) -{ - sigmatch_table[KEYWORD_ID].name = KEYWORD_NAME; - sigmatch_table[KEYWORD_ID].Setup = DetectSmbNtlmsspUserSetup; - sigmatch_table[KEYWORD_ID].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; - sigmatch_table[KEYWORD_ID].desc = "sticky buffer to match on SMB ntlmssp user in session setup"; - sigmatch_table[KEYWORD_ID].url = "/rules/smb-keywords.html#smb-ntlmssp-user"; - - DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister, - GetNtlmsspUserData, ALPROTO_SMB, 1); - - DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_SMB, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectBufferGeneric, GetNtlmsspUserData); - - g_smb_nltmssp_user_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME); -} - -#undef BUFFER_NAME -#undef KEYWORD_NAME -#undef KEYWORD_ID - -#define BUFFER_NAME "smb_ntlmssp_domain" -#define KEYWORD_NAME "smb.ntlmssp_domain" -#define KEYWORD_ID DETECT_SMB_NTLMSSP_DOMAIN - -static int g_smb_nltmssp_domain_buffer_id = 0; - -static int DetectSmbNtlmsspDomainSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) -{ - if (SCDetectBufferSetActiveList(de_ctx, s, g_smb_nltmssp_domain_buffer_id) < 0) - return -1; - - if (SCDetectSignatureSetAppProto(s, ALPROTO_SMB) < 0) - return -1; - - return 0; -} - -static InspectionBuffer *GetNtlmsspDomainData(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) { - uint32_t b_len = 0; - const uint8_t *b = NULL; - - if (SCSmbTxGetNtlmsspDomain(txv, &b, &b_len) != 1) - return NULL; - if (b == NULL || b_len == 0) - return NULL; - - InspectionBufferSetupAndApplyTransforms(det_ctx, list_id, buffer, b, b_len, transforms); - } - return buffer; -} - -void DetectSmbNtlmsspDomainRegister(void) -{ - sigmatch_table[KEYWORD_ID].name = KEYWORD_NAME; - sigmatch_table[KEYWORD_ID].Setup = DetectSmbNtlmsspDomainSetup; - sigmatch_table[KEYWORD_ID].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; - sigmatch_table[KEYWORD_ID].desc = - "sticky buffer to match on SMB ntlmssp domain in session setup"; - sigmatch_table[KEYWORD_ID].url = "/rules/smb-keywords.html#smb-ntlmssp-domain"; - - DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister, - GetNtlmsspDomainData, ALPROTO_SMB, 1); - - DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_SMB, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectBufferGeneric, GetNtlmsspDomainData); - - g_smb_nltmssp_domain_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME); -} diff --git a/src/detect-smb-ntlmssp.h b/src/detect-smb-ntlmssp.h deleted file mode 100644 index 46342d5975..0000000000 --- a/src/detect-smb-ntlmssp.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 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 Eric Leblond - */ - -#ifndef SURICATA_DETECT_SMB_NTLMSSP_H -#define SURICATA_DETECT_SMB_NTLMSSP_H - -void DetectSmbNtlmsspUserRegister(void); -void DetectSmbNtlmsspDomainRegister(void); - -#endif /* SURICATA_DETECT_SMB_NTLMSSP_H */