diff --git a/rust/src/smb/detect.rs b/rust/src/smb/detect.rs index 2b6de20aae..7d3cffef94 100644 --- a/rust/src/smb/detect.rs +++ b/rust/src/smb/detect.rs @@ -16,7 +16,7 @@ */ use super::smb::ALPROTO_SMB; -use crate::core::STREAM_TOSERVER; +use crate::core::{STREAM_TOCLIENT, 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; @@ -24,11 +24,14 @@ use crate::detect::{helper_keyword_register_sticky_buffer, SigTableElmtStickyBuf use crate::direction::Direction; use crate::smb::smb::*; use std::ffi::CStr; -use std::os::raw::{c_char, c_int, c_void}; +use std::os::raw::{c_char, c_int, c_uint, c_void}; use std::ptr; use suricata_sys::sys::{ - DetectEngineCtx, SCDetectBufferSetActiveList, SCDetectHelperBufferMpmRegister, - SCDetectHelperKeywordAliasRegister, SCDetectSignatureSetAppProto, Signature, + DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectBufferSetActiveList, + SCDetectGetLastSMFromLists, SCDetectHelperBufferMpmRegister, SCDetectHelperBufferRegister, + SCDetectHelperKeywordAliasRegister, SCDetectHelperKeywordRegister, + SCDetectSignatureSetAppProto, SCSigMatchAppendSMToList, SCSigTableAppLiteElmt, SigMatchCtx, + Signature, }; unsafe extern "C" fn smb_tx_get_share( @@ -189,19 +192,7 @@ unsafe extern "C" fn smb_tx_get_ntlmssp_domain( return false; } -#[no_mangle] -pub unsafe extern "C" fn SCSmbVersionMatch(tx: &SMBTransaction, version_data: &mut u8) -> u8 { - let version = tx.vercmd.get_version(); - SCLogDebug!("smb_version: version returned: {}", version); - if version == *version_data { - return 1; - } - - return 0; -} - -#[no_mangle] -pub unsafe extern "C" fn SCSmbVersionParse(carg: *const c_char) -> *mut c_void { +unsafe extern "C" fn smb_version_parse(carg: *const c_char) -> *mut c_void { if carg.is_null() { return std::ptr::null_mut(); } @@ -228,8 +219,7 @@ fn parse_version_data(arg: &str) -> Result { return Ok(version); } -#[no_mangle] -pub unsafe extern "C" fn SCSmbVersionFree(ptr: *mut c_void) { +unsafe extern "C" fn smb_version_free(_de_ctx: *mut DetectEngineCtx, ptr: *mut c_void) { std::mem::drop(Box::from_raw(ptr as *mut u8)); } @@ -281,10 +271,63 @@ unsafe extern "C" fn smb_named_pipe_setup( return 0; } +unsafe extern "C" fn smb_version_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 !SCDetectGetLastSMFromLists(s, G_SMB_VERSION_KW_ID as c_uint, -1).is_null() { + SCLogError!( + "Can't use 2 or more smb.version declarations in the same sig. Invalidating signature." + ); + return -1; + } + + let dod = smb_version_parse(raw); + if dod.is_null() { + return -1; + } + + if SCSigMatchAppendSMToList( + de, + s, + G_SMB_VERSION_KW_ID, + dod as *mut SigMatchCtx, + G_SMB_VERSION_BUFFER_ID, + ) + .is_null() + { + smb_version_free(std::ptr::null_mut(), dod); + return -1; + } + + return 0; +} + +unsafe extern "C" fn smb_version_match( + _det_ctx: *mut DetectEngineThreadCtx, _f: *mut Flow, _flags: u8, _state: *mut c_void, + tx: *mut c_void, _s: *const Signature, m: *const SigMatchCtx, +) -> c_int { + let tx = cast_pointer!(tx, SMBTransaction); + let version_data = m as *const u8; + + let version = tx.vercmd.get_version(); + SCLogDebug!("smb_version: version returned: {}", version); + if version == *version_data { + 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; static mut G_SMB_SHARE_BUFFER_ID: c_int = 0; static mut G_SMB_NAMED_PIPE_BUFFER_ID: c_int = 0; +static mut G_SMB_VERSION_KW_ID: u16 = 0; +static mut G_SMB_VERSION_BUFFER_ID: c_int = 0; #[no_mangle] pub unsafe extern "C" fn SCDetectSmbRegister() { @@ -355,6 +398,25 @@ pub unsafe extern "C" fn SCDetectSmbRegister() { named_pipe_keyword_id, b"smb_named_pipe\0".as_ptr() as *const libc::c_char, ); + + // Register smb.version keyword (match function) + let version_kw = SCSigTableAppLiteElmt { + name: b"smb.version\0".as_ptr() as *const libc::c_char, + desc: b"smb keyword to match on SMB version\0".as_ptr() as *const libc::c_char, + url: b"/rules/smb-keywords.html#smb-version\0".as_ptr() as *const libc::c_char, + Setup: Some(smb_version_setup), + flags: 0, + AppLayerTxMatch: Some(smb_version_match), + Free: Some(smb_version_free), + }; + + G_SMB_VERSION_KW_ID = SCDetectHelperKeywordRegister(&version_kw); + + G_SMB_VERSION_BUFFER_ID = SCDetectHelperBufferRegister( + b"smb_version\0".as_ptr() as *const libc::c_char, + ALPROTO_SMB, + STREAM_TOSERVER | STREAM_TOCLIENT, + ); } #[cfg(test)] diff --git a/src/Makefile.am b/src/Makefile.am index 306664c090..f170992c6e 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-version.h \ detect-smtp.h \ detect-ssl-state.h \ detect-ssl-version.h \ @@ -859,7 +858,6 @@ libsuricata_c_a_SOURCES = \ detect-sid.c \ detect-sip-method.c \ detect-sip-uri.c \ - detect-smb-version.c \ detect-smtp.c \ detect-ssl-state.c \ detect-ssl-version.c \ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 5cdfd18382..37d7b7c0f5 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -77,7 +77,6 @@ #include "detect-config.h" -#include "detect-smb-version.h" #include "detect-smtp.h" #include "detect-base64-decode.h" @@ -685,7 +684,6 @@ void SigTableSetup(void) DetectDceIfaceRegister(); DetectDceOpnumRegister(); DetectDceStubDataRegister(); - DetectSmbVersionRegister(); DetectTlsRegister(); DetectTlsValidityRegister(); DetectTlsVersionRegister(); diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index ac62f457cf..c07a26dd97 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -209,7 +209,6 @@ enum DetectKeywordId { DETECT_DCE_IFACE, DETECT_DCE_OPNUM, DETECT_DCE_STUB_DATA, - DETECT_SMB_VERSION, DETECT_ENGINE_EVENT, DETECT_STREAM_EVENT, diff --git a/src/detect-smb-version.c b/src/detect-smb-version.c deleted file mode 100644 index 63d32369ae..0000000000 --- a/src/detect-smb-version.c +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2022-2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Eloy Pérez - * \author Jason Taylor - * - * Implements the smb.version keyword - */ - -#include "suricata-common.h" - -#include "detect.h" -#include "detect-parse.h" - -#include "detect-engine.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-version.h" -#include "rust.h" - -#define BUFFER_NAME "smb_version" -#define KEYWORD_NAME "smb.version" - -static int g_smb_version_list_id = 0; - -static void DetectSmbVersionFree(DetectEngineCtx *de_ctx, void *ptr) -{ - - SCLogDebug("smb_version: DetectSmbVersionFree"); - SCSmbVersionFree(ptr); -} - -/** - * \brief Creates a SigMatch for the "smb.version" keyword being sent as argument, - * and appends it to the SCSmbVersionMatch Signature(s). - * - * \param de_ctx Pointer to the detection engine context. - * \param s Pointer to signature for the current Signature being parsed - * from the rules. - * \param arg Pointer to the string holding the keyword value. - * - * \retval 0 on success, -1 on failure - */ - -static int DetectSmbVersionSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) -{ - SCLogDebug("smb_version: DetectSmbVersionSetup"); - - if (SCDetectSignatureSetAppProto(s, ALPROTO_SMB) < 0) - return -1; - - if (arg == NULL) { - SCLogError("Error parsing smb.version option in signature, it needs a value"); - return -1; - } - - if (SCDetectGetLastSMFromLists(s, DETECT_SMB_VERSION, -1)) { - SCLogError("Can't use 2 or more smb.version declarations in " - "the same sig. Invalidating signature."); - return -1; - } - - void *dod = SCSmbVersionParse(arg); - - if (dod == NULL) { - SCLogError("Error parsing smb.version option in signature"); - return -1; - } - - if (SCSigMatchAppendSMToList( - de_ctx, s, DETECT_SMB_VERSION, (SigMatchCtx *)dod, g_smb_version_list_id) == NULL) { - DetectSmbVersionFree(de_ctx, dod); - return -1; - } - - return 0; -} - -/** - * \brief App layer match function for the "smb.version" keyword. - * - * \param t Pointer to the ThreadVars instance. - * \param det_ctx Pointer to the DetectEngineThreadCtx. - * \param f Pointer to the flow. - * \param flags Pointer to the flags indicating the flow direction. - * \param state Pointer to the app layer state data. - * \param s Pointer to the Signature instance. - * \param m Pointer to the SigMatch. - * - * \retval 1 On Match. - * \retval 0 On no match. - */ - -static int DetectSmbVersionMatchRust(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *m) -{ - - SCLogDebug("smb_version: DetectSmbVersionMatchRust"); - - int matchvalue = SCSmbVersionMatch(txv, (void *)m); - - if (matchvalue != 1) { - SCLogDebug("SCSmbVersionMatch: didn't match"); - SCReturnInt(0); - } else { - SCLogDebug("SCSmbVersionMatch: matched!"); - return matchvalue; - } -} - -/** - * \brief Registers the keyword handlers for the "smb_version" keyword. - */ - -void DetectSmbVersionRegister(void) -{ - sigmatch_table[DETECT_SMB_VERSION].name = KEYWORD_NAME; - sigmatch_table[DETECT_SMB_VERSION].Setup = DetectSmbVersionSetup; - sigmatch_table[DETECT_SMB_VERSION].Match = NULL; - sigmatch_table[DETECT_SMB_VERSION].AppLayerTxMatch = DetectSmbVersionMatchRust; - sigmatch_table[DETECT_SMB_VERSION].Free = DetectSmbVersionFree; - sigmatch_table[DETECT_SMB_VERSION].desc = "smb keyword to match on SMB version"; - sigmatch_table[DETECT_SMB_VERSION].url = "/rules/smb-keywords.html#smb-version"; - - DetectAppLayerInspectEngineRegister( - BUFFER_NAME, ALPROTO_SMB, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); - - DetectAppLayerInspectEngineRegister( - BUFFER_NAME, ALPROTO_SMB, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL); - - g_smb_version_list_id = DetectBufferTypeRegister(BUFFER_NAME); - - SCLogDebug("registering " BUFFER_NAME " rule option"); -} diff --git a/src/detect-smb-version.h b/src/detect-smb-version.h deleted file mode 100644 index 4d4e12b737..0000000000 --- a/src/detect-smb-version.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (C) 2022-2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#ifndef SURICATA_DETECT_SMB_VERSION_H -#define SURICATA_DETECT_SMB_VERSION_H - -/** \brief registers the keyword into the engine. Called from - * detect.c::SigTableSetup() */ -void DetectSmbVersionRegister(void); - -#endif /* SURICATA_DETECT_SMB_VERSION_H */ \ No newline at end of file