detect/snmp: pdu_type keyword now accepts strings

Ticket: 6723
pull/13892/head
Philippe Antoine 2 months ago committed by Victor Julien
parent 0553dfa814
commit 9869fb776b

@ -73,17 +73,17 @@ SNMP PDU type (integer).
snmp.pdu_type uses an, :ref:` unsigned 32-bits integer <rules-integer-keywords>`. snmp.pdu_type uses an, :ref:` unsigned 32-bits integer <rules-integer-keywords>`.
Common values are: You can specify the value as an integer or a string:
- 0: GetRequest - 0: get_request
- 1: GetNextRequest - 1: get_next_request
- 2: Response - 2: response
- 3: SetRequest - 3: set_request
- 4: TrapV1 (obsolete, was the old Trap-PDU in SNMPv1) - 4: trap_v1 (obsolete, was the old Trap-PDU in SNMPv1)
- 5: GetBulkRequest - 5: get_bulk_request
- 6: InformRequest - 6: inform_request
- 7: TrapV2 - 7: trap_v2
- 8: Report - 8: report
This keyword will not match if the value is not accessible within (for ex, an encrypted This keyword will not match if the value is not accessible within (for ex, an encrypted
SNMP v3 message). SNMP v3 message).
@ -91,7 +91,7 @@ SNMP v3 message).
Syntax:: Syntax::
snmp.pdu_type:<number> snmp.pdu_type:(mode) <number or string>
Signature example:: Signature example::

@ -17,10 +17,16 @@
// written by Pierre Chifflier <chifflier@wzdftpd.net> // written by Pierre Chifflier <chifflier@wzdftpd.net>
use super::snmp::{SNMPTransaction, ALPROTO_SNMP}; use super::snmp::{SNMPTransaction, SnmpPduType, ALPROTO_SNMP};
use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER}; use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER};
use crate::detect::uint::{DetectUintData, SCDetectU32Free, SCDetectU32Match, SCDetectU32Parse}; use crate::detect::uint::{
use crate::detect::{helper_keyword_register_sticky_buffer, SigTableElmtStickyBuffer, SIGMATCH_INFO_UINT32}; detect_parse_uint_enum, DetectUintData, SCDetectU32Free, SCDetectU32Match, SCDetectU32Parse,
};
use crate::detect::{
helper_keyword_register_sticky_buffer, SigTableElmtStickyBuffer, SIGMATCH_INFO_ENUM_UINT,
SIGMATCH_INFO_UINT32,
};
use std::ffi::CStr;
use std::os::raw::{c_int, c_void}; use std::os::raw::{c_int, c_void};
use suricata_sys::sys::{ use suricata_sys::sys::{
DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectBufferSetActiveList, DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectBufferSetActiveList,
@ -76,13 +82,26 @@ unsafe extern "C" fn snmp_detect_version_free(_de: *mut DetectEngineCtx, ctx: *m
SCDetectU32Free(ctx); SCDetectU32Free(ctx);
} }
unsafe extern "C" fn snmp_detect_pdutype_parse(
ustr: *const std::os::raw::c_char,
) -> *mut DetectUintData<u32> {
let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
if let Ok(s) = ft_name.to_str() {
if let Some(ctx) = detect_parse_uint_enum::<u32, SnmpPduType>(s) {
let boxed = Box::new(ctx);
return Box::into_raw(boxed) as *mut _;
}
}
return std::ptr::null_mut();
}
unsafe extern "C" fn snmp_detect_pdutype_setup( unsafe extern "C" fn snmp_detect_pdutype_setup(
de: *mut DetectEngineCtx, s: *mut Signature, raw: *const libc::c_char, de: *mut DetectEngineCtx, s: *mut Signature, raw: *const libc::c_char,
) -> c_int { ) -> c_int {
if SCDetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 { if SCDetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 {
return -1; return -1;
} }
let ctx = SCDetectU32Parse(raw) as *mut c_void; let ctx = snmp_detect_pdutype_parse(raw) as *mut c_void;
if ctx.is_null() { if ctx.is_null() {
return -1; return -1;
} }
@ -192,7 +211,7 @@ pub(super) unsafe extern "C" fn detect_snmp_register() {
AppLayerTxMatch: Some(snmp_detect_pdutype_match), AppLayerTxMatch: Some(snmp_detect_pdutype_match),
Setup: Some(snmp_detect_pdutype_setup), Setup: Some(snmp_detect_pdutype_setup),
Free: Some(snmp_detect_pdutype_free), Free: Some(snmp_detect_pdutype_free),
flags: SIGMATCH_INFO_UINT32, flags: SIGMATCH_INFO_UINT32 | SIGMATCH_INFO_ENUM_UINT,
}; };
G_SNMP_PDUTYPE_KW_ID = SCDetectHelperKeywordRegister(&kw); G_SNMP_PDUTYPE_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_SNMP_PDUTYPE_BUFFER_ID = SCDetectHelperBufferRegister( G_SNMP_PDUTYPE_BUFFER_ID = SCDetectHelperBufferRegister(

@ -17,25 +17,10 @@
// written by Pierre Chifflier <chifflier@wzdftpd.net> // written by Pierre Chifflier <chifflier@wzdftpd.net>
use crate::detect::EnumString;
use crate::jsonbuilder::{JsonBuilder, JsonError}; use crate::jsonbuilder::{JsonBuilder, JsonError};
use crate::snmp::snmp::SNMPTransaction; use crate::snmp::snmp::{SNMPTransaction, SnmpPduType};
use crate::snmp::snmp_parser::{NetworkAddress, PduType}; use crate::snmp::snmp_parser::NetworkAddress;
use std::borrow::Cow;
fn str_of_pdu_type(t: &PduType) -> Cow<'_, str> {
match t {
&PduType::GetRequest => Cow::Borrowed("get_request"),
&PduType::GetNextRequest => Cow::Borrowed("get_next_request"),
&PduType::Response => Cow::Borrowed("response"),
&PduType::SetRequest => Cow::Borrowed("set_request"),
&PduType::TrapV1 => Cow::Borrowed("trap_v1"),
&PduType::GetBulkRequest => Cow::Borrowed("get_bulk_request"),
&PduType::InformRequest => Cow::Borrowed("inform_request"),
&PduType::TrapV2 => Cow::Borrowed("trap_v2"),
&PduType::Report => Cow::Borrowed("report"),
x => Cow::Owned(format!("Unknown(0x{:x})", x.0)),
}
}
fn snmp_log_response(jsb: &mut JsonBuilder, tx: &SNMPTransaction) -> Result<(), JsonError> { fn snmp_log_response(jsb: &mut JsonBuilder, tx: &SNMPTransaction) -> Result<(), JsonError> {
jsb.open_object("snmp")?; jsb.open_object("snmp")?;
@ -44,7 +29,11 @@ fn snmp_log_response(jsb: &mut JsonBuilder, tx: &SNMPTransaction) -> Result<(),
jsb.set_string("pdu_type", "encrypted")?; jsb.set_string("pdu_type", "encrypted")?;
} else { } else {
if let Some(ref info) = tx.info { if let Some(ref info) = tx.info {
jsb.set_string("pdu_type", &str_of_pdu_type(&info.pdu_type))?; if let Some(pt) = SnmpPduType::from_u(info.pdu_type.0) {
jsb.set_string("pdu_type", pt.to_str())?;
} else {
jsb.set_string("pdu_type", &format!("Unknown(0x{:x})", info.pdu_type.0))?;
}
if info.err.0 != 0 { if info.err.0 != 0 {
jsb.set_string("error", &format!("{:?}", info.err))?; jsb.set_string("error", &format!("{:?}", info.err))?;
} }

@ -69,6 +69,21 @@ pub(super) struct SNMPPduInfo<'a> {
pub vars: Vec<Oid<'a>>, pub vars: Vec<Oid<'a>>,
} }
#[repr(u32)]
#[derive(EnumStringU32)]
#[allow(non_camel_case_types)]
pub enum SnmpPduType {
GET_REQUEST = 0,
GET_NEXT_REQUEST = 1,
RESPONSE = 2,
SET_REQUEST = 3,
TRAP_V1 = 4,
GET_BULK_REQUEST = 5,
INFORM_REQUEST = 6,
TRAP_V2 = 7,
REPORT = 8,
}
pub(super) struct SNMPTransaction<'a> { pub(super) struct SNMPTransaction<'a> {
/// PDU version /// PDU version
pub version: u32, pub version: u32,

Loading…
Cancel
Save