Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3067,6 +3067,7 @@ jobs:
env:
DISTCHECK_CONFIGURE_FLAGS: "--enable-unittests --enable-debug --enable-geoip --enable-profiling --enable-profiling-locks --enable-dpdk --enable-ebpf --enable-ebpf-build"
- run: python3 scripts/check-dist-rules.py
- run: python3 scripts/check-uint-keywords.py
- run: test -e doc/userguide/suricata.1
- run: test -e doc/userguide/userguide.pdf
- name: Building Rust documentation
Expand Down
6 changes: 6 additions & 0 deletions doc/userguide/rules/enip-keyword.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ This allows to match without needing to match on cip.service.

enip.cip_attribute uses an :ref:`unsigned 32-bits integer <rules-integer-keywords>`.

enip.cip_attribute is also a :ref:`multi-integer <multi-integers>`.

Examples::

enip.cip_attribute:1;
Expand All @@ -84,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;
Expand All @@ -97,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::
Expand Down
103 changes: 68 additions & 35 deletions rust/src/enip/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ 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};
use crate::detect::uint::{
detect_match_uint, detect_parse_uint_enum, DetectUintData, SCDetectU16Free, SCDetectU16Match,
SCDetectU16Parse, SCDetectU32Free, SCDetectU32Match, SCDetectU32Parse, SCDetectU8Free,
SCDetectU8Match, SCDetectU8Parse,
detect_match_uint, detect_parse_uint_enum, detect_uint_match_at_index, DetectUintArrayData,
DetectUintData, DetectUintIndex, SCDetectU16Free, SCDetectU16Match, SCDetectU16Parse,
SCDetectU32ArrayFree, SCDetectU32ArrayParse, SCDetectU32Free, SCDetectU32Match,
SCDetectU32Parse, SCDetectU8Free, SCDetectU8Match, SCDetectU8Parse,
};
use crate::detect::{
helper_keyword_register_sticky_buffer, SigTableElmtStickyBuffer, SIGMATCH_INFO_ENUM_UINT,
Expand Down Expand Up @@ -293,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;
}
}
Expand All @@ -314,63 +331,79 @@ 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);
}
}
}
}
return 0;
}

fn enip_cip_match_attribute(d: &CipData, ctx: &DetectUintData<u32>) -> 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() {
if seg.segment_type >> 2 == 12 && detect_match_uint(ctx, seg.value) {
return 1;
if seg.segment_type >> 2 == 12 {
if ctx.index != DetectUintIndex::Any {
vals.push(seg.value);
} else if detect_match_uint(&ctx.du, seg.value) {
return 1;
}
}
}
match &req.payload {
EnipCipRequestPayload::GetAttributeList(ga) => {
for attrg in ga.attr_list.iter() {
if detect_match_uint(ctx, (*attrg).into()) {
if ctx.index != DetectUintIndex::Any {
vals.push((*attrg).into());
} else if detect_match_uint(&ctx.du, (*attrg).into()) {
return 1;
}
}
}
EnipCipRequestPayload::SetAttributeList(sa) => {
if let Some(val) = sa.first_attr {
if detect_match_uint(ctx, val.into()) {
if ctx.index != DetectUintIndex::Any {
vals.push(val.into());
} else if detect_match_uint(&ctx.du, val.into()) {
return 1;
}
}
}
EnipCipRequestPayload::Multiple(m) => {
for p in m.packet_list.iter() {
if enip_cip_match_attribute(p, ctx) == 1 {
// treat each array independently
if enip_cip_match_attribute(p, ctx, done) == 1 {
return 1;
}
}
}
_ => {}
}
if ctx.index != DetectUintIndex::Any {
return detect_uint_match_at_index::<u32, u32>(&vals, ctx, |v| Some(*v), done);
}
}
return 0;
}

fn enip_tx_has_cip_attribute(
tx: &EnipTransaction, ctx: &DetectUintData<u32>,
tx: &EnipTransaction, ctx: &DetectUintArrayData<u32>,
) -> 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_attribute(&d.cip, ctx);
// there should be only one EnipItemPayload item
return enip_cip_match_attribute(&d.cip, ctx, tx.done);
}
}
}
Expand Down Expand Up @@ -554,7 +587,7 @@ unsafe extern "C" fn cip_attribute_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;
}
Expand All @@ -578,14 +611,14 @@ unsafe extern "C" fn cip_attribute_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_attribute(tx, ctx);
}

unsafe extern "C" fn cip_attribute_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_class_setup(
Expand All @@ -594,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;
}
Expand All @@ -618,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(
Expand Down Expand Up @@ -1207,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;
}
Expand All @@ -1231,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(
Expand Down Expand Up @@ -1579,7 +1612,7 @@ pub unsafe extern "C" fn SCDetectEnipRegister() {
AppLayerTxMatch: Some(cip_status_match),
Setup: Some(cip_status_setup),
Free: Some(cip_status_free),
flags: SIGMATCH_INFO_UINT8 | SIGMATCH_INFO_MULTI_UINT,
flags: SIGMATCH_INFO_UINT8,
};
G_ENIP_CIP_STATUS_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_ENIP_CIP_STATUS_BUFFER_ID = SCDetectHelperBufferProgressRegister(
Expand Down Expand Up @@ -1612,7 +1645,7 @@ pub unsafe extern "C" fn SCDetectEnipRegister() {
AppLayerTxMatch: Some(cip_extendedstatus_match),
Setup: Some(cip_extendedstatus_setup),
Free: Some(cip_extendedstatus_free),
flags: SIGMATCH_INFO_UINT16 | SIGMATCH_INFO_MULTI_UINT,
flags: SIGMATCH_INFO_UINT16,
};
G_ENIP_CIP_EXTENDEDSTATUS_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_ENIP_CIP_EXTENDEDSTATUS_BUFFER_ID = SCDetectHelperBufferProgressRegister(
Expand Down
4 changes: 2 additions & 2 deletions rust/src/krb/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::detect::uint::{
};
use crate::detect::{
helper_keyword_register_multi_buffer, SigTableElmtStickyBuffer, SIGMATCH_INFO_ENUM_UINT,
SIGMATCH_INFO_MULTI_UINT, SIGMATCH_INFO_UINT32,
SIGMATCH_INFO_UINT32,
};
use kerberos_parser::krb5::EncryptionType;

Expand Down Expand Up @@ -537,7 +537,7 @@ pub unsafe extern "C" fn SCDetectKrb5Register() {
AppLayerTxMatch: Some(krb5_msg_type_match),
Setup: Some(krb5_msg_type_setup),
Free: Some(krb5_msg_type_free),
flags: SIGMATCH_INFO_MULTI_UINT | SIGMATCH_INFO_ENUM_UINT | SIGMATCH_INFO_UINT32,
flags: SIGMATCH_INFO_ENUM_UINT | SIGMATCH_INFO_UINT32,
};
G_KRB5_MSG_TYPE_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_KRB5_GENERIC_BUFFER_ID = SCDetectHelperBufferProgressRegister(
Expand Down
4 changes: 2 additions & 2 deletions rust/src/mqtt/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,7 @@ pub unsafe extern "C" fn SCDetectMqttRegister() {
AppLayerTxMatch: Some(mqtt_flags_match),
Setup: Some(mqtt_flags_setup),
Free: Some(mqtt_flags_free),
flags: SIGMATCH_INFO_UINT8 | SIGMATCH_INFO_MULTI_UINT | SIGMATCH_INFO_BITFLAGS_UINT,
flags: SIGMATCH_INFO_UINT8 | SIGMATCH_INFO_BITFLAGS_UINT,
};
G_MQTT_FLAGS_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_MQTT_FLAGS_BUFFER_ID = SCDetectHelperBufferProgressRegister(
Expand All @@ -1089,7 +1089,7 @@ pub unsafe extern "C" fn SCDetectMqttRegister() {
AppLayerTxMatch: Some(mqtt_conn_flags_match),
Setup: Some(mqtt_conn_flags_setup),
Free: Some(mqtt_conn_flags_free),
flags: SIGMATCH_INFO_UINT8 | SIGMATCH_INFO_MULTI_UINT | SIGMATCH_INFO_BITFLAGS_UINT,
flags: SIGMATCH_INFO_UINT8 | SIGMATCH_INFO_BITFLAGS_UINT,
};
G_MQTT_CONN_FLAGS_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_MQTT_CONN_FLAGS_BUFFER_ID = SCDetectHelperBufferProgressRegister(
Expand Down
4 changes: 2 additions & 2 deletions rust/src/nfs/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::core::STREAM_TOSERVER;
use crate::detect::uint::{
detect_match_uint, detect_parse_uint_enum, detect_parse_uint_inclusive, DetectUintData,
};
use crate::detect::{SIGMATCH_INFO_ENUM_UINT, SIGMATCH_INFO_MULTI_UINT, SIGMATCH_INFO_UINT32};
use crate::detect::{SIGMATCH_INFO_ENUM_UINT, SIGMATCH_INFO_UINT32};

use std::ffi::{c_int, CStr};
use std::os::raw::c_void;
Expand Down Expand Up @@ -168,7 +168,7 @@ pub unsafe extern "C" fn SCDetectNfsProcedureRegister() {
AppLayerTxMatch: Some(nfs_procedure_match),
Setup: Some(nfs_procedure_setup),
Free: Some(nfs_procedure_free),
flags: SIGMATCH_INFO_UINT32 | SIGMATCH_INFO_MULTI_UINT | SIGMATCH_INFO_ENUM_UINT,
flags: SIGMATCH_INFO_UINT32 | SIGMATCH_INFO_ENUM_UINT,
};
G_NFS_PROCEDURE_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_NFS_PROCEDURE_BUFFER_ID = SCDetectHelperBufferProgressRegister(
Expand Down
Loading
Loading