detect/snmp: move keywords to rust

Ticket: 4863

On the way, convert unit test DetectSNMPCommunityTest to a SV test.

And also, make snmp.pdu_type use a generic uint32 for detection,
allowing operators, instead of just equality.
pull/11309/head
Philippe Antoine 1 year ago committed by Victor Julien
parent 4bbe7d92dc
commit ae72376ebe

@ -6,6 +6,8 @@ snmp.version
SNMP protocol version (integer). Expected values are 1, 2 (for version 2c) or 3.
snmp.version uses an, :ref:` unsigned 32-bits integer <rules-integer-keywords>`.
Syntax::
snmp.version:[op]<number>
@ -69,6 +71,8 @@ snmp.pdu_type
SNMP PDU type (integer).
snmp.pdu_type uses an, :ref:` unsigned 32-bits integer <rules-integer-keywords>`.
Common values are:
- 0: GetRequest

@ -17,42 +17,251 @@
// written by Pierre Chifflier <chifflier@wzdftpd.net>
use crate::snmp::snmp::SNMPTransaction;
use super::snmp::{SNMPTransaction, ALPROTO_SNMP};
use crate::detect::uint::{
rs_detect_u32_free, rs_detect_u32_match, rs_detect_u32_parse, DetectUintData,
};
use crate::detect::{
DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperBufferRegister,
DetectHelperGetData, DetectHelperKeywordRegister, DetectSignatureSetAppProto, SCSigTableElmt,
SigMatchAppendSMToList, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT,
};
use std::os::raw::{c_int, c_void};
#[no_mangle]
pub unsafe extern "C" fn rs_snmp_tx_get_version(tx: &mut SNMPTransaction, version: *mut u32) {
debug_assert!(tx.version != 0, "SNMP version is 0");
*version = tx.version;
static mut G_SNMP_VERSION_KW_ID: c_int = 0;
static mut G_SNMP_VERSION_BUFFER_ID: c_int = 0;
static mut G_SNMP_PDUTYPE_KW_ID: c_int = 0;
static mut G_SNMP_PDUTYPE_BUFFER_ID: c_int = 0;
static mut G_SNMP_USM_BUFFER_ID: c_int = 0;
static mut G_SNMP_COMMUNITY_BUFFER_ID: c_int = 0;
unsafe extern "C" fn snmp_detect_version_setup(
de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
) -> c_int {
if DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 {
return -1;
}
let ctx = rs_detect_u32_parse(raw) as *mut c_void;
if ctx.is_null() {
return -1;
}
if SigMatchAppendSMToList(de, s, G_SNMP_VERSION_KW_ID, ctx, G_SNMP_VERSION_BUFFER_ID).is_null()
{
snmp_detect_version_free(std::ptr::null_mut(), ctx);
return -1;
}
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn rs_snmp_tx_get_community(
tx: &mut SNMPTransaction, buf: *mut *const u8, len: *mut u32,
) {
if let Some(ref c) = tx.community {
*buf = c.as_ptr();
*len = c.len() as u32;
unsafe extern "C" fn snmp_detect_version_match(
_de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void,
_sig: *const c_void, ctx: *const c_void,
) -> c_int {
let tx = cast_pointer!(tx, SNMPTransaction);
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
return rs_detect_u32_match(tx.version, ctx);
}
unsafe extern "C" fn snmp_detect_version_free(_de: *mut c_void, ctx: *mut c_void) {
// Just unbox...
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
rs_detect_u32_free(ctx);
}
unsafe extern "C" fn snmp_detect_pdutype_setup(
de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
) -> c_int {
if DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 {
return -1;
}
let ctx = rs_detect_u32_parse(raw) as *mut c_void;
if ctx.is_null() {
return -1;
}
if SigMatchAppendSMToList(de, s, G_SNMP_PDUTYPE_KW_ID, ctx, G_SNMP_PDUTYPE_BUFFER_ID).is_null()
{
snmp_detect_pdutype_free(std::ptr::null_mut(), ctx);
return -1;
}
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn rs_snmp_tx_get_pdu_type(tx: &mut SNMPTransaction, pdu_type: *mut u32) {
match tx.info {
Some(ref info) => {
*pdu_type = info.pdu_type.0;
}
None => {
*pdu_type = 0xffffffff;
}
unsafe extern "C" fn snmp_detect_pdutype_match(
_de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void,
_sig: *const c_void, ctx: *const c_void,
) -> c_int {
let tx = cast_pointer!(tx, SNMPTransaction);
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
if let Some(ref info) = tx.info {
let pdu_type = info.pdu_type.0;
return rs_detect_u32_match(pdu_type, ctx);
}
return 0;
}
unsafe extern "C" fn snmp_detect_pdutype_free(_de: *mut c_void, ctx: *mut c_void) {
// Just unbox...
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
rs_detect_u32_free(ctx);
}
pub unsafe extern "C" fn snmp_detect_usm_setup(
de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
) -> c_int {
if DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 {
return -1;
}
if DetectBufferSetActiveList(de, s, G_SNMP_USM_BUFFER_ID) < 0 {
return -1;
}
return 0;
}
pub unsafe extern "C" fn snmp_detect_usm_get(
tx: *const c_void, _flow_flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
) -> bool {
let tx = cast_pointer!(tx, SNMPTransaction);
if let Some(ref c) = tx.usm {
*buffer = c.as_ptr();
*buffer_len = c.len() as u32;
return true;
}
return false;
}
pub unsafe extern "C" fn snmp_detect_usm_get_data(
de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
tx: *const c_void, list_id: c_int,
) -> *mut c_void {
return DetectHelperGetData(
de,
transforms,
flow,
flow_flags,
tx,
list_id,
snmp_detect_usm_get,
);
}
pub unsafe extern "C" fn snmp_detect_community_setup(
de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
) -> c_int {
if DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 {
return -1;
}
if DetectBufferSetActiveList(de, s, G_SNMP_COMMUNITY_BUFFER_ID) < 0 {
return -1;
}
return 0;
}
pub unsafe extern "C" fn snmp_detect_community_get(
tx: *const c_void, _flow_flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
) -> bool {
let tx = cast_pointer!(tx, SNMPTransaction);
if let Some(ref c) = tx.community {
*buffer = c.as_ptr();
*buffer_len = c.len() as u32;
return true;
}
return false;
}
pub unsafe extern "C" fn snmp_detect_community_get_data(
de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
tx: *const c_void, list_id: c_int,
) -> *mut c_void {
return DetectHelperGetData(
de,
transforms,
flow,
flow_flags,
tx,
list_id,
snmp_detect_community_get,
);
}
#[no_mangle]
pub unsafe extern "C" fn rs_snmp_tx_get_usm(
tx: &mut SNMPTransaction, buf: *mut *const u8, len: *mut u32,
) {
if let Some(ref c) = tx.usm {
*buf = c.as_ptr();
*len = c.len() as u32;
pub unsafe extern "C" fn ScDetectSNMPRegister() {
let kw = SCSigTableElmt {
name: b"snmp.version\0".as_ptr() as *const libc::c_char,
desc: b"match SNMP version\0".as_ptr() as *const libc::c_char,
url: b"/rules/snmp-keywords.html#snmp-version\0".as_ptr() as *const libc::c_char,
AppLayerTxMatch: Some(snmp_detect_version_match),
Setup: snmp_detect_version_setup,
Free: Some(snmp_detect_version_free),
flags: 0,
};
unsafe {
G_SNMP_VERSION_KW_ID = DetectHelperKeywordRegister(&kw);
G_SNMP_VERSION_BUFFER_ID = DetectHelperBufferRegister(
b"snmp.version\0".as_ptr() as *const libc::c_char,
ALPROTO_SNMP,
true,
true,
);
}
let kw = SCSigTableElmt {
name: b"snmp.pdu_type\0".as_ptr() as *const libc::c_char,
desc: b"match SNMP PDU type\0".as_ptr() as *const libc::c_char,
url: b"/rules/snmp-keywords.html#snmp-pdu-type\0".as_ptr() as *const libc::c_char,
AppLayerTxMatch: Some(snmp_detect_pdutype_match),
Setup: snmp_detect_pdutype_setup,
Free: Some(snmp_detect_pdutype_free),
flags: 0,
};
unsafe {
G_SNMP_PDUTYPE_KW_ID = DetectHelperKeywordRegister(&kw);
G_SNMP_PDUTYPE_BUFFER_ID = DetectHelperBufferRegister(
b"snmp.pdu_type\0".as_ptr() as *const libc::c_char,
ALPROTO_SNMP,
true,
true,
);
}
let kw = SCSigTableElmt {
name: b"snmp.usm\0".as_ptr() as *const libc::c_char,
desc: b"SNMP content modifier to match on the SNMP usm\0".as_ptr() as *const libc::c_char,
url: b"/rules/snmp-keywords.html#snmp-usm\0".as_ptr() as *const libc::c_char,
Setup: snmp_detect_usm_setup,
flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
AppLayerTxMatch: None,
Free: None,
};
unsafe {
let _g_snmp_usm_kw_id = DetectHelperKeywordRegister(&kw);
G_SNMP_USM_BUFFER_ID = DetectHelperBufferMpmRegister(
b"snmp.usm\0".as_ptr() as *const libc::c_char,
b"SNMP USM\0".as_ptr() as *const libc::c_char,
ALPROTO_SNMP,
true,
true,
snmp_detect_usm_get_data,
);
}
let kw = SCSigTableElmt {
name: b"snmp.community\0".as_ptr() as *const libc::c_char,
desc: b"SNMP content modifier to match on the SNMP community\0".as_ptr()
as *const libc::c_char,
url: b"/rules/snmp-keywords.html#snmp-community\0".as_ptr() as *const libc::c_char,
Setup: snmp_detect_community_setup,
flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
AppLayerTxMatch: None,
Free: None,
};
unsafe {
let _g_snmp_community_kw_id = DetectHelperKeywordRegister(&kw);
G_SNMP_COMMUNITY_BUFFER_ID = DetectHelperBufferMpmRegister(
b"snmp.community\0".as_ptr() as *const libc::c_char,
b"SNMP Community identifier\0".as_ptr() as *const libc::c_char,
ALPROTO_SNMP,
true,
true,
snmp_detect_community_get_data,
);
}
}

@ -322,7 +322,7 @@ pub extern "C" fn rs_snmp_tx_get_alstate_progress(_tx: *mut std::os::raw::c_void
1
}
static mut ALPROTO_SNMP : AppProto = ALPROTO_UNKNOWN;
pub(super) static mut ALPROTO_SNMP : AppProto = ALPROTO_UNKNOWN;
// Read PDU sequence and extract version, if similar to SNMP definition
fn parse_pdu_envelope_version(i:&[u8]) -> IResult<&[u8],u32> {

@ -310,10 +310,6 @@ noinst_HEADERS = \
detect-smb-ntlmssp.h \
detect-smb-share.h \
detect-smb-version.h \
detect-snmp-community.h \
detect-snmp-pdu_type.h \
detect-snmp-usm.h \
detect-snmp-version.h \
detect-dhcp-leasetime.h \
detect-dhcp-rebinding-time.h \
detect-dhcp-renewal-time.h \
@ -936,10 +932,6 @@ libsuricata_c_a_SOURCES = \
detect-smb-ntlmssp.c \
detect-smb-share.c \
detect-smb-version.c \
detect-snmp-community.c \
detect-snmp-pdu_type.c \
detect-snmp-usm.c \
detect-snmp-version.c \
detect-dhcp-leasetime.c \
detect-dhcp-rebinding-time.c \
detect-dhcp-renewal-time.c \
@ -1263,8 +1255,6 @@ EXTRA_DIST = \
tests/detect-http2.c \
tests/detect-icmpv6-mtu.c \
tests/detect-icmpv6hdr.c \
tests/detect-snmp-pdu_type.c \
tests/detect-snmp-version.c \
tests/detect-template.c \
tests/detect-transform-pcrexform.c \
tests/detect-transform-xor.c \

@ -215,10 +215,6 @@
#include "detect-dhcp-leasetime.h"
#include "detect-dhcp-rebinding-time.h"
#include "detect-dhcp-renewal-time.h"
#include "detect-snmp-usm.h"
#include "detect-snmp-version.h"
#include "detect-snmp-community.h"
#include "detect-snmp-pdu_type.h"
#include "detect-mqtt-type.h"
#include "detect-mqtt-flags.h"
#include "detect-mqtt-qos.h"
@ -740,10 +736,6 @@ void SigTableSetup(void)
DetectDHCPLeaseTimeRegister();
DetectDHCPRebindingTimeRegister();
DetectDHCPRenewalTimeRegister();
DetectSNMPUsmRegister();
DetectSNMPVersionRegister();
DetectSNMPCommunityRegister();
DetectSNMPPduTypeRegister();
DetectMQTTTypeRegister();
DetectMQTTFlagsRegister();
DetectMQTTQosRegister();
@ -788,6 +780,8 @@ void SigTableSetup(void)
DetectFileHandlerRegister();
ScDetectSNMPRegister();
/* close keyword registration */
DetectBufferTypeCloseRegistration();
}

@ -312,10 +312,6 @@ enum DetectKeywordId {
DETECT_AL_DHCP_LEASETIME,
DETECT_AL_DHCP_REBINDING_TIME,
DETECT_AL_DHCP_RENEWAL_TIME,
DETECT_AL_SNMP_USM,
DETECT_AL_SNMP_VERSION,
DETECT_AL_SNMP_COMMUNITY,
DETECT_AL_SNMP_PDU_TYPE,
DETECT_AL_MQTT_TYPE,
DETECT_AL_MQTT_FLAGS,
DETECT_AL_MQTT_QOS,

@ -1,101 +0,0 @@
/* Copyright (C) 2015-2019 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 Pierre Chifflier <chifflier@wzdftpd.net>
*
* Set up of the "snmp.community" keyword to allow content
* inspections on the decoded snmp community.
*/
#include "suricata-common.h"
#include "conf.h"
#include "detect.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "detect-engine-prefilter.h"
#include "detect-engine-content-inspection.h"
#include "detect-snmp-community.h"
#include "app-layer-parser.h"
#include "rust.h"
static int DetectSNMPCommunitySetup(DetectEngineCtx *, Signature *,
const char *);
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
const int list_id);
static int g_snmp_rust_id = 0;
void DetectSNMPCommunityRegister(void)
{
sigmatch_table[DETECT_AL_SNMP_COMMUNITY].name = "snmp.community";
sigmatch_table[DETECT_AL_SNMP_COMMUNITY].desc =
"SNMP content modifier to match on the SNMP community";
sigmatch_table[DETECT_AL_SNMP_COMMUNITY].Setup = DetectSNMPCommunitySetup;
sigmatch_table[DETECT_AL_SNMP_COMMUNITY].url = "/rules/snmp-keywords.html#snmp-community";
sigmatch_table[DETECT_AL_SNMP_COMMUNITY].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;
/* register inspect engines */
DetectAppLayerInspectEngineRegister("snmp.community", ALPROTO_SNMP, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("snmp.community", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_SNMP, 0);
DetectAppLayerInspectEngineRegister("snmp.community", ALPROTO_SNMP, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("snmp.community", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_SNMP, 0);
DetectBufferTypeSetDescriptionByName("snmp.community", "SNMP Community identifier");
g_snmp_rust_id = DetectBufferTypeGetByName("snmp.community");
}
static int DetectSNMPCommunitySetup(DetectEngineCtx *de_ctx, Signature *s,
const char *str)
{
if (DetectBufferSetActiveList(de_ctx, s, g_snmp_rust_id) < 0)
return -1;
if (DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0)
return -1;
return 0;
}
static InspectionBuffer *GetData(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 data_len = 0;
const uint8_t *data = NULL;
rs_snmp_tx_get_community(txv, &data, &data_len);
if (data == NULL || data_len == 0) {
return NULL;
}
InspectionBufferSetup(det_ctx, list_id, buffer, data, data_len);
InspectionBufferApplyTransforms(buffer, transforms);
}
return buffer;
}

@ -1,29 +0,0 @@
/* Copyright (C) 2015-2019 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 FirstName LastName <yourname@domain>
*/
#ifndef SURICATA_DETECT_SNMP_COMMUNITY_H
#define SURICATA_DETECT_SNMP_COMMUNITY_H
void DetectSNMPCommunityRegister(void);
#endif /* SURICATA_DETECT_SNMP_COMMUNITY_H */

@ -1,221 +0,0 @@
/* Copyright (C) 2015-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.
*/
/**
* \file
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#include "suricata-common.h"
#include "conf.h"
#include "detect.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-content-inspection.h"
#include "detect-snmp-pdu_type.h"
#include "app-layer-parser.h"
#include "rust.h"
/**
* [snmp.pdu_type]:<type>;
*/
#define PARSE_REGEX "^\\s*([0-9]+)\\s*$"
static DetectParseRegex parse_regex;
typedef struct DetectSNMPPduTypeData_ {
uint32_t pdu_type;
} DetectSNMPPduTypeData;
static DetectSNMPPduTypeData *DetectSNMPPduTypeParse (const char *);
static int DetectSNMPPduTypeSetup (DetectEngineCtx *, Signature *s, const char *str);
static void DetectSNMPPduTypeFree(DetectEngineCtx *, void *);
#ifdef UNITTESTS
static void DetectSNMPPduTypeRegisterTests(void);
#endif
static int g_snmp_pdu_type_buffer_id = 0;
static int DetectSNMPPduTypeMatch (DetectEngineThreadCtx *, Flow *,
uint8_t, void *, void *, const Signature *,
const SigMatchCtx *);
void DetectSNMPPduTypeRegister(void)
{
sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].name = "snmp.pdu_type";
sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].desc = "match SNMP PDU type";
sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].url = "/rules/snmp-keywords.html#snmp-pdu-type";
sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].Match = NULL;
sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].AppLayerTxMatch = DetectSNMPPduTypeMatch;
sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].Setup = DetectSNMPPduTypeSetup;
sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].Free = DetectSNMPPduTypeFree;
#ifdef UNITTESTS
sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].RegisterTests = DetectSNMPPduTypeRegisterTests;
#endif
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
DetectAppLayerInspectEngineRegister("snmp.pdu_type", ALPROTO_SNMP, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister("snmp.pdu_type", ALPROTO_SNMP, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectGenericList, NULL);
g_snmp_pdu_type_buffer_id = DetectBufferTypeGetByName("snmp.pdu_type");
}
/**
* \internal
* \brief Function to match pdu_type of a TX
*
* \param t Pointer to thread vars.
* \param det_ctx Pointer to the pattern matcher thread.
* \param f Pointer to the current flow.
* \param flags Flags.
* \param state App layer state.
* \param s Pointer to the Signature.
* \param m Pointer to the sigmatch that we will cast into
* DetectSNMPPduTypeData.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DetectSNMPPduTypeMatch (DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state,
void *txv, const Signature *s,
const SigMatchCtx *ctx)
{
SCEnter();
const DetectSNMPPduTypeData *dd = (const DetectSNMPPduTypeData *)ctx;
uint32_t pdu_type;
rs_snmp_tx_get_pdu_type(txv, &pdu_type);
SCLogDebug("pdu_type %u ref_pdu_type %d",
pdu_type, dd->pdu_type);
if (pdu_type == dd->pdu_type)
SCReturnInt(1);
SCReturnInt(0);
}
/**
* \internal
* \brief Function to parse options passed via snmp.pdu_type keywords.
*
* \param rawstr Pointer to the user provided options.
*
* \retval dd pointer to DetectSNMPPduTypeData on success.
* \retval NULL on failure.
*/
static DetectSNMPPduTypeData *DetectSNMPPduTypeParse (const char *rawstr)
{
DetectSNMPPduTypeData *dd = NULL;
int res = 0;
size_t pcre2len;
char value1[20] = "";
char *endptr = NULL;
pcre2_match_data *match = NULL;
int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
if (ret != 2) {
SCLogError("Parse error %s", rawstr);
goto error;
}
pcre2len = sizeof(value1);
res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)value1, &pcre2len);
if (res < 0) {
SCLogError("pcre2_substring_copy_bynumber failed");
goto error;
}
dd = SCCalloc(1, sizeof(DetectSNMPPduTypeData));
if (unlikely(dd == NULL))
goto error;
/* set the value */
dd->pdu_type = strtoul(value1, &endptr, 10);
if (endptr == NULL || *endptr != '\0') {
SCLogError("invalid character as arg "
"to snmp.pdu_type keyword");
goto error;
}
pcre2_match_data_free(match);
return dd;
error:
if (match) {
pcre2_match_data_free(match);
}
if (dd)
SCFree(dd);
return NULL;
}
/**
* \brief Function to add the parsed snmp pdu_type field into the current signature.
*
* \param de_ctx Pointer to the Detection Engine Context.
* \param s Pointer to the Current Signature.
* \param rawstr Pointer to the user provided flags options.
* \param type Defines if this is notBefore or notAfter.
*
* \retval 0 on Success.
* \retval -1 on Failure.
*/
static int DetectSNMPPduTypeSetup (DetectEngineCtx *de_ctx, Signature *s,
const char *rawstr)
{
DetectSNMPPduTypeData *dd = NULL;
if (DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0)
return -1;
dd = DetectSNMPPduTypeParse(rawstr);
if (dd == NULL) {
SCLogError("Parsing \'%s\' failed", rawstr);
goto error;
}
/* okay so far so good, lets get this into a SigMatch
* and put it in the Signature. */
SCLogDebug("snmp.pdu_type %d", dd->pdu_type);
if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_SNMP_PDU_TYPE, (SigMatchCtx *)dd,
g_snmp_pdu_type_buffer_id) == NULL) {
goto error;
}
return 0;
error:
DetectSNMPPduTypeFree(de_ctx, dd);
return -1;
}
/**
* \internal
* \brief Function to free memory associated with DetectSNMPPduTypeData.
*
* \param de_ptr Pointer to DetectSNMPPduTypeData.
*/
static void DetectSNMPPduTypeFree(DetectEngineCtx *de_ctx, void *ptr)
{
SCFree(ptr);
}
#ifdef UNITTESTS
#include "tests/detect-snmp-pdu_type.c"
#endif /* UNITTESTS */

@ -1,29 +0,0 @@
/* Copyright (C) 2015-2019 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 Pierre Chifflier <chifflier@wzdftpd.net>
*/
#ifndef SURICATA_DETECT_SNMP_PDU_TYPE_H
#define SURICATA_DETECT_SNMP_PDU_TYPE_H
void DetectSNMPPduTypeRegister(void);
#endif /* SURICATA_DETECT_SNMP_PDU_TYPE_H */

@ -1,81 +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.
*/
#include "suricata-common.h"
#include "rust.h"
#include "detect-snmp-usm.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "detect-engine-prefilter.h"
#include "detect-parse.h"
static int g_buffer_id = 0;
static int DetectSNMPUsmSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{
if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
return -1;
if (DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0)
return -1;
return 0;
}
static InspectionBuffer *GetData(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 data_len = 0;
const uint8_t *data = NULL;
rs_snmp_tx_get_usm(txv, &data, &data_len);
if (data == NULL || data_len == 0) {
return NULL;
}
InspectionBufferSetup(det_ctx, list_id, buffer, data, data_len);
InspectionBufferApplyTransforms(buffer, transforms);
}
return buffer;
}
void DetectSNMPUsmRegister(void)
{
sigmatch_table[DETECT_AL_SNMP_USM].name = "snmp.usm";
sigmatch_table[DETECT_AL_SNMP_USM].desc = "SNMP content modifier to match on the SNMP usm";
sigmatch_table[DETECT_AL_SNMP_USM].Setup = DetectSNMPUsmSetup;
sigmatch_table[DETECT_AL_SNMP_USM].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
/* register inspect engines */
DetectAppLayerInspectEngineRegister("snmp.usm", ALPROTO_SNMP, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("snmp.usm", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_SNMP, 0);
DetectAppLayerInspectEngineRegister("snmp.usm", ALPROTO_SNMP, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("snmp.usm", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_SNMP, 0);
DetectBufferTypeSetDescriptionByName("snmp.usm", "SNMP USM");
g_buffer_id = DetectBufferTypeGetByName("snmp.usm");
}

@ -1,23 +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.
*/
#ifndef SURICATA_DETECT_SNMP_USM_H
#define SURICATA_DETECT_SNMP_USM_H
void DetectSNMPUsmRegister(void);
#endif /* SURICATA_DETECT_SNMP_USM_H */

@ -1,174 +0,0 @@
/* Copyright (C) 2015-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.
*/
/**
* \file
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#include "suricata-common.h"
#include "conf.h"
#include "detect.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-content-inspection.h"
#include "detect-snmp-version.h"
#include "detect-engine-uint.h"
#include "app-layer-parser.h"
#include "rust.h"
static int DetectSNMPVersionSetup (DetectEngineCtx *, Signature *s, const char *str);
static void DetectSNMPVersionFree(DetectEngineCtx *, void *);
#ifdef UNITTESTS
static void DetectSNMPVersionRegisterTests(void);
#endif
static int g_snmp_version_buffer_id = 0;
static int DetectSNMPVersionMatch (DetectEngineThreadCtx *, Flow *,
uint8_t, void *, void *, const Signature *,
const SigMatchCtx *);
/**
* \brief Registration function for snmp.procedure keyword.
*/
void DetectSNMPVersionRegister (void)
{
sigmatch_table[DETECT_AL_SNMP_VERSION].name = "snmp.version";
sigmatch_table[DETECT_AL_SNMP_VERSION].desc = "match SNMP version";
sigmatch_table[DETECT_AL_SNMP_VERSION].url = "/rules/snmp-keywords.html#snmp-version";
sigmatch_table[DETECT_AL_SNMP_VERSION].Match = NULL;
sigmatch_table[DETECT_AL_SNMP_VERSION].AppLayerTxMatch = DetectSNMPVersionMatch;
sigmatch_table[DETECT_AL_SNMP_VERSION].Setup = DetectSNMPVersionSetup;
sigmatch_table[DETECT_AL_SNMP_VERSION].Free = DetectSNMPVersionFree;
#ifdef UNITTESTS
sigmatch_table[DETECT_AL_SNMP_VERSION].RegisterTests = DetectSNMPVersionRegisterTests;
#endif
DetectAppLayerInspectEngineRegister("snmp.version", ALPROTO_SNMP, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister("snmp.version", ALPROTO_SNMP, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectGenericList, NULL);
g_snmp_version_buffer_id = DetectBufferTypeGetByName("snmp.version");
}
/**
* \internal
* \brief Function to match version of a TX
*
* \param t Pointer to thread vars.
* \param det_ctx Pointer to the pattern matcher thread.
* \param f Pointer to the current flow.
* \param flags Flags.
* \param state App layer state.
* \param s Pointer to the Signature.
* \param m Pointer to the sigmatch that we will cast into
* DetectU32Data.
*
* \retval 0 no match.
* \retval 1 match.
*/
static int DetectSNMPVersionMatch (DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state,
void *txv, const Signature *s,
const SigMatchCtx *ctx)
{
SCEnter();
const DetectU32Data *dd = (const DetectU32Data *)ctx;
uint32_t version;
rs_snmp_tx_get_version(txv, &version);
SCLogDebug("version %u mode %u ref_version %d", version, dd->mode, dd->arg1);
if (DetectU32Match(version, dd))
SCReturnInt(1);
SCReturnInt(0);
}
/**
* \internal
* \brief Function to parse options passed via snmp.version keywords.
*
* \param rawstr Pointer to the user provided options.
*
* \retval dd pointer to DetectU32Data on success.
* \retval NULL on failure.
*/
static DetectU32Data *DetectSNMPVersionParse(const char *rawstr)
{
return DetectU32Parse(rawstr);
}
/**
* \brief Function to add the parsed snmp version field into the current signature.
*
* \param de_ctx Pointer to the Detection Engine Context.
* \param s Pointer to the Current Signature.
* \param rawstr Pointer to the user provided flags options.
* \param type Defines if this is notBefore or notAfter.
*
* \retval 0 on Success.
* \retval -1 on Failure.
*/
static int DetectSNMPVersionSetup (DetectEngineCtx *de_ctx, Signature *s,
const char *rawstr)
{
DetectU32Data *dd = NULL;
if (DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0)
return -1;
dd = DetectSNMPVersionParse(rawstr);
if (dd == NULL) {
SCLogError("Parsing \'%s\' failed", rawstr);
goto error;
}
/* okay so far so good, lets get this into a SigMatch
* and put it in the Signature. */
SCLogDebug("snmp.version %d", dd->arg1);
if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_SNMP_VERSION, (SigMatchCtx *)dd,
g_snmp_version_buffer_id) == NULL) {
goto error;
}
return 0;
error:
DetectSNMPVersionFree(de_ctx, dd);
return -1;
}
/**
* \internal
* \brief Function to free memory associated with DetectU32Data.
*
* \param de_ptr Pointer to DetectU32Data.
*/
static void DetectSNMPVersionFree(DetectEngineCtx *de_ctx, void *ptr)
{
rs_detect_u32_free(ptr);
}
#ifdef UNITTESTS
#include "tests/detect-snmp-version.c"
#endif /* UNITTESTS */

@ -1,29 +0,0 @@
/* Copyright (C) 2015-2019 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 Pierre Chifflier <chifflier@wzdftpd.net>
*/
#ifndef SURICATA_DETECT_SNMP_VERSION_H
#define SURICATA_DETECT_SNMP_VERSION_H
void DetectSNMPVersionRegister(void);
#endif /* SURICATA_DETECT_SNMP_VERSION_H */

@ -1,40 +0,0 @@
/* Copyright (C) 2019 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.
*/
#include "util-unittest.h"
#include "util-unittest-helper.h"
/**
* \test This is a test for a valid value 2.
*
* \retval 1 on success.
* \retval 0 on failure.
*/
static int SNMPValidityTestParse01 (void)
{
DetectSNMPPduTypeData *dd = NULL;
dd = DetectSNMPPduTypeParse("2");
FAIL_IF_NULL(dd);
FAIL_IF_NOT(dd->pdu_type == 2);
DetectSNMPPduTypeFree(NULL, dd);
PASS;
}
static void DetectSNMPPduTypeRegisterTests(void)
{
UtRegisterTest("SNMPValidityTestParse01", SNMPValidityTestParse01);
}

@ -1,57 +0,0 @@
/* Copyright (C) 2019 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.
*/
#include "util-unittest.h"
#include "util-unittest-helper.h"
/**
* \test This is a test for a valid value 2.
*
* \retval 1 on success.
* \retval 0 on failure.
*/
static int SNMPValidityTestParse01 (void)
{
DetectU32Data *dd = NULL;
dd = DetectSNMPVersionParse("2");
FAIL_IF_NULL(dd);
FAIL_IF_NOT(dd->arg1 == 2 && dd->mode == DETECT_UINT_EQ);
DetectSNMPVersionFree(NULL, dd);
PASS;
}
/**
* \test This is a test for a valid value >2.
*
* \retval 1 on success.
* \retval 0 on failure.
*/
static int SNMPValidityTestParse02 (void)
{
DetectU32Data *dd = NULL;
dd = DetectSNMPVersionParse(">2");
FAIL_IF_NULL(dd);
FAIL_IF_NOT(dd->arg1 == 2 && dd->mode == DETECT_UINT_GT);
DetectSNMPVersionFree(NULL, dd);
PASS;
}
static void DetectSNMPVersionRegisterTests(void)
{
UtRegisterTest("SNMPValidityTestParse01", SNMPValidityTestParse01);
UtRegisterTest("SNMPValidityTestParse02", SNMPValidityTestParse02);
}
Loading…
Cancel
Save