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
9 changes: 9 additions & 0 deletions doc/userguide/rules/integer-keywords.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ case-insensitive suffix:
The most direct example is to match for equality, but there are
different modes.

The list of integer keywords can be found by command
``suricata --list-keywords=csv | grep "uint"``

Some other keywords may use unsigned integers as part of their logic:
* iprep
* stream_size
* flow.pkts
* flow.bytes

Comparison modes
----------------

Expand Down
8 changes: 5 additions & 3 deletions doc/userguide/rules/kerberos-keywords.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ krb5_msg_type
This keyword allows to match the Kerberos messages by its type (integer).
It is possible to specify the following values defined in RFC4120:

krb5_msg_type uses :ref:`unsigned 32-bit integer <rules-integer-keywords>`.

* 10 (AS-REQ)
* 11 (AS-REP)
* 12 (TGS-REQ)
Expand All @@ -15,15 +17,15 @@ It is possible to specify the following values defined in RFC4120:

Syntax::

krb5_msg_type:<number>
krb5_msg_type:(mode) <number or string>

Signature examples::

alert krb5 any any -> any any (msg:"Kerberos 5 AS-REQ message"; krb5_msg_type:10; sid:3; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 AS-REP message"; krb5_msg_type:11; sid:4; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 AS-REP message"; krb5_msg_type:AS_REP; sid:4; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 TGS-REQ message"; krb5_msg_type:12; sid:5; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 TGS-REP message"; krb5_msg_type:13; sid:6; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 ERROR message"; krb5_msg_type:30; sid:7; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 not ERROR message"; krb5_msg_type:!30; sid:7; rev:1;)


.. note:: AP-REQ and AP-REP are not currently supported since those messages
Expand Down
30 changes: 25 additions & 5 deletions doc/userguide/rules/multi-buffer-matching.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,36 +74,56 @@ not be met.
Multiple buffer matching is currently enabled for use with the
following keywords:

* ``dns.additionals.rrname``
* ``dns.answer.name``
* ``dns.query.name``
* ``dns.answers.rrname``
* ``dns.authorities.rrname``
* ``dns.queries.rrname``
* ``dns.query``
* ``dns.query.name``
* ``email.received``
* ``email.url``
* ``file.data``
* ``file.magic``
* ``file.name``
* ``ftp.completion_code``
* ``ftp.reply``
* ``http.request_header``
* ``http.response_header``
* ``http2.header_name``
* ``ike.vendor``
* ``krb5_cname``
* ``krb5_sname``
* ``krb5.cname``
* ``krb5.sname``
* ``ldap.request.attribute_type``
* ``ldap.responses.attribute_type``
* ``ldap.responses.dn``
* ``ldap.responses.message``
* ``mdns.additionals.rrname``
* ``mdns.answers.rrname``
* ``mdns.authorities.rrname``
* ``mdns.queries.rrname``
* ``mqtt.subscribe.topic``
* ``mqtt.unsubscribe.topic``
* ``quic.cyu.hash``
* ``quic.cyu.string``
* ``sdp.attribute``
* ``sdp.bandwidth``
* ``sdp.media.connection_data``
* ``sdp.media.encryption_key``
* ``sdp.media.media``
* ``sdp.media.media_info``
* ``sdp.repeat_time``
* ``sdp.time``
* ``sip.content_length``
* ``sip.content_type``
* ``sip.from``
* ``sip.to``
* ``sip.ua``
* ``sip.user_agent``
* ``sip.via``
* ``smtp.rcpt_to``
* ``tls.alpn``
* ``tls.cert_subject``
* ``tls.certs``
* ``tls.subjectaltname``

These can be found by command
``suricata --list-keywords=csv | grep "multi buffer" | cut -d';' -f1``
6 changes: 6 additions & 0 deletions rust/cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ exclude = [
"SRepCatGetByShortname",
"SIGMATCH_NOOPT",
"SIGMATCH_INFO_STICKY_BUFFER",
"SIGMATCH_INFO_MULTI_BUFFER",
"SIGMATCH_INFO_UINT8",
"SIGMATCH_INFO_UINT16",
"SIGMATCH_INFO_UINT32",
"SIGMATCH_INFO_UINT64",
"SIGMATCH_INFO_MULTI_UINT",
"FtpCommand",
]

Expand Down
30 changes: 24 additions & 6 deletions rust/src/detect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub struct SigTableElmtStickyBuffer {
) -> c_int,
}

pub fn helper_keyword_register_sticky_buffer(kw: &SigTableElmtStickyBuffer) -> u16 {
fn helper_keyword_register_buffer_flags(kw: &SigTableElmtStickyBuffer, flags: u32) -> u16 {
let name = CString::new(kw.name.as_bytes()).unwrap().into_raw();
let desc = CString::new(kw.desc.as_bytes()).unwrap().into_raw();
let url = CString::new(kw.url.as_bytes()).unwrap().into_raw();
Expand All @@ -83,7 +83,7 @@ pub fn helper_keyword_register_sticky_buffer(kw: &SigTableElmtStickyBuffer) -> u
desc,
url,
Setup: Some(kw.setup),
flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
flags,
AppLayerTxMatch: None,
Free: None,
};
Expand All @@ -94,6 +94,17 @@ pub fn helper_keyword_register_sticky_buffer(kw: &SigTableElmtStickyBuffer) -> u
}
}

pub fn helper_keyword_register_multi_buffer(kw: &SigTableElmtStickyBuffer) -> u16 {
return helper_keyword_register_buffer_flags(
kw,
SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER | SIGMATCH_INFO_MULTI_BUFFER,
);
}

pub fn helper_keyword_register_sticky_buffer(kw: &SigTableElmtStickyBuffer) -> u16 {
return helper_keyword_register_buffer_flags(kw, SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER);
}

#[repr(C)]
#[allow(non_snake_case)]
/// Names of SigTableElmt for release by rust
Expand All @@ -114,10 +125,17 @@ pub unsafe extern "C" fn SCDetectSigMatchNamesFree(kw: &mut SCSigTableNamesElmt)
}

// TODO bindgen these
pub const SIGMATCH_NOOPT: u16 = 1; // BIT_U16(0) in detect.h
pub(crate) const SIGMATCH_OPTIONAL_OPT: u16 = 0x10; // BIT_U16(4) in detect.h
pub(crate) const SIGMATCH_QUOTES_MANDATORY: u16 = 0x40; // BIT_U16(6) in detect.h
pub const SIGMATCH_INFO_STICKY_BUFFER: u16 = 0x200; // BIT_U16(9)
pub const SIGMATCH_NOOPT: u32 = 1; // BIT_U16(0) in detect.h
pub(crate) const SIGMATCH_OPTIONAL_OPT: u32 = 0x10; // BIT_U16(4) in detect.h
pub(crate) const SIGMATCH_QUOTES_MANDATORY: u32 = 0x40; // BIT_U16(6) in detect.h
pub const SIGMATCH_INFO_STICKY_BUFFER: u32 = 0x200; // BIT_U16(9)
pub const SIGMATCH_INFO_MULTI_BUFFER: u32 = 0x4000; // BIT_U16(14)
pub const SIGMATCH_INFO_UINT8: u32 = 0x8000; // BIT_U32(15)
pub const SIGMATCH_INFO_UINT16: u32 = 0x10000; // BIT_U32(16)
pub const SIGMATCH_INFO_UINT32: u32 = 0x20000; // BIT_U32(17)
pub const SIGMATCH_INFO_UINT64: u32 = 0x40000; // BIT_U32(18)
pub const SIGMATCH_INFO_MULTI_UINT: u32 = 0x80000; // BIT_U32(19)


#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down
89 changes: 88 additions & 1 deletion rust/src/detect/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use nom7::IResult;

use super::EnumString;

use std::ffi::CStr;
use std::ffi::{CStr, c_int};
use std::str::FromStr;

#[derive(PartialEq, Eq, Clone, Debug)]
#[repr(u8)]
Expand All @@ -50,6 +51,92 @@ pub struct DetectUintData<T> {
pub mode: DetectUintMode,
}

#[derive(Debug, PartialEq)]
pub(crate) enum DetectUintIndex {
Any,
All,
Index(i32),
}

#[derive(Debug, PartialEq)]
pub(crate) struct DetectUintArrayData<T> {
pub du: DetectUintData<T>,
pub index: DetectUintIndex,
}

fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
let index = if parts.len() == 2 {
match parts[1] {
"all" => DetectUintIndex::All,
"any" => DetectUintIndex::Any,
_ => {
let i32_index = i32::from_str(parts[1]).ok()?;
DetectUintIndex::Index(i32_index)
}
}
} else {
DetectUintIndex::Any
};
return Some(index);
}

pub(crate) fn detect_parse_array_uint_enum<T1: DetectIntType, T2: EnumString<T1>>(
s: &str,
) -> Option<DetectUintArrayData<T1>> {
let parts: Vec<&str> = s.split(',').collect();
if parts.len() > 2 {
return None;
}

let index = parse_uint_index(&parts)?;
let du = detect_parse_uint_enum::<T1, T2>(parts[0])?;

Some(DetectUintArrayData { du, index })
}

pub(crate) fn detect_uint_match_at_index<T, U>(
array: &Vec<T>, ctx: &DetectUintArrayData<U>, get_value: impl Fn(&T) -> Option<U>,
detect_match: impl Fn(U, &DetectUintData<U>) -> c_int,
) -> c_int {
match ctx.index {
DetectUintIndex::Any => {
for response in array {
if let Some(code) = get_value(response) {
if detect_match(code, &ctx.du) == 1 {
return 1;
}
}
}
return 0;
}
DetectUintIndex::All => {
for response in array {
if let Some(code) = get_value(response) {
if detect_match(code, &ctx.du) == 0 {
return 0;
}
}
}
return 1;
}
DetectUintIndex::Index(idx) => {
let index = if idx < 0 {
// negative values for backward indexing.
((array.len() as i32) + idx) as usize
} else {
idx as usize
};
if array.len() <= index {
return 0;
}
if let Some(code) = get_value(&array[index]) {
return detect_match(code, &ctx.du);
}
return 0;
}
}
}

/// Parses a string for detection with integers, using enumeration strings
///
/// Needs to specify T1 the integer type (like u8)
Expand Down
7 changes: 4 additions & 3 deletions rust/src/dhcp/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use super::dhcp::{
use super::parser::DHCPOptionWrapper;
use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER};
use crate::detect::uint::{DetectUintData, SCDetectU64Free, SCDetectU64Match, SCDetectU64Parse};
use crate::detect::SIGMATCH_INFO_UINT64;
use std::os::raw::{c_int, c_void};
use suricata_sys::sys::{
DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectHelperBufferRegister,
Expand Down Expand Up @@ -173,7 +174,7 @@ pub unsafe extern "C" fn SCDetectDHCPRegister() {
AppLayerTxMatch: Some(dhcp_detect_leasetime_match),
Setup: Some(dhcp_detect_leasetime_setup),
Free: Some(dhcp_detect_time_free),
flags: 0,
flags: SIGMATCH_INFO_UINT64,
};
G_DHCP_LEASE_TIME_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_DHCP_LEASE_TIME_BUFFER_ID = SCDetectHelperBufferRegister(
Expand All @@ -188,7 +189,7 @@ pub unsafe extern "C" fn SCDetectDHCPRegister() {
AppLayerTxMatch: Some(dhcp_detect_rebindingtime_match),
Setup: Some(dhcp_detect_rebindingtime_setup),
Free: Some(dhcp_detect_time_free),
flags: 0,
flags: SIGMATCH_INFO_UINT64,
};
G_DHCP_REBINDING_TIME_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_DHCP_REBINDING_TIME_BUFFER_ID = SCDetectHelperBufferRegister(
Expand All @@ -203,7 +204,7 @@ pub unsafe extern "C" fn SCDetectDHCPRegister() {
AppLayerTxMatch: Some(dhcp_detect_renewaltime_match),
Setup: Some(dhcp_detect_renewaltime_setup),
Free: Some(dhcp_detect_time_free),
flags: 0,
flags: SIGMATCH_INFO_UINT64,
};
G_DHCP_RENEWAL_TIME_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_DHCP_RENEWAL_TIME_BUFFER_ID = SCDetectHelperBufferRegister(
Expand Down
Loading
Loading