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

@ -17,10 +17,16 @@
// 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::detect::uint::{DetectUintData, SCDetectU32Free, SCDetectU32Match, SCDetectU32Parse};
use crate::detect::{helper_keyword_register_sticky_buffer, SigTableElmtStickyBuffer, SIGMATCH_INFO_UINT32};
use crate::detect::uint::{
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 suricata_sys::sys::{
DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectBufferSetActiveList,
@ -76,13 +82,26 @@ unsafe extern "C" fn snmp_detect_version_free(_de: *mut DetectEngineCtx, ctx: *m
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(
de: *mut DetectEngineCtx, s: *mut Signature, raw: *const libc::c_char,
) -> c_int {
if SCDetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 {
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() {
return -1;
}
@ -192,7 +211,7 @@ pub(super) unsafe extern "C" fn detect_snmp_register() {
AppLayerTxMatch: Some(snmp_detect_pdutype_match),
Setup: Some(snmp_detect_pdutype_setup),
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_BUFFER_ID = SCDetectHelperBufferRegister(

@ -17,25 +17,10 @@
// written by Pierre Chifflier <chifflier@wzdftpd.net>
use crate::detect::EnumString;
use crate::jsonbuilder::{JsonBuilder, JsonError};
use crate::snmp::snmp::SNMPTransaction;
use crate::snmp::snmp_parser::{NetworkAddress, PduType};
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)),
}
}
use crate::snmp::snmp::{SNMPTransaction, SnmpPduType};
use crate::snmp::snmp_parser::NetworkAddress;
fn snmp_log_response(jsb: &mut JsonBuilder, tx: &SNMPTransaction) -> Result<(), JsonError> {
jsb.open_object("snmp")?;
@ -44,7 +29,11 @@ fn snmp_log_response(jsb: &mut JsonBuilder, tx: &SNMPTransaction) -> Result<(),
jsb.set_string("pdu_type", "encrypted")?;
} else {
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 {
jsb.set_string("error", &format!("{:?}", info.err))?;
}

@ -69,6 +69,21 @@ pub(super) struct SNMPPduInfo<'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> {
/// PDU version
pub version: u32,

Loading…
Cancel
Save