detect/enip: cip_class and cip_instance are now a multi-integer

Ticket: 7929

One commit as they share the same code
pull/15740/head
Philippe Antoine 3 months ago committed by Victor Julien
parent 0bdfe3f571
commit e08a19a88a

@ -86,6 +86,8 @@ It uses a 32-bit unsigned integer as value.
enip.cip_instance uses an :ref:`unsigned 32-bits integer <rules-integer-keywords>`.
enip.cip_instance is also a :ref:`multi-integer <multi-integers>`.
Examples::
enip.cip_instance:1;
@ -99,6 +101,8 @@ It uses a 32-bit unsigned integer as value.
enip.cip_class uses an :ref:`unsigned 32-bits integer <rules-integer-keywords>`.
enip.cip_class is also a :ref:`multi-integer <multi-integers>`.
This allows to match without needing to match on cip.service.
Examples::

@ -26,8 +26,8 @@ use std::os::raw::{c_int, c_void};
use super::constant::{EnipCommand, EnipStatus};
use super::enip::{EnipTransaction, ALPROTO_ENIP};
use super::parser::{
CipData, CipDir, EnipCipRequestPayload, EnipCipResponsePayload, EnipItemPayload, EnipPayload,
CIP_MULTIPLE_SERVICE,
CipData, CipDir, EnipCipPathSegment, EnipCipRequestPayload, EnipCipResponsePayload,
EnipItemPayload, EnipPayload, CIP_MULTIPLE_SERVICE,
};
use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER};
@ -294,18 +294,34 @@ fn enip_get_status(tx: &EnipTransaction, direction: Direction) -> Option<u32> {
return None;
}
macro_rules! get_enip_segment_val {
($segment_type:expr) => {
|seg: &EnipCipPathSegment| {
if seg.segment_type >> 2 == $segment_type {
Some(seg.value)
} else {
None
}
}
};
}
fn enip_cip_match_segment(
d: &CipData, ctx: &DetectUintData<u32>, segment_type: u8,
d: &CipData, ctx: &DetectUintArrayData<u32>, segment_type: u8, done: bool,
) -> std::os::raw::c_int {
if let CipDir::Request(req) = &d.cipdir {
for seg in req.path.iter() {
if seg.segment_type >> 2 == segment_type && detect_match_uint(ctx, seg.value) {
return 1;
}
let r = detect_uint_match_at_index::<EnipCipPathSegment, u32>(
&req.path,
ctx,
get_enip_segment_val!(segment_type),
done,
);
if r == 1 {
return 1;
}
if let EnipCipRequestPayload::Multiple(m) = &req.payload {
for p in m.packet_list.iter() {
if enip_cip_match_segment(p, ctx, segment_type) == 1 {
if enip_cip_match_segment(p, ctx, segment_type, done) == 1 {
return 1;
}
}
@ -315,13 +331,13 @@ fn enip_cip_match_segment(
}
fn enip_tx_has_cip_segment(
tx: &EnipTransaction, ctx: &DetectUintData<u32>, segment_type: u8,
tx: &EnipTransaction, ctx: &DetectUintArrayData<u32>, segment_type: u8,
) -> std::os::raw::c_int {
if let Some(pdu) = &tx.request {
if let EnipPayload::Cip(c) = &pdu.payload {
for item in c.items.iter() {
if let EnipItemPayload::Data(d) = &item.payload {
return enip_cip_match_segment(&d.cip, ctx, segment_type);
return enip_cip_match_segment(&d.cip, ctx, segment_type, tx.done);
}
}
}
@ -329,7 +345,9 @@ fn enip_tx_has_cip_segment(
return 0;
}
fn enip_cip_match_attribute(d: &CipData, ctx: &DetectUintArrayData<u32>, done: bool) -> std::os::raw::c_int {
fn enip_cip_match_attribute(
d: &CipData, ctx: &DetectUintArrayData<u32>, done: bool,
) -> std::os::raw::c_int {
if let CipDir::Request(req) = &d.cipdir {
let mut vals = Vec::new();
for seg in req.path.iter() {
@ -609,7 +627,7 @@ unsafe extern "C" fn cip_class_setup(
if SCDetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 {
return -1;
}
let ctx = SCDetectU32Parse(raw) as *mut c_void;
let ctx = SCDetectU32ArrayParse(raw) as *mut c_void;
if ctx.is_null() {
return -1;
}
@ -633,14 +651,14 @@ unsafe extern "C" fn cip_class_match(
tx: *mut c_void, _sig: *const Signature, ctx: *const SigMatchCtx,
) -> c_int {
let tx = cast_pointer!(tx, EnipTransaction);
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
let ctx = cast_pointer!(ctx, DetectUintArrayData<u32>);
return enip_tx_has_cip_segment(tx, ctx, 8);
}
unsafe extern "C" fn cip_class_free(_de: *mut DetectEngineCtx, ctx: *mut c_void) {
// Just unbox...
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
SCDetectU32Free(ctx);
let ctx = cast_pointer!(ctx, DetectUintArrayData<u32>);
SCDetectU32ArrayFree(ctx);
}
unsafe extern "C" fn vendor_id_setup(
@ -1222,7 +1240,7 @@ unsafe extern "C" fn cip_instance_setup(
if SCDetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 {
return -1;
}
let ctx = SCDetectU32Parse(raw) as *mut c_void;
let ctx = SCDetectU32ArrayParse(raw) as *mut c_void;
if ctx.is_null() {
return -1;
}
@ -1246,14 +1264,14 @@ unsafe extern "C" fn cip_instance_match(
tx: *mut c_void, _sig: *const Signature, ctx: *const SigMatchCtx,
) -> c_int {
let tx = cast_pointer!(tx, EnipTransaction);
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
let ctx = cast_pointer!(ctx, DetectUintArrayData<u32>);
return enip_tx_has_cip_segment(tx, ctx, 9);
}
unsafe extern "C" fn cip_instance_free(_de: *mut DetectEngineCtx, ctx: *mut c_void) {
// Just unbox...
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
SCDetectU32Free(ctx);
let ctx = cast_pointer!(ctx, DetectUintArrayData<u32>);
SCDetectU32ArrayFree(ctx);
}
unsafe extern "C" fn cip_extendedstatus_setup(

Loading…
Cancel
Save