diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index dc8b7cb25e9b..ac51b07dcd51 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -1246,6 +1246,62 @@ jobs: else exit 0 fi + almalinux-9-minimal-recommended-dependecies: + name: AlmaLinux 9 (Minimal/Recommended Build) + runs-on: ubuntu-latest + container: almalinux:9 + needs: [prepare-deps] + steps: + # Cache Rust stuff. + - name: Cache cargo registry + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 + with: + path: ~/.cargo + key: ${{ github.job }}-cargo + + - name: Cache RPMs + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 + with: + path: /var/cache/dnf + key: ${{ github.job }}-dnf + - run: echo "keepcache=1" >> /etc/dnf/dnf.conf + + - name: Determine number of CPUs + run: echo CPUS=$(nproc --all) >> $GITHUB_ENV + + - name: Install git dependencies + run: | + dnf -y install \ + sudo \ + git \ + libtool \ + which + + - name: Install Almalinux 9 extra repositories + run : | + dnf -y update + dnf -y install dnf-plugins-core epel-release + dnf config-manager --set-enabled crb + + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - run: git config --global --add safe.directory /__w/suricata/suricata + - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 + + - name: Install minimal dependencies + run: ./scripts/docs-almalinux9-minimal-build.sh + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - run: git config --global --add safe.directory /__w/suricata/suricata + - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + name: prep + path: prep + - run: tar xf prep/libhtp.tar.gz + - run: ./autogen.sh + - run: CFLAGS="${DEFAULT_CFLAGS}" ./configure + - run: make -j ${{ env.CPUS }} + - run: ./src/suricata --build-info # check if we can run Suricata ubuntu-24-04: name: Ubuntu 24.04 (cocci) @@ -2420,6 +2476,46 @@ jobs: - run: make -j ${{ env.CPUS }} - run: ./src/suricata --build-info | grep -E "Netmap support:\s+yes" + ubuntu-22-04-minimal-recommended-build: + name: Ubuntu 22.04 (Minimal/Recommended Build) + needs: [prepare-deps, prepare-cbindgen] + runs-on: ubuntu-22.04 + steps: + # Cache Rust stuff. + - name: Cache cargo registry + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 + with: + path: ~/.cargo/registry + key: cargo-registry + + - name: Determine number of CPUs + run: echo CPUS=$(nproc --all) >> $GITHUB_ENV + + - name: Install git dependencies + run: | + sudo apt update + sudo apt -y install \ + git \ + libtool + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - run: git config --global --add safe.directory /__w/suricata/suricata + - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 + with: + name: prep + path: prep + - run: tar xf prep/libhtp.tar.gz + - run: tar xf prep/suricata-update.tar.gz + - run: tar xf prep/suricata-verify.tar.gz + - run: ./autogen.sh + + - name: Install minimal dependencies + run: ./scripts/docs-ubuntu-debian-minimal-build.sh + + - run: CFLAGS="${DEFAULT_CFLAGS}" ./configure + - run: make -j ${{ env.CPUS }} + - run: ./src/suricata --build-info # check if we can run Suricata + ubuntu-22-04-dpdk-build: name: Ubuntu 22.04 (DPDK Build) runs-on: ubuntu-22.04 @@ -2819,7 +2915,6 @@ jobs: ccache \ curl \ git \ - gosu \ jq \ libpcre2-dev \ libpcap-dev \ @@ -2901,7 +2996,6 @@ jobs: ccache \ curl \ git \ - gosu \ jq \ libpcre2-dev \ libpcap-dev \ diff --git a/Makefile.am b/Makefile.am index b60180de2aa1..9b09ab007d19 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,8 @@ EXTRA_DIST = ChangeLog COPYING LICENSE suricata.yaml.in \ lua \ acsite.m4 \ scripts/generate-images.sh \ + scripts/docs-almalinux9-minimal-build.sh \ + scripts/docs-ubuntu-debian-minimal-build.sh \ examples/plugins SUBDIRS = $(HTP_DIR) rust src qa rules doc contrib etc python ebpf \ $(SURICATA_UPDATE_DIR) diff --git a/configure.ac b/configure.ac index 19bb8ffc2092..7a8be3b6faea 100644 --- a/configure.ac +++ b/configure.ac @@ -318,6 +318,17 @@ CFLAGS="$CFLAGS -std=gnu99" fi + # check if our target supports -Wl,--start-group + AC_MSG_CHECKING(for -Wl,--start-group support) + OLDFLAGS=$LDFLAGS + LDFLAGS="-Wl,--start-group,--end-group" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[ + have_linker_group_support=yes + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)]) + LDFLAGS=$OLDFLAGS + AM_CONDITIONAL([LINKER_SUPPORTS_GROUP], [test "x$have_linker_group_support" = "xyes"]) + # check if our target supports thread local storage AC_MSG_CHECKING(for thread local storage gnu __thread support) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], diff --git a/doc/userguide/capture-hardware/ebpf-xdp.rst b/doc/userguide/capture-hardware/ebpf-xdp.rst index 116038716eff..d9e3b2eeb04d 100644 --- a/doc/userguide/capture-hardware/ebpf-xdp.rst +++ b/doc/userguide/capture-hardware/ebpf-xdp.rst @@ -80,16 +80,15 @@ Make sure you have ``clang`` (>=3.9) installed on the system :: sudo apt install clang -Some i386 headers will also be needed as eBPF is not x86_64 and some included headers -are architecture specific :: - - sudo apt install libc6-dev-i386 --no-install-recommends - libbpf ~~~~~~ Suricata uses libbpf to interact with eBPF and XDP :: + sudo apt install libbpf-dev + +If the libbpf package is unavailable, it can be cloned from the repository :: + git clone https://github.com/libbpf/libbpf.git Now, you can build and install the library :: @@ -109,7 +108,7 @@ Compile and install Suricata To get Suricata source, you can use the usual :: git clone https://github.com/OISF/suricata.git - cd suricata && git clone https://github.com/OISF/libhtp.git -b 0.5.x + cd suricata && ./scripts/bundle.sh ./autogen.sh diff --git a/doc/userguide/install.rst b/doc/userguide/install.rst index cf9c6c03fed8..5e1e01050bd2 100644 --- a/doc/userguide/install.rst +++ b/doc/userguide/install.rst @@ -64,61 +64,19 @@ Common configure options Enables `DPDK `_ packet capture method. -Dependencies -^^^^^^^^^^^^ - -For Suricata's compilation you'll need the following libraries and their development headers installed:: - - libjansson, libpcap, libpcre2, libyaml, zlib - -The following tools are required:: - - make gcc (or clang) pkg-config rustc cargo - -Rust support:: - - rustc, cargo - - Some distros don't provide or provide outdated Rust packages. - Rust can also be installed directly from the Rust project itself:: - - 1) Install Rust https://www.rust-lang.org/en-US/install.html - 2) Install cbindgen - if the cbindgen is not found in the repository - or the cbindgen version is lower than required, it can be - alternatively installed as: cargo install --force cbindgen - 3) Make sure the cargo path is within your PATH environment - e.g. echo 'export PATH=”${PATH}:~/.cargo/bin”' >> ~/.bashrc - e.g. export PATH="${PATH}:/root/.cargo/bin" +Dependencies and compilation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Ubuntu/Debian """"""""""""" .. note:: The following instructions require ``sudo`` to be installed. -Minimal:: - - # Installed Rust and cargo as indicated above - sudo apt-get install build-essential git libjansson-dev libpcap-dev \ - libpcre2-dev libtool libyaml-dev make pkg-config zlib1g-dev - # On most distros installing cbindgen with package manager should be enough - sudo apt-get install cbindgen # alternative: cargo install --force cbindgen - -Recommended:: - - # Installed Rust and cargo as indicated above - sudo apt-get install autoconf automake build-essential ccache clang curl git \ - gosu jq libbpf-dev libcap-ng0 libcap-ng-dev libelf-dev \ - libevent-dev libgeoip-dev libhiredis-dev libjansson-dev \ - libmagic-dev libnet1-dev libpcap-dev libpcre2-dev libtool \ - libyaml-0-2 libyaml-dev m4 make pkg-config python3 \ - python3-dev python3-yaml sudo zlib1g zlib1g-dev - cargo install --force cbindgen - -Extra for iptables/nftables IPS integration:: - - sudo apt-get install libnetfilter-queue-dev libnetfilter-queue1 \ - libnetfilter-log-dev libnetfilter-log1 \ - libnfnetlink-dev libnfnetlink0 +.. literalinclude:: ../../scripts/docs-ubuntu-debian-minimal-build.sh + :caption: Minimal dependencies for Ubuntu/Debian + :language: bash + :start-after: # install-guide-documentation tag start: Minimal dependencies + :end-before: # install-guide-documentation tag end: Minimal dependencies CentOS, AlmaLinux, RockyLinux, Fedora, etc """""""""""""""""""""""""""""""""""""""""" @@ -130,46 +88,50 @@ repository in most distros. You can enable it possibly by one of the following ways:: sudo dnf -y update - sudo dnf -y install dnf-plugins-core - # AlmaLinux 8 + sudo dnf -y install epel-release dnf-plugins-core + # AlmaLinux 8 / RockyLinux 8 sudo dnf config-manager --set-enabled powertools - # AlmaLinux 9 + # AlmaLinux 9 / RockyLinux 9 sudo dnf config-manager --set-enable crb # Oracle Linux 8 sudo dnf config-manager --set-enable ol8_codeready_builder # Oracle Linux 9 sudo dnf config-manager --set-enable ol9_codeready_builder -Minimal:: - - # Installed Rust and cargo as indicated above - sudo dnf install -y gcc gcc-c++ git jansson-devel libpcap-devel libtool \ - libyaml-devel make pcre2-devel which zlib-devel - cargo install --force cbindgen - -Recommended:: - - # Installed Rust and cargo as indicated above - sudo dnf install -y autoconf automake diffutils file-devel gcc gcc-c++ git \ - jansson-devel jq libcap-ng-devel libevent-devel \ - libmaxminddb-devel libnet-devel libnetfilter_queue-devel \ - libnfnetlink-devel libpcap-devel libtool libyaml-devel \ - lua-devel lz4-devel make pcre2-devel pkgconfig \ - python3-devel python3-sphinx python3-yaml sudo which \ - zlib-devel - cargo install --force cbindgen +.. literalinclude:: ../../scripts/docs-almalinux9-minimal-build.sh + :caption: Minimal dependencies for RPM-based distributions + :language: bash + :start-after: # install-guide-documentation tag start: Minimal RPM-based dependencies + :end-before: # install-guide-documentation tag end: Minimal RPM-based dependencies Compilation -^^^^^^^^^^^ +""""""""""" Follow these steps from your Suricata directory:: - ./scripts/bundle.sh - ./autogen.sh ./configure # you may want to add additional parameters here # ./configure --help to get all available parameters - make -j8 # j is for paralleling, you may de/increase depending on your CPU + # j is for adding concurrency to make; the number indicates how much + # concurrency so choose a number that is suitable for your build system + make -j8 make install # to install your Suricata compiled binary + # make install-full - installs configuration and rulesets as well + +Rust support +"""""""""""" + + Rust packages can be found in package managers but some distributions + don't provide Rust or provide outdated Rust packages. + In case of insufficient version you can install Rust directly + from the Rust project itself:: + + 1) Install Rust https://www.rust-lang.org/en-US/install.html + 2) Install cbindgen - if the cbindgen is not found in the repository + or the cbindgen version is lower than required, it can be + alternatively installed as: cargo install --force cbindgen + 3) Make sure the cargo path is within your PATH environment + echo 'export PATH="~/.cargo/bin:${PATH}"' >> ~/.bashrc + export PATH="~/.cargo/bin:${PATH}" Auto-Setup ^^^^^^^^^^ diff --git a/doc/userguide/rules/ip-reputation-rules.rst b/doc/userguide/rules/ip-reputation-rules.rst index 730a4f11a92d..dd520b4e3fea 100644 --- a/doc/userguide/rules/ip-reputation-rules.rst +++ b/doc/userguide/rules/ip-reputation-rules.rst @@ -17,20 +17,49 @@ The iprep directive matches on the IP reputation information for a host. side to check: -category: the category short name +``category``: the category short name -operator: <, >, = +``operator``: <, <=, >, >=, = -reputation score: 0-127 +``reputation score``: 0-127 Example: :: - alert ip $HOME_NET any -> any any (msg:"IPREP internal host talking to CnC server"; flow:to_server; iprep:dst,CnC,>,30; sid:1; rev:1;) -This rule will alert when a system in $HOME_NET acts as a client while communicating with any IP in the CnC category that has a reputation score set to greater than 30. +This rule will alert when a system in ``$HOME_NET`` acts as a client while communicating with any IP in the CnC category that has a reputation score set to greater than 30. + +isset and isnotset +~~~~~~~~~~~~~~~~~~ + +``isset`` and ``isnotset`` can be used to test reputation "membership" + +:: + + iprep:,, + + +``side to check``: + +``category``: the category short name + +To test whether an IP is part of an iprep set at all, the ``isset`` can be used. It acts as a ``>=,0`` statement. + +.. container:: example-rule + + drop ip $HOME_NET any -> any any (:example-rule-options:`iprep:src,known-bad-hosts,isset;` sid:1;) + +In this example traffic to any IP with a score in ``known-bad-hosts`` would be blocked. + +``isnotset`` can be used to test if an IP is not a part of the set. + +.. container:: example-rule + + drop ip $HOME_NET any -> any any (:example-rule-options:`iprep:src,trusted-hosts,isnotset;` sid:1;) + +In this example traffic for a host w/o a trust score would be blocked. Compatibility with IP-only ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/userguide/rules/snmp-keywords.rst b/doc/userguide/rules/snmp-keywords.rst index a5349c2e5056..8429f0d805d7 100644 --- a/doc/userguide/rules/snmp-keywords.rst +++ b/doc/userguide/rules/snmp-keywords.rst @@ -6,6 +6,8 @@ snmp.version SNMP protocol version (integer). Expected values are 1, 2 (for version 2c) or 3. +snmp.version uses an, :ref:` unsigned 32-bits integer `. + Syntax:: snmp.version:[op] @@ -69,6 +71,8 @@ snmp.pdu_type SNMP PDU type (integer). +snmp.pdu_type uses an, :ref:` unsigned 32-bits integer `. + Common values are: - 0: GetRequest diff --git a/examples/lib/simple/Makefile.am b/examples/lib/simple/Makefile.am index afc6505c3bae..c4004b9446c9 100644 --- a/examples/lib/simple/Makefile.am +++ b/examples/lib/simple/Makefile.am @@ -5,7 +5,7 @@ simple_SOURCES = main.c AM_CPPFLAGS = -I$(top_srcdir)/src simple_LDFLAGS = $(all_libraries) $(SECLDFLAGS) -simple_LDADD = $(top_builddir)/src/libsuricata_c.a ../../$(RUST_SURICATA_LIB) $(RUST_LDADD) +simple_LDADD = "-Wl,--start-group,$(top_builddir)/src/libsuricata_c.a,../../$(RUST_SURICATA_LIB),--end-group" $(RUST_LDADD) if HTP_LDADD simple_LDADD += ../../$(HTP_LDADD) endif diff --git a/rust/Cargo.toml.in b/rust/Cargo.toml.in index bb1553b5cac3..f750765d13c3 100644 --- a/rust/Cargo.toml.in +++ b/rust/Cargo.toml.in @@ -41,8 +41,8 @@ hkdf = "~0.12.3" aes = "~0.7.5" aes-gcm = "~0.9.4" -der-parser = { version = "~9.0.0", default_features = false } -kerberos-parser = { version = "~0.8.0", default_features = false } +der-parser = { version = "~9.0.0", default-features = false } +kerberos-parser = { version = "~0.8.0", default-features = false } sawp-modbus = "~0.12.1" sawp = "~0.12.1" diff --git a/rust/cbindgen.toml b/rust/cbindgen.toml index 3240f4661ef1..b277e00506d8 100644 --- a/rust/cbindgen.toml +++ b/rust/cbindgen.toml @@ -82,6 +82,7 @@ include = [ "QuicState", "QuicTransaction", "FtpEvent", + "SCSigTableElmt", ] # A list of items to not include in the generated bindings diff --git a/rust/src/asn1/parse_rules.rs b/rust/src/asn1/parse_rules.rs index 540734c72fa5..9a857868db98 100644 --- a/rust/src/asn1/parse_rules.rs +++ b/rust/src/asn1/parse_rules.rs @@ -153,7 +153,7 @@ pub(super) fn asn1_parse_rule(input: &str) -> IResult<&str, DetectAsn1Data> { tag("relative_offset"), multispace1, verify(parse_i32_number, |v| { - *v >= -i32::from(std::u16::MAX) && *v <= i32::from(std::u16::MAX) + *v >= -i32::from(u16::MAX) && *v <= i32::from(u16::MAX) }), )(i) } diff --git a/rust/src/detect/error.rs b/rust/src/detect/error.rs index 4959e2c883a4..211c5afceb33 100644 --- a/rust/src/detect/error.rs +++ b/rust/src/detect/error.rs @@ -23,6 +23,7 @@ use nom7::error::{ErrorKind, ParseError}; #[derive(Debug, PartialEq, Eq)] pub enum RuleParseError { InvalidByteMath(String), + InvalidIPRep(String), Nom(I, ErrorKind), } diff --git a/rust/src/detect/iprep.rs b/rust/src/detect/iprep.rs index 16f5d9d5d15e..f4082683c384 100644 --- a/rust/src/detect/iprep.rs +++ b/rust/src/detect/iprep.rs @@ -16,10 +16,11 @@ */ use super::uint::*; -use nom7::bytes::complete::{is_a, take_while}; -use nom7::character::complete::{alpha0, char, digit1}; -use nom7::combinator::{all_consuming, map_opt, map_res, opt}; -use nom7::error::{make_error, ErrorKind}; +use crate::detect::error::RuleParseError; +use nom7::bytes::complete::tag; +use nom7::character::complete::multispace0; +use nom7::sequence::preceded; + use nom7::Err; use nom7::IResult; @@ -53,12 +54,17 @@ impl std::str::FromStr for DetectIPRepDataCmd { } } +/// value matching is done use `DetectUintData` logic. +/// isset matching is done using special `DetectUintData` value ">= 0" +/// isnotset matching bypasses `DetectUintData` and is handled directly +/// in the match function (in C). #[derive(Debug)] #[repr(C)] pub struct DetectIPRepData { pub du8: DetectUintData, pub cat: u8, pub cmd: DetectIPRepDataCmd, + pub isnotset: bool, // if true, ignores `du8` } pub fn is_alphanumeric_or_slash(chr: char) -> bool { @@ -75,40 +81,73 @@ extern "C" { pub fn SRepCatGetByShortname(name: *const c_char) -> u8; } -pub fn detect_parse_iprep(i: &str) -> IResult<&str, DetectIPRepData> { - let (i, _) = opt(is_a(" "))(i)?; - let (i, cmd) = map_res(alpha0, DetectIPRepDataCmd::from_str)(i)?; - let (i, _) = opt(is_a(" "))(i)?; - let (i, _) = char(',')(i)?; - let (i, _) = opt(is_a(" "))(i)?; - - let (i, name) = take_while(is_alphanumeric_or_slash)(i)?; - // copy as to have final zero - let namez = CString::new(name).unwrap(); - let cat = unsafe { SRepCatGetByShortname(namez.as_ptr()) }; - if cat == 0 { - return Err(Err::Error(make_error(i, ErrorKind::MapOpt))); +pub fn detect_parse_iprep(i: &str) -> IResult<&str, DetectIPRepData, RuleParseError<&str>> { + // Inner utility function for easy error creation. + fn make_error(reason: String) -> nom7::Err> { + Err::Error(RuleParseError::InvalidIPRep(reason)) + } + let (_, values) = nom7::multi::separated_list1( + tag(","), + preceded(multispace0, nom7::bytes::complete::is_not(",")), + )(i)?; + + let args = values.len(); + if args == 4 || args == 3 { + let cmd = if let Ok(cmd) = DetectIPRepDataCmd::from_str(values[0].trim()) { + cmd + } else { + return Err(make_error("invalid command".to_string())); + }; + let name = values[1].trim(); + let namez = if let Ok(name) = CString::new(name) { + name + } else { + return Err(make_error("invalid name".to_string())); + }; + let cat = unsafe { SRepCatGetByShortname(namez.as_ptr()) }; + if cat == 0 { + return Err(make_error("unknown category".to_string())); + } + + if args == 4 { + let mode = match detect_parse_uint_mode(values[2].trim()) { + Ok(val) => val.1, + Err(_) => return Err(make_error("invalid mode".to_string())), + }; + + let arg1 = match values[3].trim().parse::() { + Ok(val) => val, + Err(_) => return Err(make_error("invalid value".to_string())), + }; + let du8 = DetectUintData:: { + arg1, + arg2: 0, + mode, + }; + return Ok((i, DetectIPRepData { du8, cat, cmd, isnotset: false, })); + } else { + let (isnotset, mode, arg1) = match values[2].trim() { + "isset" => { (false, DetectUintMode::DetectUintModeGte, 0) }, + "isnotset" => { (true, DetectUintMode::DetectUintModeEqual, 0) }, + _ => { return Err(make_error("invalid mode".to_string())); }, + }; + let du8 = DetectUintData:: { + arg1, + arg2: 0, + mode, + }; + return Ok((i, DetectIPRepData { du8, cat, cmd, isnotset, })); + } + } else if args < 3 { + return Err(make_error("too few arguments".to_string())); + } else { + return Err(make_error("too many arguments".to_string())); } - let (i, _) = opt(is_a(" "))(i)?; - let (i, _) = char(',')(i)?; - let (i, _) = opt(is_a(" "))(i)?; - let (i, mode) = detect_parse_uint_mode(i)?; - let (i, _) = opt(is_a(" "))(i)?; - let (i, _) = char(',')(i)?; - let (i, _) = opt(is_a(" "))(i)?; - let (i, arg1) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; - let (i, _) = all_consuming(take_while(|c| c == ' '))(i)?; - let du8 = DetectUintData:: { - arg1, - arg2: 0, - mode, - }; - return Ok((i, DetectIPRepData { du8, cat, cmd })); } #[no_mangle] -pub unsafe extern "C" fn rs_detect_iprep_parse( +pub unsafe extern "C" fn SCDetectIPRepParse( ustr: *const std::os::raw::c_char, ) -> *mut DetectIPRepData { let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe @@ -122,7 +161,7 @@ pub unsafe extern "C" fn rs_detect_iprep_parse( } #[no_mangle] -pub unsafe extern "C" fn rs_detect_iprep_free(ctx: &mut DetectIPRepData) { +pub unsafe extern "C" fn SCDetectIPRepFree(ctx: &mut DetectIPRepData) { // Just unbox... std::mem::drop(Box::from_raw(ctx)); } diff --git a/rust/src/detect/mod.rs b/rust/src/detect/mod.rs index 2b1fd0e464b0..bb2441798edb 100644 --- a/rust/src/detect/mod.rs +++ b/rust/src/detect/mod.rs @@ -27,6 +27,9 @@ pub mod uri; pub mod requires; pub mod tojson; +use crate::core::AppProto; +use std::os::raw::{c_int, c_void}; + /// EnumString trait that will be implemented on enums that /// derive StringEnum. pub trait EnumString { @@ -43,6 +46,64 @@ pub trait EnumString { fn from_str(s: &str) -> Option where Self: Sized; } +#[repr(C)] +#[allow(non_snake_case)] +pub struct SCSigTableElmt { + pub name: *const libc::c_char, + pub desc: *const libc::c_char, + pub url: *const libc::c_char, + pub flags: u16, + pub Setup: unsafe extern "C" fn( + de: *mut c_void, + s: *mut c_void, + raw: *const std::os::raw::c_char, + ) -> c_int, + pub Free: Option, + pub AppLayerTxMatch: Option< + unsafe extern "C" fn( + de: *mut c_void, + f: *mut c_void, + flags: u8, + state: *mut c_void, + tx: *mut c_void, + sig: *const c_void, + ctx: *const c_void, + ) -> c_int, + >, +} + +pub(crate) const SIGMATCH_NOOPT: u16 = 1; // BIT_U16(0) in detect.h +pub(crate) const SIGMATCH_INFO_STICKY_BUFFER: u16 = 0x200; // BIT_U16(9) + +extern { + pub fn DetectBufferSetActiveList(de: *mut c_void, s: *mut c_void, bufid: c_int) -> c_int; + pub fn DetectHelperGetData( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, + get_buf: unsafe extern "C" fn(*const c_void, u8, *mut *const u8, *mut u32) -> bool, + ) -> *mut c_void; + pub fn DetectHelperBufferMpmRegister( + name: *const libc::c_char, desc: *const libc::c_char, alproto: AppProto, toclient: bool, + toserver: bool, + get_data: unsafe extern "C" fn( + *mut c_void, + *const c_void, + *const c_void, + u8, + *const c_void, + i32, + ) -> *mut c_void, + ) -> c_int; + pub fn DetectHelperKeywordRegister(kw: *const SCSigTableElmt) -> c_int; + pub fn DetectHelperBufferRegister( + name: *const libc::c_char, alproto: AppProto, toclient: bool, toserver: bool, + ) -> c_int; + pub fn DetectSignatureSetAppProto(s: *mut c_void, alproto: AppProto) -> c_int; + pub fn SigMatchAppendSMToList( + de: *mut c_void, s: *mut c_void, kwid: c_int, ctx: *const c_void, bufid: c_int, + ) -> *mut c_void; +} + #[cfg(test)] mod test { use super::*; diff --git a/rust/src/detect/uint.rs b/rust/src/detect/uint.rs index 5b28830cea6a..fdfc4c30f89f 100644 --- a/rust/src/detect/uint.rs +++ b/rust/src/detect/uint.rs @@ -398,9 +398,9 @@ pub unsafe extern "C" fn rs_detect_u64_match( } #[no_mangle] -pub unsafe extern "C" fn rs_detect_u64_free(ctx: *mut std::os::raw::c_void) { +pub unsafe extern "C" fn rs_detect_u64_free(ctx: &mut DetectUintData) { // Just unbox... - std::mem::drop(Box::from_raw(ctx as *mut DetectUintData)); + std::mem::drop(Box::from_raw(ctx)); } #[no_mangle] diff --git a/rust/src/dhcp/detect.rs b/rust/src/dhcp/detect.rs index 0215810ae847..73cf92538643 100644 --- a/rust/src/dhcp/detect.rs +++ b/rust/src/dhcp/detect.rs @@ -16,51 +16,208 @@ */ use super::dhcp::{ - DHCPTransaction, DHCP_OPT_ADDRESS_TIME, DHCP_OPT_REBINDING_TIME, DHCP_OPT_RENEWAL_TIME, + DHCPTransaction, ALPROTO_DHCP, DHCP_OPT_ADDRESS_TIME, DHCP_OPT_REBINDING_TIME, + DHCP_OPT_RENEWAL_TIME, }; use super::parser::DHCPOptionWrapper; +use crate::detect::uint::{ + rs_detect_u64_free, rs_detect_u64_match, rs_detect_u64_parse, DetectUintData, +}; +use crate::detect::{ + DetectHelperBufferRegister, DetectHelperKeywordRegister, DetectSignatureSetAppProto, + SCSigTableElmt, SigMatchAppendSMToList, +}; +use std::os::raw::{c_int, c_void}; -#[no_mangle] -pub unsafe extern "C" fn rs_dhcp_tx_get_leasetime( - tx: &mut DHCPTransaction, leasetime: *mut u64, -) -> u8 { +fn rs_dhcp_tx_get_time(tx: &DHCPTransaction, code: u8) -> Option { for option in &tx.message.options { - if option.code == DHCP_OPT_ADDRESS_TIME { + if option.code == code { if let DHCPOptionWrapper::TimeValue(ref time_value) = option.option { - *leasetime = time_value.seconds as u64; - return 1; + return Some(time_value.seconds as u64); } } } + return None; +} + +static mut G_DHCP_LEASE_TIME_KW_ID: c_int = 0; +static mut G_DHCP_LEASE_TIME_BUFFER_ID: c_int = 0; +static mut G_DHCP_REBINDING_TIME_KW_ID: c_int = 0; +static mut G_DHCP_REBINDING_TIME_BUFFER_ID: c_int = 0; +static mut G_DHCP_RENEWAL_TIME_KW_ID: c_int = 0; +static mut G_DHCP_RENEWAL_TIME_BUFFER_ID: c_int = 0; + +unsafe extern "C" fn dhcp_detect_leasetime_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_DHCP) != 0 { + return -1; + } + let ctx = rs_detect_u64_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_DHCP_LEASE_TIME_KW_ID, + ctx, + G_DHCP_LEASE_TIME_BUFFER_ID, + ) + .is_null() + { + dhcp_detect_time_free(std::ptr::null_mut(), ctx); + return -1; + } return 0; } -#[no_mangle] -pub unsafe extern "C" fn rs_dhcp_tx_get_rebinding_time( - tx: &mut DHCPTransaction, res: *mut u64, -) -> u8 { - for option in &tx.message.options { - if option.code == DHCP_OPT_REBINDING_TIME { - if let DHCPOptionWrapper::TimeValue(ref time_value) = option.option { - *res = time_value.seconds as u64; - return 1; - } - } +unsafe extern "C" fn dhcp_detect_leasetime_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, DHCPTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(val) = rs_dhcp_tx_get_time(tx, DHCP_OPT_ADDRESS_TIME) { + return rs_detect_u64_match(val, ctx); } return 0; } -#[no_mangle] -pub unsafe extern "C" fn rs_dhcp_tx_get_renewal_time( - tx: &mut DHCPTransaction, res: *mut u64, -) -> u8 { - for option in &tx.message.options { - if option.code == DHCP_OPT_RENEWAL_TIME { - if let DHCPOptionWrapper::TimeValue(ref time_value) = option.option { - *res = time_value.seconds as u64; - return 1; - } - } +unsafe extern "C" fn dhcp_detect_time_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u64_free(ctx); +} + +unsafe extern "C" fn dhcp_detect_rebindingtime_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_DHCP) != 0 { + return -1; + } + let ctx = rs_detect_u64_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_DHCP_REBINDING_TIME_KW_ID, + ctx, + G_DHCP_REBINDING_TIME_BUFFER_ID, + ) + .is_null() + { + dhcp_detect_time_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn dhcp_detect_rebindingtime_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, DHCPTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(val) = rs_dhcp_tx_get_time(tx, DHCP_OPT_REBINDING_TIME) { + return rs_detect_u64_match(val, ctx); + } + return 0; +} + +unsafe extern "C" fn dhcp_detect_renewaltime_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_DHCP) != 0 { + return -1; + } + let ctx = rs_detect_u64_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_DHCP_RENEWAL_TIME_KW_ID, + ctx, + G_DHCP_RENEWAL_TIME_BUFFER_ID, + ) + .is_null() + { + dhcp_detect_time_free(std::ptr::null_mut(), ctx); + return -1; } return 0; } + +unsafe extern "C" fn dhcp_detect_renewaltime_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, DHCPTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(val) = rs_dhcp_tx_get_time(tx, DHCP_OPT_RENEWAL_TIME) { + return rs_detect_u64_match(val, ctx); + } + return 0; +} + +#[no_mangle] +pub unsafe extern "C" fn ScDetectDHCPRegister() { + let kw = SCSigTableElmt { + name: b"dhcp.leasetime\0".as_ptr() as *const libc::c_char, + desc: b"match DHCP leasetime\0".as_ptr() as *const libc::c_char, + url: b"/rules/dhcp-keywords.html#dhcp-leasetime\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(dhcp_detect_leasetime_match), + Setup: dhcp_detect_leasetime_setup, + Free: Some(dhcp_detect_time_free), + flags: 0, + }; + unsafe { + G_DHCP_LEASE_TIME_KW_ID = DetectHelperKeywordRegister(&kw); + G_DHCP_LEASE_TIME_BUFFER_ID = DetectHelperBufferRegister( + b"dhcp.leasetime\0".as_ptr() as *const libc::c_char, + ALPROTO_DHCP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"dhcp.rebinding_time\0".as_ptr() as *const libc::c_char, + desc: b"match DHCP rebinding time\0".as_ptr() as *const libc::c_char, + url: b"/rules/dhcp-keywords.html#dhcp-rebinding-time\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(dhcp_detect_rebindingtime_match), + Setup: dhcp_detect_rebindingtime_setup, + Free: Some(dhcp_detect_time_free), + flags: 0, + }; + unsafe { + G_DHCP_REBINDING_TIME_KW_ID = DetectHelperKeywordRegister(&kw); + G_DHCP_REBINDING_TIME_BUFFER_ID = DetectHelperBufferRegister( + b"dhcp.rebinding-time\0".as_ptr() as *const libc::c_char, + ALPROTO_DHCP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"dhcp.renewal_time\0".as_ptr() as *const libc::c_char, + desc: b"match DHCP renewal time\0".as_ptr() as *const libc::c_char, + url: b"/rules/dhcp-keywords.html#dhcp-renewal-time\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(dhcp_detect_renewaltime_match), + Setup: dhcp_detect_renewaltime_setup, + Free: Some(dhcp_detect_time_free), + flags: 0, + }; + unsafe { + G_DHCP_RENEWAL_TIME_KW_ID = DetectHelperKeywordRegister(&kw); + G_DHCP_RENEWAL_TIME_BUFFER_ID = DetectHelperBufferRegister( + b"dhcp.renewal-time\0".as_ptr() as *const libc::c_char, + ALPROTO_DHCP, + true, + true, + ); + } +} diff --git a/rust/src/dhcp/dhcp.rs b/rust/src/dhcp/dhcp.rs index 7f0da5526e19..e43d4e863a60 100644 --- a/rust/src/dhcp/dhcp.rs +++ b/rust/src/dhcp/dhcp.rs @@ -22,7 +22,7 @@ use crate::dhcp::parser::*; use std; use std::ffi::CString; -static mut ALPROTO_DHCP: AppProto = ALPROTO_UNKNOWN; +pub(super) static mut ALPROTO_DHCP: AppProto = ALPROTO_UNKNOWN; static DHCP_MIN_FRAME_LEN: u32 = 232; diff --git a/rust/src/enip/detect.rs b/rust/src/enip/detect.rs index 2de00ca0143a..dde0af841f2d 100644 --- a/rust/src/enip/detect.rs +++ b/rust/src/enip/detect.rs @@ -20,25 +20,31 @@ use nom7::combinator::{map_opt, opt, verify}; use nom7::error::{make_error, ErrorKind}; use nom7::IResult; -use std::ffi::c_void; +use std::os::raw::{c_int, c_void}; -use crate::enip::constant::{EnipCommand, EnipStatus}; -use crate::enip::enip::EnipTransaction; -use crate::enip::parser::{ +use super::constant::{EnipCommand, EnipStatus}; +use super::enip::{EnipTransaction, ALPROTO_ENIP}; +use super::parser::{ CipData, CipDir, EnipCipRequestPayload, EnipCipResponsePayload, EnipItemPayload, EnipPayload, CIP_MULTIPLE_SERVICE, }; -use crate::detect::uint::{detect_match_uint, detect_parse_uint_enum, DetectUintData}; +use crate::detect::uint::{ + detect_match_uint, detect_parse_uint_enum, rs_detect_u16_free, rs_detect_u16_match, + rs_detect_u16_parse, rs_detect_u32_free, rs_detect_u32_match, rs_detect_u32_parse, + rs_detect_u8_free, rs_detect_u8_match, rs_detect_u8_parse, DetectUintData, +}; +use crate::detect::{ + DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperBufferRegister, + DetectHelperGetData, DetectHelperKeywordRegister, DetectSignatureSetAppProto, SCSigTableElmt, + SigMatchAppendSMToList, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT, +}; use crate::core::Direction; use std::ffi::CStr; -#[no_mangle] -pub unsafe extern "C" fn SCEnipParseCommand( - raw: *const std::os::raw::c_char, -) -> *mut DetectUintData { +unsafe fn parse_command(raw: *const std::os::raw::c_char) -> *mut DetectUintData { let raw: &CStr = CStr::from_ptr(raw); //unsafe if let Ok(s) = raw.to_str() { if let Some(ctx) = detect_parse_uint_enum::(s) { @@ -49,10 +55,7 @@ pub unsafe extern "C" fn SCEnipParseCommand( return std::ptr::null_mut(); } -#[no_mangle] -pub unsafe extern "C" fn SCEnipParseStatus( - raw: *const std::os::raw::c_char, -) -> *mut DetectUintData { +unsafe fn parse_status(raw: *const std::os::raw::c_char) -> *mut DetectUintData { let raw: &CStr = CStr::from_ptr(raw); //unsafe if let Ok(s) = raw.to_str() { if let Some(ctx) = detect_parse_uint_enum::(s) { @@ -63,23 +66,6 @@ pub unsafe extern "C" fn SCEnipParseStatus( return std::ptr::null_mut(); } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetCommand( - tx: &mut EnipTransaction, direction: u8, value: *mut u16, -) -> bool { - let direction: Direction = direction.into(); - if direction == Direction::ToServer { - if let Some(req) = &tx.request { - *value = req.header.cmd; - return true; - } - } else if let Some(resp) = &tx.response { - *value = resp.header.cmd; - return true; - } - return false; -} - #[derive(Clone, Debug, Default)] pub struct DetectCipServiceData { pub service: u8, @@ -128,23 +114,6 @@ fn enip_parse_cip_service(i: &str) -> IResult<&str, DetectCipServiceData> { )); } -#[no_mangle] -pub unsafe extern "C" fn SCEnipParseCipService(raw: *const std::os::raw::c_char) -> *mut c_void { - let raw: &CStr = CStr::from_ptr(raw); //unsafe - if let Ok(s) = raw.to_str() { - if let Ok((_, ctx)) = enip_parse_cip_service(s) { - let boxed = Box::new(ctx); - return Box::into_raw(boxed) as *mut _; - } - } - return std::ptr::null_mut(); -} - -#[no_mangle] -pub unsafe extern "C" fn SCEnipCipServiceFree(ctx: *mut c_void) { - std::mem::drop(Box::from_raw(ctx as *mut DetectCipServiceData)); -} - fn enip_cip_has_attribute(cipdir: &CipDir, attr: u32) -> std::os::raw::c_int { if let CipDir::Request(req) = cipdir { for seg in req.path.iter() { @@ -242,14 +211,6 @@ fn enip_tx_has_cip_service( return 0; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxHasCipService( - tx: &mut EnipTransaction, direction: u8, ctx: *const c_void, -) -> std::os::raw::c_int { - let ctx = cast_pointer!(ctx, DetectCipServiceData); - return enip_tx_has_cip_service(tx, direction.into(), ctx); -} - fn enip_cip_match_status(d: &CipData, ctx: &DetectUintData) -> std::os::raw::c_int { if let CipDir::Response(resp) = &d.cipdir { if detect_match_uint(ctx, resp.status) { @@ -281,14 +242,6 @@ fn enip_tx_has_cip_status( return 0; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxHasCipStatus( - tx: &mut EnipTransaction, ctx: *const c_void, -) -> std::os::raw::c_int { - let ctx = cast_pointer!(ctx, DetectUintData); - return enip_tx_has_cip_status(tx, ctx); -} - fn enip_cip_match_extendedstatus(d: &CipData, ctx: &DetectUintData) -> std::os::raw::c_int { if let CipDir::Response(resp) = &d.cipdir { if resp.status_extended.len() == 2 { @@ -323,14 +276,6 @@ fn enip_tx_has_cip_extendedstatus( return 0; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxHasCipExtendedstatus( - tx: &mut EnipTransaction, ctx: *const c_void, -) -> std::os::raw::c_int { - let ctx = cast_pointer!(ctx, DetectUintData); - return enip_tx_has_cip_extendedstatus(tx, ctx); -} - fn enip_get_status(tx: &mut EnipTransaction, direction: Direction) -> Option { if direction == Direction::ToServer { if let Some(req) = &tx.request { @@ -377,22 +322,6 @@ fn enip_tx_has_cip_segment( return 0; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxHasCipClass( - tx: &mut EnipTransaction, ctx: *const c_void, -) -> std::os::raw::c_int { - let ctx = cast_pointer!(ctx, DetectUintData); - return enip_tx_has_cip_segment(tx, ctx, 8); -} - -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxHasCipInstance( - tx: &mut EnipTransaction, ctx: *const c_void, -) -> std::os::raw::c_int { - let ctx = cast_pointer!(ctx, DetectUintData); - return enip_tx_has_cip_segment(tx, ctx, 9); -} - fn enip_cip_match_attribute(d: &CipData, ctx: &DetectUintData) -> std::os::raw::c_int { if let CipDir::Request(req) = &d.cipdir { for seg in req.path.iter() { @@ -443,26 +372,7 @@ fn enip_tx_has_cip_attribute( return 0; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxHasCipAttribute( - tx: &mut EnipTransaction, ctx: *const c_void, -) -> std::os::raw::c_int { - let ctx = cast_pointer!(ctx, DetectUintData); - return enip_tx_has_cip_attribute(tx, ctx); -} - -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetStatus( - tx: &mut EnipTransaction, direction: u8, value: *mut u32, -) -> bool { - if let Some(x) = enip_get_status(tx, direction.into()) { - *value = x; - return true; - } - return false; -} - -fn enip_tx_get_protocol_version(tx: &mut EnipTransaction, direction: Direction) -> Option { +fn tx_get_protocol_version(tx: &mut EnipTransaction, direction: Direction) -> Option { if direction == Direction::ToServer { if let Some(req) = &tx.request { if let EnipPayload::RegisterSession(rs) = &req.payload { @@ -490,181 +400,1305 @@ fn enip_tx_get_protocol_version(tx: &mut EnipTransaction, direction: Direction) return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetProtocolVersion( - tx: &mut EnipTransaction, direction: u8, value: *mut u16, -) -> bool { - if let Some(val) = enip_tx_get_protocol_version(tx, direction.into()) { - *value = val; - return true; +static mut G_ENIP_CIPSERVICE_KW_ID: c_int = 0; +static mut G_ENIP_CIPSERVICE_BUFFER_ID: c_int = 0; +static mut G_ENIP_CAPABILITIES_KW_ID: c_int = 0; +static mut G_ENIP_CAPABILITIES_BUFFER_ID: c_int = 0; +static mut G_ENIP_CIP_ATTRIBUTE_KW_ID: c_int = 0; +static mut G_ENIP_CIP_ATTRIBUTE_BUFFER_ID: c_int = 0; +static mut G_ENIP_CIP_CLASS_KW_ID: c_int = 0; +static mut G_ENIP_CIP_CLASS_BUFFER_ID: c_int = 0; +static mut G_ENIP_VENDOR_ID_KW_ID: c_int = 0; +static mut G_ENIP_VENDOR_ID_BUFFER_ID: c_int = 0; +static mut G_ENIP_STATUS_KW_ID: c_int = 0; +static mut G_ENIP_STATUS_BUFFER_ID: c_int = 0; +static mut G_ENIP_STATE_KW_ID: c_int = 0; +static mut G_ENIP_STATE_BUFFER_ID: c_int = 0; +static mut G_ENIP_SERIAL_KW_ID: c_int = 0; +static mut G_ENIP_SERIAL_BUFFER_ID: c_int = 0; +static mut G_ENIP_REVISION_KW_ID: c_int = 0; +static mut G_ENIP_REVISION_BUFFER_ID: c_int = 0; +static mut G_ENIP_PROTOCOL_VERSION_KW_ID: c_int = 0; +static mut G_ENIP_PROTOCOL_VERSION_BUFFER_ID: c_int = 0; +static mut G_ENIP_PRODUCT_CODE_KW_ID: c_int = 0; +static mut G_ENIP_PRODUCT_CODE_BUFFER_ID: c_int = 0; +static mut G_ENIP_IDENTITY_STATUS_KW_ID: c_int = 0; +static mut G_ENIP_IDENTITY_STATUS_BUFFER_ID: c_int = 0; +static mut G_ENIP_DEVICE_TYPE_KW_ID: c_int = 0; +static mut G_ENIP_DEVICE_TYPE_BUFFER_ID: c_int = 0; +static mut G_ENIP_COMMAND_KW_ID: c_int = 0; +static mut G_ENIP_COMMAND_BUFFER_ID: c_int = 0; +static mut G_ENIP_CIP_STATUS_KW_ID: c_int = 0; +static mut G_ENIP_CIP_STATUS_BUFFER_ID: c_int = 0; +static mut G_ENIP_CIP_INSTANCE_KW_ID: c_int = 0; +static mut G_ENIP_CIP_INSTANCE_BUFFER_ID: c_int = 0; +static mut G_ENIP_CIP_EXTENDEDSTATUS_KW_ID: c_int = 0; +static mut G_ENIP_CIP_EXTENDEDSTATUS_BUFFER_ID: c_int = 0; +static mut G_ENIP_PRODUCT_NAME_BUFFER_ID: c_int = 0; +static mut G_ENIP_SERVICE_NAME_BUFFER_ID: c_int = 0; + +unsafe fn parse_cip_service(raw: *const std::os::raw::c_char) -> *mut c_void { + let raw: &CStr = CStr::from_ptr(raw); //unsafe + if let Ok(s) = raw.to_str() { + if let Ok((_, ctx)) = enip_parse_cip_service(s) { + let boxed = Box::new(ctx); + return Box::into_raw(boxed) as *mut _; + } } - return false; + return std::ptr::null_mut(); } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetCapabilities( - tx: &mut EnipTransaction, value: *mut u16, -) -> bool { +unsafe extern "C" fn cipservice_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = parse_cip_service(raw); + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_CIPSERVICE_KW_ID, + ctx, + G_ENIP_CIPSERVICE_BUFFER_ID, + ) + .is_null() + { + cipservice_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn cipservice_free(_de: *mut c_void, ctx: *mut c_void) { + std::mem::drop(Box::from_raw(ctx as *mut DetectCipServiceData)); +} + +unsafe extern "C" fn cipservice_match( + _de: *mut c_void, _f: *mut c_void, flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectCipServiceData); + return enip_tx_has_cip_service(tx, flags.into(), ctx); +} + +unsafe extern "C" fn capabilities_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u16_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_CAPABILITIES_KW_ID, + ctx, + G_ENIP_CAPABILITIES_BUFFER_ID, + ) + .is_null() + { + capabilities_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_capabilities(tx: &mut EnipTransaction) -> Option { if let Some(ref response) = tx.response { if let EnipPayload::ListServices(lsp) = &response.payload { if !lsp.is_empty() { if let EnipItemPayload::Services(ls) = &lsp[0].payload { - *value = ls.capabilities; - return true; + return Some(ls.capabilities); } } } } - return false; + return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetRevision(tx: &mut EnipTransaction, value: *mut u16) -> bool { +unsafe extern "C" fn capabilities_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(v) = tx_get_capabilities(tx) { + return rs_detect_u16_match(v, ctx); + } + return 0; +} + +unsafe extern "C" fn capabilities_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +unsafe extern "C" fn cip_attribute_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u32_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_CIP_ATTRIBUTE_KW_ID, + ctx, + G_ENIP_CIP_ATTRIBUTE_BUFFER_ID, + ) + .is_null() + { + cip_attribute_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn cip_attribute_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + return enip_tx_has_cip_attribute(tx, ctx); +} + +unsafe extern "C" fn cip_attribute_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u32_free(ctx); +} + +unsafe extern "C" fn cip_class_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u32_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_CIP_CLASS_KW_ID, + ctx, + G_ENIP_CIP_CLASS_BUFFER_ID, + ) + .is_null() + { + cip_class_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn cip_class_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + return enip_tx_has_cip_segment(tx, ctx, 8); +} + +unsafe extern "C" fn cip_class_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u32_free(ctx); +} + +unsafe extern "C" fn vendor_id_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u16_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_VENDOR_ID_KW_ID, + ctx, + G_ENIP_VENDOR_ID_BUFFER_ID, + ) + .is_null() + { + vendor_id_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_vendor_id(tx: &mut EnipTransaction) -> Option { if let Some(ref response) = tx.response { if let EnipPayload::ListIdentity(lip) = &response.payload { if !lip.is_empty() { if let EnipItemPayload::Identity(li) = &lip[0].payload { - *value = ((li.revision_major as u16) << 8) | (li.revision_minor as u16); - return true; + return Some(li.vendor_id); } } } } - return false; + return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetIdentityStatus( - tx: &mut EnipTransaction, value: *mut u16, -) -> bool { +unsafe extern "C" fn vendor_id_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(val) = tx_get_vendor_id(tx) { + return rs_detect_u16_match(val, ctx); + } + return 0; +} + +unsafe extern "C" fn vendor_id_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +unsafe extern "C" fn status_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = parse_status(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList(de, s, G_ENIP_STATUS_KW_ID, ctx, G_ENIP_STATUS_BUFFER_ID).is_null() { + status_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn status_match( + _de: *mut c_void, _f: *mut c_void, flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(x) = enip_get_status(tx, flags.into()) { + return rs_detect_u32_match(x, ctx); + } + return 0; +} + +unsafe extern "C" fn status_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u32_free(ctx); +} + +unsafe extern "C" fn state_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u8_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList(de, s, G_ENIP_STATE_KW_ID, ctx, G_ENIP_STATE_BUFFER_ID).is_null() { + state_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_state(tx: &mut EnipTransaction) -> Option { if let Some(ref response) = tx.response { if let EnipPayload::ListIdentity(lip) = &response.payload { if !lip.is_empty() { if let EnipItemPayload::Identity(li) = &lip[0].payload { - *value = li.status; - return true; + return Some(li.state); } } } } - return false; + return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetState(tx: &mut EnipTransaction, value: *mut u8) -> bool { +unsafe extern "C" fn state_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(val) = tx_get_state(tx) { + return rs_detect_u8_match(val, ctx); + } + return 0; +} + +unsafe extern "C" fn state_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u8_free(ctx); +} + +unsafe extern "C" fn serial_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u32_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList(de, s, G_ENIP_SERIAL_KW_ID, ctx, G_ENIP_SERIAL_BUFFER_ID).is_null() { + serial_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_serial(tx: &mut EnipTransaction) -> Option { if let Some(ref response) = tx.response { if let EnipPayload::ListIdentity(lip) = &response.payload { if !lip.is_empty() { if let EnipItemPayload::Identity(li) = &lip[0].payload { - *value = li.state; - return true; + return Some(li.serial); } } } } - return false; + return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetSerial(tx: &mut EnipTransaction, value: *mut u32) -> bool { +unsafe extern "C" fn serial_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(val) = tx_get_serial(tx) { + return rs_detect_u32_match(val, ctx); + } + return 0; +} + +unsafe extern "C" fn serial_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u32_free(ctx); +} + +unsafe extern "C" fn revision_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u16_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList(de, s, G_ENIP_REVISION_KW_ID, ctx, G_ENIP_REVISION_BUFFER_ID) + .is_null() + { + revision_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_revision(tx: &mut EnipTransaction) -> Option { if let Some(ref response) = tx.response { if let EnipPayload::ListIdentity(lip) = &response.payload { if !lip.is_empty() { if let EnipItemPayload::Identity(li) = &lip[0].payload { - *value = li.serial; - return true; + return Some(((li.revision_major as u16) << 8) | (li.revision_minor as u16)); } } } } - return false; + return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetProductCode(tx: &mut EnipTransaction, value: *mut u16) -> bool { +unsafe extern "C" fn revision_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(val) = tx_get_revision(tx) { + return rs_detect_u16_match(val, ctx); + } + return 0; +} + +unsafe extern "C" fn revision_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +unsafe extern "C" fn protocol_version_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u16_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_PROTOCOL_VERSION_KW_ID, + ctx, + G_ENIP_PROTOCOL_VERSION_BUFFER_ID, + ) + .is_null() + { + protocol_version_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn protocol_version_match( + _de: *mut c_void, _f: *mut c_void, flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(val) = tx_get_protocol_version(tx, flags.into()) { + return rs_detect_u16_match(val, ctx); + } + return 0; +} + +unsafe extern "C" fn protocol_version_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +unsafe extern "C" fn product_code_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u16_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_PRODUCT_CODE_KW_ID, + ctx, + G_ENIP_PRODUCT_CODE_BUFFER_ID, + ) + .is_null() + { + product_code_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_product_code(tx: &mut EnipTransaction) -> Option { if let Some(ref response) = tx.response { if let EnipPayload::ListIdentity(lip) = &response.payload { if !lip.is_empty() { if let EnipItemPayload::Identity(li) = &lip[0].payload { - *value = li.product_code; - return true; + return Some(li.product_code); } } } } - return false; + return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetDeviceType(tx: &mut EnipTransaction, value: *mut u16) -> bool { +unsafe extern "C" fn product_code_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(v) = tx_get_product_code(tx) { + return rs_detect_u16_match(v, ctx); + } + return 0; +} + +unsafe extern "C" fn product_code_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +unsafe extern "C" fn identity_status_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u16_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_IDENTITY_STATUS_KW_ID, + ctx, + G_ENIP_IDENTITY_STATUS_BUFFER_ID, + ) + .is_null() + { + identity_status_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_identity_status(tx: &mut EnipTransaction) -> Option { if let Some(ref response) = tx.response { if let EnipPayload::ListIdentity(lip) = &response.payload { if !lip.is_empty() { if let EnipItemPayload::Identity(li) = &lip[0].payload { - *value = li.device_type; - return true; + return Some(li.status); } } } } - return false; + return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetVendorId(tx: &mut EnipTransaction, value: *mut u16) -> bool { +unsafe extern "C" fn identity_status_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(v) = tx_get_identity_status(tx) { + return rs_detect_u16_match(v, ctx); + } + return 0; +} + +unsafe extern "C" fn identity_status_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +unsafe extern "C" fn device_type_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u16_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_DEVICE_TYPE_KW_ID, + ctx, + G_ENIP_DEVICE_TYPE_BUFFER_ID, + ) + .is_null() + { + device_type_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_device_type(tx: &mut EnipTransaction) -> Option { if let Some(ref response) = tx.response { if let EnipPayload::ListIdentity(lip) = &response.payload { if !lip.is_empty() { if let EnipItemPayload::Identity(li) = &lip[0].payload { - *value = li.vendor_id; - return true; + return Some(li.device_type); } } } } - return false; + return None; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetProductName( - tx: &EnipTransaction, buffer: *mut *const u8, buffer_len: *mut u32, -) -> u8 { +unsafe extern "C" fn device_type_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(v) = tx_get_device_type(tx) { + return rs_detect_u16_match(v, ctx); + } + return 0; +} + +unsafe extern "C" fn device_type_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +unsafe extern "C" fn command_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = parse_command(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList(de, s, G_ENIP_COMMAND_KW_ID, ctx, G_ENIP_COMMAND_BUFFER_ID).is_null() + { + command_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +fn tx_get_command(tx: &mut EnipTransaction, direction: u8) -> Option { + let direction: Direction = direction.into(); + if direction == Direction::ToServer { + if let Some(req) = &tx.request { + return Some(req.header.cmd); + } + } else if let Some(resp) = &tx.response { + return Some(resp.header.cmd); + } + return None; +} + +unsafe extern "C" fn command_match( + _de: *mut c_void, _f: *mut c_void, flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(v) = tx_get_command(tx, flags) { + return rs_detect_u16_match(v, ctx); + } + return 0; +} + +unsafe extern "C" fn command_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +unsafe extern "C" fn cip_status_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u8_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_CIP_STATUS_KW_ID, + ctx, + G_ENIP_CIP_STATUS_BUFFER_ID, + ) + .is_null() + { + cip_status_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn cip_status_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + return enip_tx_has_cip_status(tx, ctx); +} + +unsafe extern "C" fn cip_status_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u8_free(ctx); +} + +unsafe extern "C" fn cip_instance_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u32_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_CIP_INSTANCE_KW_ID, + ctx, + G_ENIP_CIP_INSTANCE_BUFFER_ID, + ) + .is_null() + { + cip_instance_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn cip_instance_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + return enip_tx_has_cip_segment(tx, ctx, 9); +} + +unsafe extern "C" fn cip_instance_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u32_free(ctx); +} + +unsafe extern "C" fn cip_extendedstatus_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + let ctx = rs_detect_u16_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_ENIP_CIP_EXTENDEDSTATUS_KW_ID, + ctx, + G_ENIP_CIP_EXTENDEDSTATUS_BUFFER_ID, + ) + .is_null() + { + cip_extendedstatus_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn cip_extendedstatus_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, EnipTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + return enip_tx_has_cip_extendedstatus(tx, ctx); +} + +unsafe extern "C" fn cip_extendedstatus_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u16_free(ctx); +} + +pub unsafe extern "C" fn product_name_setup( + de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + if DetectBufferSetActiveList(de, s, G_ENIP_PRODUCT_NAME_BUFFER_ID) < 0 { + return -1; + } + return 0; +} + +unsafe extern "C" fn product_name_get( + tx: *const c_void, _flow_flags: u8, buffer: *mut *const u8, buffer_len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, EnipTransaction); if let Some(ref response) = tx.response { if let EnipPayload::ListIdentity(lip) = &response.payload { if !lip.is_empty() { if let EnipItemPayload::Identity(li) = &lip[0].payload { *buffer = li.product_name.as_ptr(); *buffer_len = li.product_name.len() as u32; - return 1; + return true; } } } } - *buffer = std::ptr::null(); *buffer_len = 0; + return false; +} + +unsafe extern "C" fn product_name_get_data( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, +) -> *mut c_void { + return DetectHelperGetData( + de, + transforms, + flow, + flow_flags, + tx, + list_id, + product_name_get, + ); +} + +pub unsafe extern "C" fn service_name_setup( + de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0 { + return -1; + } + if DetectBufferSetActiveList(de, s, G_ENIP_SERVICE_NAME_BUFFER_ID) < 0 { + return -1; + } return 0; } -#[no_mangle] -pub unsafe extern "C" fn SCEnipTxGetServiceName( - tx: &EnipTransaction, buffer: *mut *const u8, buffer_len: *mut u32, -) -> u8 { +unsafe extern "C" fn service_name_get( + tx: *const c_void, _flow_flags: u8, buffer: *mut *const u8, buffer_len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, EnipTransaction); if let Some(ref response) = tx.response { if let EnipPayload::ListServices(lsp) = &response.payload { if !lsp.is_empty() { if let EnipItemPayload::Services(ls) = &lsp[0].payload { *buffer = ls.service_name.as_ptr(); *buffer_len = ls.service_name.len() as u32; - return 1; + return true; } } } } - *buffer = std::ptr::null(); *buffer_len = 0; - return 0; + return false; +} + +unsafe extern "C" fn service_name_get_data( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, +) -> *mut c_void { + return DetectHelperGetData( + de, + transforms, + flow, + flow_flags, + tx, + list_id, + service_name_get, + ); +} +#[no_mangle] +pub unsafe extern "C" fn ScDetectEnipRegister() { + let kw = SCSigTableElmt { + name: b"cip_service\0".as_ptr() as *const libc::c_char, + desc: b"match on CIP Service, and optionnally class and attribute\0".as_ptr() + as *const libc::c_char, + url: b"/rules/enip-keyword.html#cip_service\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(cipservice_match), + Setup: cipservice_setup, + Free: Some(cipservice_free), + flags: 0, + }; + unsafe { + G_ENIP_CIPSERVICE_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_CIPSERVICE_BUFFER_ID = DetectHelperBufferRegister( + b"cip\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.capabilities\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP capabilities\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-capabilities\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(capabilities_match), + Setup: capabilities_setup, + Free: Some(capabilities_free), + flags: 0, + }; + unsafe { + G_ENIP_CAPABILITIES_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_CAPABILITIES_BUFFER_ID = DetectHelperBufferRegister( + b"enip.capabilities\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.cip_attribute\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP cip_attribute\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-cip-attribute\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(cip_attribute_match), + Setup: cip_attribute_setup, + Free: Some(cip_attribute_free), + flags: 0, + }; + unsafe { + G_ENIP_CIP_ATTRIBUTE_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_CIP_ATTRIBUTE_BUFFER_ID = DetectHelperBufferRegister( + b"enip.cip_attribute\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.cip_class\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP cip_class\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-cip-class\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(cip_class_match), + Setup: cip_class_setup, + Free: Some(cip_class_free), + flags: 0, + }; + unsafe { + G_ENIP_CIP_CLASS_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_CIP_CLASS_BUFFER_ID = DetectHelperBufferRegister( + b"enip.cip_class\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.vendor_id\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP vendor_id\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-vendor-id\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(vendor_id_match), + Setup: vendor_id_setup, + Free: Some(vendor_id_free), + flags: 0, + }; + unsafe { + G_ENIP_VENDOR_ID_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_VENDOR_ID_BUFFER_ID = DetectHelperBufferRegister( + b"enip.vendor_id\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.status\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP status\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-status\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(status_match), + Setup: status_setup, + Free: Some(status_free), + flags: 0, + }; + unsafe { + G_ENIP_STATUS_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_STATUS_BUFFER_ID = DetectHelperBufferRegister( + b"enip.status\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.state\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP state\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-state\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(state_match), + Setup: state_setup, + Free: Some(state_free), + flags: 0, + }; + unsafe { + G_ENIP_STATE_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_STATE_BUFFER_ID = DetectHelperBufferRegister( + b"enip.state\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.serial\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP serial\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-serial\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(serial_match), + Setup: serial_setup, + Free: Some(serial_free), + flags: 0, + }; + unsafe { + G_ENIP_SERIAL_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_SERIAL_BUFFER_ID = DetectHelperBufferRegister( + b"enip.serial\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.revision\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP revision\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-revision\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(revision_match), + Setup: revision_setup, + Free: Some(revision_free), + flags: 0, + }; + unsafe { + G_ENIP_REVISION_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_REVISION_BUFFER_ID = DetectHelperBufferRegister( + b"enip.revision\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.protocol_version\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP protocol_version\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-protocol-version\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(protocol_version_match), + Setup: protocol_version_setup, + Free: Some(protocol_version_free), + flags: 0, + }; + unsafe { + G_ENIP_PROTOCOL_VERSION_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_PROTOCOL_VERSION_BUFFER_ID = DetectHelperBufferRegister( + b"enip.protocol_version\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.product_code\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP product_code\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-product-code\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(product_code_match), + Setup: product_code_setup, + Free: Some(product_code_free), + flags: 0, + }; + unsafe { + G_ENIP_PRODUCT_CODE_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_PRODUCT_CODE_BUFFER_ID = DetectHelperBufferRegister( + b"enip.product_code\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip_command\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP command\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip_command\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(command_match), + Setup: command_setup, + Free: Some(command_free), + flags: 0, + }; + unsafe { + G_ENIP_COMMAND_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_COMMAND_BUFFER_ID = DetectHelperBufferRegister( + b"enip.command\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.identity_status\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP identity_status\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-identity-status\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(identity_status_match), + Setup: identity_status_setup, + Free: Some(identity_status_free), + flags: 0, + }; + unsafe { + G_ENIP_IDENTITY_STATUS_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_IDENTITY_STATUS_BUFFER_ID = DetectHelperBufferRegister( + b"enip.identity_status\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.device_type\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP device_type\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-device-type\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(device_type_match), + Setup: device_type_setup, + Free: Some(device_type_free), + flags: 0, + }; + unsafe { + G_ENIP_DEVICE_TYPE_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_DEVICE_TYPE_BUFFER_ID = DetectHelperBufferRegister( + b"enip.device_type\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip_command\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP command\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip_command\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(command_match), + Setup: command_setup, + Free: Some(command_free), + flags: 0, + }; + unsafe { + G_ENIP_COMMAND_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_COMMAND_BUFFER_ID = DetectHelperBufferRegister( + b"enip.command\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.cip_status\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP cip_status\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-cip-status\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(cip_status_match), + Setup: cip_status_setup, + Free: Some(cip_status_free), + flags: 0, + }; + unsafe { + G_ENIP_CIP_STATUS_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_CIP_STATUS_BUFFER_ID = DetectHelperBufferRegister( + b"enip.cip_status\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.cip_instance\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP cip_instance\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-cip-instance\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(cip_instance_match), + Setup: cip_instance_setup, + Free: Some(cip_instance_free), + flags: 0, + }; + unsafe { + G_ENIP_CIP_INSTANCE_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_CIP_INSTANCE_BUFFER_ID = DetectHelperBufferRegister( + b"enip.cip_instance\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.cip_extendedstatus\0".as_ptr() as *const libc::c_char, + desc: b"rules for detecting EtherNet/IP cip_extendedstatus\0".as_ptr() + as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-cip-extendedstatus\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(cip_extendedstatus_match), + Setup: cip_extendedstatus_setup, + Free: Some(cip_extendedstatus_free), + flags: 0, + }; + unsafe { + G_ENIP_CIP_EXTENDEDSTATUS_KW_ID = DetectHelperKeywordRegister(&kw); + G_ENIP_CIP_EXTENDEDSTATUS_BUFFER_ID = DetectHelperBufferRegister( + b"enip.cip_extendedstatus\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"enip.product_name\0".as_ptr() as *const libc::c_char, + desc: b"sticky buffer to match EtherNet/IP product name\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-product-name\0".as_ptr() as *const libc::c_char, + Setup: product_name_setup, + flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, + AppLayerTxMatch: None, + Free: None, + }; + unsafe { + let _g_enip_product_name_kw_id = DetectHelperKeywordRegister(&kw); + G_ENIP_PRODUCT_NAME_BUFFER_ID = DetectHelperBufferMpmRegister( + b"enip.product_name\0".as_ptr() as *const libc::c_char, + b"ENIP product name\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + product_name_get_data, + ); + } + let kw = SCSigTableElmt { + name: b"enip.service_name\0".as_ptr() as *const libc::c_char, + desc: b"sticky buffer to match EtherNet/IP service name\0".as_ptr() as *const libc::c_char, + url: b"/rules/enip-keyword.html#enip-service-name\0".as_ptr() as *const libc::c_char, + Setup: service_name_setup, + flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, + AppLayerTxMatch: None, + Free: None, + }; + unsafe { + let _g_enip_service_name_kw_id = DetectHelperKeywordRegister(&kw); + G_ENIP_SERVICE_NAME_BUFFER_ID = DetectHelperBufferMpmRegister( + b"enip.service_name\0".as_ptr() as *const libc::c_char, + b"ENIP service name\0".as_ptr() as *const libc::c_char, + ALPROTO_ENIP, + true, + true, + service_name_get_data, + ); + } } #[cfg(test)] diff --git a/rust/src/enip/enip.rs b/rust/src/enip/enip.rs index 834e3e2af4f3..26f11140dc3a 100644 --- a/rust/src/enip/enip.rs +++ b/rust/src/enip/enip.rs @@ -31,7 +31,7 @@ use std::collections::VecDeque; use std::ffi::CString; use std::os::raw::{c_char, c_int, c_void}; -static mut ALPROTO_ENIP: AppProto = ALPROTO_UNKNOWN; +pub(super) static mut ALPROTO_ENIP: AppProto = ALPROTO_UNKNOWN; static mut ENIP_MAX_TX: usize = 1024; @@ -634,13 +634,11 @@ pub unsafe extern "C" fn SCEnipRegisterParsers() { let _ = AppLayerRegisterParser(&parser, alproto); } SCLogDebug!("Rust enip parser registered for UDP."); - unsafe { - AppLayerParserRegisterParserAcceptableDataDirection( - IPPROTO_UDP, - ALPROTO_ENIP, - STREAM_TOSERVER | STREAM_TOCLIENT, - ); - } + AppLayerParserRegisterParserAcceptableDataDirection( + IPPROTO_UDP, + ALPROTO_ENIP, + STREAM_TOSERVER | STREAM_TOCLIENT, + ); AppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_ENIP); } else { SCLogDebug!("Protocol detector and parser disabled for ENIP on UDP."); @@ -661,13 +659,11 @@ pub unsafe extern "C" fn SCEnipRegisterParsers() { let _ = AppLayerRegisterParser(&parser, alproto); } SCLogDebug!("Rust enip parser registered for TCP."); - unsafe { - AppLayerParserRegisterParserAcceptableDataDirection( - IPPROTO_TCP, - ALPROTO_ENIP, - STREAM_TOSERVER | STREAM_TOCLIENT, - ); - } + AppLayerParserRegisterParserAcceptableDataDirection( + IPPROTO_TCP, + ALPROTO_ENIP, + STREAM_TOSERVER | STREAM_TOCLIENT, + ); AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_ENIP); } else { SCLogDebug!("Protocol detector and parser disabled for ENIP on TCP."); diff --git a/rust/src/ftp/mod.rs b/rust/src/ftp/mod.rs index 3839c9661e0d..aae5ff4afe56 100644 --- a/rust/src/ftp/mod.rs +++ b/rust/src/ftp/mod.rs @@ -56,9 +56,9 @@ pub fn ftp_active_port(i: &[u8]) -> IResult<&[u8], u16> { digit1, tag(","), ))(i)?; - let (i, part1) = verify(parse_u16, |&v| v <= std::u8::MAX as u16)(i)?; + let (i, part1) = verify(parse_u16, |&v| v <= u8::MAX as u16)(i)?; let (i, _) = tag(",")(i)?; - let (i, part2) = verify(parse_u16, |&v| v <= std::u8::MAX as u16)(i)?; + let (i, part2) = verify(parse_u16, |&v| v <= u8::MAX as u16)(i)?; Ok((i, part1 * 256 + part2)) } @@ -77,9 +77,9 @@ pub fn ftp_pasv_response(i: &[u8]) -> IResult<&[u8], u16> { digit1, tag(","), ))(i)?; - let (i, part1) = verify(getu16, |&v| v <= std::u8::MAX as u16)(i)?; + let (i, part1) = verify(getu16, |&v| v <= u8::MAX as u16)(i)?; let (i, _) = tag(",")(i)?; - let (i, part2) = verify(getu16, |&v| v <= std::u8::MAX as u16)(i)?; + let (i, part2) = verify(getu16, |&v| v <= u8::MAX as u16)(i)?; // may also be completed by a final point let (i, _) = tag(")")(i)?; let (i, _) = opt(complete(tag(".")))(i)?; diff --git a/rust/src/ike/parser.rs b/rust/src/ike/parser.rs index dcc574534290..3ec5be04b914 100644 --- a/rust/src/ike/parser.rs +++ b/rust/src/ike/parser.rs @@ -69,8 +69,8 @@ pub struct IsakmpHeader { pub struct IsakmpPayloadHeader { pub next_payload: u8, - pub reserved: u8, - pub payload_length: u16, + pub _reserved: u8, + pub _payload_length: u16, } pub struct IsakmpPayload<'a> { @@ -83,24 +83,24 @@ pub struct IsakmpPayload<'a> { // 1 -> Security Association pub struct SecurityAssociationPayload<'a> { pub domain_of_interpretation: u32, - pub situation: Option<&'a [u8]>, + pub _situation: Option<&'a [u8]>, pub data: Option<&'a [u8]>, } // 2 -> Proposal pub struct ProposalPayload<'a> { - pub proposal_number: u8, - pub proposal_type: u8, - pub spi_size: u8, - pub number_transforms: u8, - pub spi: &'a [u8], + pub _proposal_number: u8, + pub _proposal_type: u8, + pub _spi_size: u8, + pub _number_transforms: u8, + pub _spi: &'a [u8], pub data: &'a [u8], } // 3 -> Transform pub struct TransformPayload<'a> { - pub transform_number: u8, - pub transform_type: u8, + pub _transform_number: u8, + pub _transform_type: u8, pub sa_attributes: &'a [u8], } @@ -286,7 +286,7 @@ pub fn parse_security_association(i: &[u8]) -> IResult<&[u8], SecurityAssociatio i, SecurityAssociationPayload { domain_of_interpretation, - situation, + _situation: situation, data, }, )) @@ -308,11 +308,11 @@ pub fn parse_proposal(i: &[u8]) -> IResult<&[u8], ProposalPayload> { take((start_i.len() - 4) - spi_size as usize)(b) })(i)?; let payload = ProposalPayload { - proposal_number, - proposal_type, - spi_size, - number_transforms, - spi, + _proposal_number: proposal_number, + _proposal_type: proposal_type, + _spi_size: spi_size, + _number_transforms: number_transforms, + _spi: spi, data: payload_data.unwrap_or_default(), }; Ok((i, payload)) @@ -326,8 +326,8 @@ pub fn parse_transform(i: &[u8], length: u16) -> IResult<&[u8], TransformPayload Ok(( i, TransformPayload { - transform_number, - transform_type, + _transform_number: transform_number, + _transform_type: transform_type, sa_attributes: payload_data.unwrap_or_default(), }, )) @@ -495,8 +495,8 @@ pub fn parse_ikev1_payload_list(i: &[u8]) -> IResult<&[u8], Vec> IsakmpPayload { payload_header: IsakmpPayloadHeader { next_payload, - reserved, - payload_length, + _reserved: reserved, + _payload_length: payload_length, }, data: payload_data.unwrap_or_default(), }, diff --git a/rust/src/modbus/detect.rs b/rust/src/modbus/detect.rs index fdd5d51db9f5..4dc14d03783e 100644 --- a/rust/src/modbus/detect.rs +++ b/rust/src/modbus/detect.rs @@ -63,9 +63,9 @@ pub struct DetectModbusRust { fn check_match_range(sig_range: &Range, trans_range: RangeInclusive) -> bool { if sig_range.start == sig_range.end { sig_range.start >= *trans_range.start() && sig_range.start <= *trans_range.end() - } else if sig_range.start == std::u16::MIN { + } else if sig_range.start == u16::MIN { sig_range.end > *trans_range.start() - } else if sig_range.end == std::u16::MAX { + } else if sig_range.end == u16::MAX { sig_range.start < *trans_range.end() } else { sig_range.start < *trans_range.end() && *trans_range.start() < sig_range.end @@ -78,9 +78,9 @@ fn check_match_range(sig_range: &Range, trans_range: RangeInclusive) - fn check_match(sig_range: &Range, value: u16) -> bool { if sig_range.start == sig_range.end { sig_range.start == value - } else if sig_range.start == std::u16::MIN { + } else if sig_range.start == u16::MIN { sig_range.end > value - } else if sig_range.end == std::u16::MAX { + } else if sig_range.end == u16::MAX { sig_range.start < value } else { sig_range.start < value && value < sig_range.end @@ -90,8 +90,8 @@ fn check_match(sig_range: &Range, value: u16) -> bool { /// Gets the min/max range of an alert signature from the respective capture groups. /// In the case where the max is not given, it is set based on the first char of the min str /// which indicates what range we are looking for: -/// '<' = std::u16::MIN..min -/// '>' = min..std::u16::MAX +/// '<' = u16::MIN..min +/// '>' = min..u16::MAX /// _ = min..min /// If the max is given, the range returned is min..max fn parse_range(min_str: &str, max_str: &str) -> Result, ()> { @@ -100,8 +100,8 @@ fn parse_range(min_str: &str, max_str: &str) -> Result, ()> { debug_validate_bug_on!(!sign.is_ascii_digit() && sign != '<' && sign != '>'); match min_str[!sign.is_ascii_digit() as usize..].parse::() { Ok(num) => match sign { - '>' => Ok(num..std::u16::MAX), - '<' => Ok(std::u16::MIN..num), + '>' => Ok(num..u16::MAX), + '<' => Ok(u16::MIN..num), _ => Ok(num..num), }, Err(_) => { @@ -524,7 +524,7 @@ mod test { parse_access("access write coils, address <500"), Ok(DetectModbusRust { access_type: Some(AccessType::WRITE | AccessType::COILS), - address: Some(std::u16::MIN..500), + address: Some(u16::MIN..500), ..Default::default() }) ); @@ -532,7 +532,7 @@ mod test { parse_access("access write coils, address >500"), Ok(DetectModbusRust { access_type: Some(AccessType::WRITE | AccessType::COILS), - address: Some(500..std::u16::MAX), + address: Some(500..u16::MAX), ..Default::default() }) ); @@ -541,7 +541,7 @@ mod test { Ok(DetectModbusRust { access_type: Some(AccessType::WRITE | AccessType::HOLDING), address: Some(100..100), - value: Some(std::u16::MIN..1000), + value: Some(u16::MIN..1000), ..Default::default() }) ); @@ -583,7 +583,7 @@ mod test { assert_eq!( parse_unit_id("unit <11"), Ok(DetectModbusRust { - unit_id: Some(std::u16::MIN..11), + unit_id: Some(u16::MIN..11), ..Default::default() }) ); @@ -649,7 +649,7 @@ mod test { &DetectModbusRust { access_type: Some(AccessType::WRITE | AccessType::HOLDING), address: Some(15..15), - value: Some(std::u16::MIN..4660), + value: Some(u16::MIN..4660), ..Default::default() } ), @@ -701,7 +701,7 @@ mod test { &DetectModbusRust { access_type: Some(AccessType::WRITE | AccessType::HOLDING), address: Some(15..15), - value: Some(4660..std::u16::MAX), + value: Some(4660..u16::MAX), ..Default::default() } ), @@ -714,7 +714,7 @@ mod test { &DetectModbusRust { access_type: Some(AccessType::WRITE | AccessType::HOLDING), address: Some(16..16), - value: Some(std::u16::MIN..22137), + value: Some(u16::MIN..22137), ..Default::default() } ), @@ -727,7 +727,7 @@ mod test { &DetectModbusRust { access_type: Some(AccessType::WRITE | AccessType::HOLDING), address: Some(16..16), - value: Some(std::u16::MIN..22137), + value: Some(u16::MIN..22137), ..Default::default() } ), @@ -779,7 +779,7 @@ mod test { &DetectModbusRust { access_type: Some(AccessType::WRITE | AccessType::HOLDING), address: Some(17..17), - value: Some(39611..std::u16::MAX), + value: Some(39611..u16::MAX), ..Default::default() } ), @@ -823,7 +823,7 @@ mod test { rs_modbus_inspect( &modbus.transactions[0], &DetectModbusRust { - unit_id: Some(11..std::u16::MAX), + unit_id: Some(11..u16::MAX), ..Default::default() } ), @@ -834,7 +834,7 @@ mod test { rs_modbus_inspect( &modbus.transactions[0], &DetectModbusRust { - unit_id: Some(std::u16::MIN..9), + unit_id: Some(u16::MIN..9), ..Default::default() } ), @@ -867,7 +867,7 @@ mod test { rs_modbus_inspect( &modbus.transactions[0], &DetectModbusRust { - unit_id: Some(9..std::u16::MAX), + unit_id: Some(9..u16::MAX), ..Default::default() } ), @@ -878,7 +878,7 @@ mod test { rs_modbus_inspect( &modbus.transactions[0], &DetectModbusRust { - unit_id: Some(std::u16::MIN..11), + unit_id: Some(u16::MIN..11), ..Default::default() } ), @@ -1206,7 +1206,7 @@ mod test { &modbus.transactions[5], &DetectModbusRust { access_type: Some(AccessType::READ | AccessType::INPUT), - address: Some(std::u16::MIN..9), + address: Some(u16::MIN..9), ..Default::default() } ), @@ -1230,7 +1230,7 @@ mod test { &modbus.transactions[5], &DetectModbusRust { access_type: Some(AccessType::READ | AccessType::INPUT), - address: Some(104..std::u16::MAX), + address: Some(104..u16::MAX), ..Default::default() } ), @@ -1266,7 +1266,7 @@ mod test { &modbus.transactions[5], &DetectModbusRust { access_type: Some(AccessType::READ | AccessType::INPUT), - address: Some(std::u16::MIN..10), + address: Some(u16::MIN..10), ..Default::default() } ), @@ -1290,7 +1290,7 @@ mod test { &modbus.transactions[5], &DetectModbusRust { access_type: Some(AccessType::READ | AccessType::INPUT), - address: Some(103..std::u16::MAX), + address: Some(103..u16::MAX), ..Default::default() } ), diff --git a/rust/src/mqtt/mqtt.rs b/rust/src/mqtt/mqtt.rs index dace75c8ecb5..b33069f7094c 100644 --- a/rust/src/mqtt/mqtt.rs +++ b/rust/src/mqtt/mqtt.rs @@ -33,7 +33,7 @@ use std::ffi::CString; // packet in a connection. Note that there is no risk of collision with a // parsed packet identifier because in the protocol these are only 16 bit // unsigned. -const MQTT_CONNECT_PKT_ID: u32 = std::u32::MAX; +const MQTT_CONNECT_PKT_ID: u32 = u32::MAX; // Maximum message length in bytes. If the length of a message exceeds // this value, it will be truncated. Default: 1MB. static mut MAX_MSG_LEN: u32 = 1048576; diff --git a/rust/src/smb/dcerpc.rs b/rust/src/smb/dcerpc.rs index b4c5749eac46..de6b8def73b3 100644 --- a/rust/src/smb/dcerpc.rs +++ b/rust/src/smb/dcerpc.rs @@ -455,10 +455,7 @@ pub fn smb_read_dcerpc_record(state: &mut SMBState, // msg_id 0 as this data crosses cmd/reply pairs let ehdr = SMBHashKeyHdrGuid::new(SMBCommonHdr::new(SMBHDR_TYPE_TRANS_FRAG, hdr.ssn_id, hdr.tree_id, 0_u64), guid.to_vec()); - let mut prevdata = match state.ssnguid2vec_map.remove(&ehdr) { - Some(s) => s, - None => Vec::new(), - }; + let mut prevdata = state.ssnguid2vec_map.remove(&ehdr).unwrap_or_default(); SCLogDebug!("indata {} prevdata {}", indata.len(), prevdata.len()); prevdata.extend_from_slice(indata); let data = prevdata; diff --git a/rust/src/smb/smb1.rs b/rust/src/smb/smb1.rs index ce1bb4b21297..b0d4e4d3d9c2 100644 --- a/rust/src/smb/smb1.rs +++ b/rust/src/smb/smb1.rs @@ -891,11 +891,8 @@ pub fn smb1_trans_response_record(state: &mut SMBState, r: &SmbRecord) SCLogDebug!("TRANS response {:?}", rd); // see if we have a stored fid - let fid = match state.ssn2vec_map.remove( - &SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID)) { - Some(f) => f, - None => Vec::new(), - }; + let fid = state.ssn2vec_map.remove( + &SMBCommonHdr::from1(r, SMBHDR_TYPE_GUID)).unwrap_or_default(); SCLogDebug!("FID {:?}", fid); let mut frankenfid = fid.to_vec(); diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index a2fe021b0276..98ed30da1cb5 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -679,13 +679,7 @@ pub fn smb2_response_record(state: &mut SMBState, r: &Smb2Record) /* search key-guid map */ let guid_key = SMBCommonHdr::new(SMBHDR_TYPE_GUID, r.session_id, r.tree_id, r.message_id); - let _guid_vec = match state.ssn2vec_map.remove(&guid_key) { - Some(p) => p, - None => { - SCLogDebug!("SMBv2 response: GUID NOT FOUND"); - Vec::new() - }, - }; + let _guid_vec = state.ssn2vec_map.remove(&guid_key).unwrap_or_default(); SCLogDebug!("SMBv2 write response for GUID {:?}", _guid_vec); } _ => { diff --git a/rust/src/snmp/detect.rs b/rust/src/snmp/detect.rs index bb4ffd12c3ba..7dee00a707b1 100644 --- a/rust/src/snmp/detect.rs +++ b/rust/src/snmp/detect.rs @@ -17,42 +17,251 @@ // written by Pierre Chifflier -use crate::snmp::snmp::SNMPTransaction; +use super::snmp::{SNMPTransaction, ALPROTO_SNMP}; +use crate::detect::uint::{ + rs_detect_u32_free, rs_detect_u32_match, rs_detect_u32_parse, DetectUintData, +}; +use crate::detect::{ + DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperBufferRegister, + DetectHelperGetData, DetectHelperKeywordRegister, DetectSignatureSetAppProto, SCSigTableElmt, + SigMatchAppendSMToList, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT, +}; +use std::os::raw::{c_int, c_void}; -#[no_mangle] -pub unsafe extern "C" fn rs_snmp_tx_get_version(tx: &mut SNMPTransaction, version: *mut u32) { - debug_assert!(tx.version != 0, "SNMP version is 0"); - *version = tx.version; +static mut G_SNMP_VERSION_KW_ID: c_int = 0; +static mut G_SNMP_VERSION_BUFFER_ID: c_int = 0; +static mut G_SNMP_PDUTYPE_KW_ID: c_int = 0; +static mut G_SNMP_PDUTYPE_BUFFER_ID: c_int = 0; +static mut G_SNMP_USM_BUFFER_ID: c_int = 0; +static mut G_SNMP_COMMUNITY_BUFFER_ID: c_int = 0; + +unsafe extern "C" fn snmp_detect_version_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 { + return -1; + } + let ctx = rs_detect_u32_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList(de, s, G_SNMP_VERSION_KW_ID, ctx, G_SNMP_VERSION_BUFFER_ID).is_null() + { + snmp_detect_version_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; } -#[no_mangle] -pub unsafe extern "C" fn rs_snmp_tx_get_community( - tx: &mut SNMPTransaction, buf: *mut *const u8, len: *mut u32, -) { - if let Some(ref c) = tx.community { - *buf = c.as_ptr(); - *len = c.len() as u32; +unsafe extern "C" fn snmp_detect_version_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, SNMPTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + return rs_detect_u32_match(tx.version, ctx); +} + +unsafe extern "C" fn snmp_detect_version_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u32_free(ctx); +} + +unsafe extern "C" fn snmp_detect_pdutype_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 { + return -1; } + let ctx = rs_detect_u32_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList(de, s, G_SNMP_PDUTYPE_KW_ID, ctx, G_SNMP_PDUTYPE_BUFFER_ID).is_null() + { + snmp_detect_pdutype_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; } -#[no_mangle] -pub unsafe extern "C" fn rs_snmp_tx_get_pdu_type(tx: &mut SNMPTransaction, pdu_type: *mut u32) { - match tx.info { - Some(ref info) => { - *pdu_type = info.pdu_type.0; - } - None => { - *pdu_type = 0xffffffff; - } +unsafe extern "C" fn snmp_detect_pdutype_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, SNMPTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(ref info) = tx.info { + let pdu_type = info.pdu_type.0; + return rs_detect_u32_match(pdu_type, ctx); + } + return 0; +} + +unsafe extern "C" fn snmp_detect_pdutype_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u32_free(ctx); +} + +pub unsafe extern "C" fn snmp_detect_usm_setup( + de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 { + return -1; + } + if DetectBufferSetActiveList(de, s, G_SNMP_USM_BUFFER_ID) < 0 { + return -1; } + return 0; } +pub unsafe extern "C" fn snmp_detect_usm_get( + tx: *const c_void, _flow_flags: u8, buffer: *mut *const u8, buffer_len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, SNMPTransaction); + if let Some(ref c) = tx.usm { + *buffer = c.as_ptr(); + *buffer_len = c.len() as u32; + return true; + } + return false; +} + +pub unsafe extern "C" fn snmp_detect_usm_get_data( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, +) -> *mut c_void { + return DetectHelperGetData( + de, + transforms, + flow, + flow_flags, + tx, + list_id, + snmp_detect_usm_get, + ); +} + +pub unsafe extern "C" fn snmp_detect_community_setup( + de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0 { + return -1; + } + if DetectBufferSetActiveList(de, s, G_SNMP_COMMUNITY_BUFFER_ID) < 0 { + return -1; + } + return 0; +} + +pub unsafe extern "C" fn snmp_detect_community_get( + tx: *const c_void, _flow_flags: u8, buffer: *mut *const u8, buffer_len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, SNMPTransaction); + if let Some(ref c) = tx.community { + *buffer = c.as_ptr(); + *buffer_len = c.len() as u32; + return true; + } + return false; +} + +pub unsafe extern "C" fn snmp_detect_community_get_data( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, +) -> *mut c_void { + return DetectHelperGetData( + de, + transforms, + flow, + flow_flags, + tx, + list_id, + snmp_detect_community_get, + ); +} #[no_mangle] -pub unsafe extern "C" fn rs_snmp_tx_get_usm( - tx: &mut SNMPTransaction, buf: *mut *const u8, len: *mut u32, -) { - if let Some(ref c) = tx.usm { - *buf = c.as_ptr(); - *len = c.len() as u32; +pub unsafe extern "C" fn ScDetectSNMPRegister() { + let kw = SCSigTableElmt { + name: b"snmp.version\0".as_ptr() as *const libc::c_char, + desc: b"match SNMP version\0".as_ptr() as *const libc::c_char, + url: b"/rules/snmp-keywords.html#snmp-version\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(snmp_detect_version_match), + Setup: snmp_detect_version_setup, + Free: Some(snmp_detect_version_free), + flags: 0, + }; + unsafe { + G_SNMP_VERSION_KW_ID = DetectHelperKeywordRegister(&kw); + G_SNMP_VERSION_BUFFER_ID = DetectHelperBufferRegister( + b"snmp.version\0".as_ptr() as *const libc::c_char, + ALPROTO_SNMP, + true, + true, + ); + } + + let kw = SCSigTableElmt { + name: b"snmp.pdu_type\0".as_ptr() as *const libc::c_char, + desc: b"match SNMP PDU type\0".as_ptr() as *const libc::c_char, + url: b"/rules/snmp-keywords.html#snmp-pdu-type\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(snmp_detect_pdutype_match), + Setup: snmp_detect_pdutype_setup, + Free: Some(snmp_detect_pdutype_free), + flags: 0, + }; + unsafe { + G_SNMP_PDUTYPE_KW_ID = DetectHelperKeywordRegister(&kw); + G_SNMP_PDUTYPE_BUFFER_ID = DetectHelperBufferRegister( + b"snmp.pdu_type\0".as_ptr() as *const libc::c_char, + ALPROTO_SNMP, + true, + true, + ); + } + + let kw = SCSigTableElmt { + name: b"snmp.usm\0".as_ptr() as *const libc::c_char, + desc: b"SNMP content modifier to match on the SNMP usm\0".as_ptr() as *const libc::c_char, + url: b"/rules/snmp-keywords.html#snmp-usm\0".as_ptr() as *const libc::c_char, + Setup: snmp_detect_usm_setup, + flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, + AppLayerTxMatch: None, + Free: None, + }; + unsafe { + let _g_snmp_usm_kw_id = DetectHelperKeywordRegister(&kw); + G_SNMP_USM_BUFFER_ID = DetectHelperBufferMpmRegister( + b"snmp.usm\0".as_ptr() as *const libc::c_char, + b"SNMP USM\0".as_ptr() as *const libc::c_char, + ALPROTO_SNMP, + true, + true, + snmp_detect_usm_get_data, + ); + } + + let kw = SCSigTableElmt { + name: b"snmp.community\0".as_ptr() as *const libc::c_char, + desc: b"SNMP content modifier to match on the SNMP community\0".as_ptr() + as *const libc::c_char, + url: b"/rules/snmp-keywords.html#snmp-community\0".as_ptr() as *const libc::c_char, + Setup: snmp_detect_community_setup, + flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, + AppLayerTxMatch: None, + Free: None, + }; + unsafe { + let _g_snmp_community_kw_id = DetectHelperKeywordRegister(&kw); + G_SNMP_COMMUNITY_BUFFER_ID = DetectHelperBufferMpmRegister( + b"snmp.community\0".as_ptr() as *const libc::c_char, + b"SNMP Community identifier\0".as_ptr() as *const libc::c_char, + ALPROTO_SNMP, + true, + true, + snmp_detect_community_get_data, + ); } } diff --git a/rust/src/snmp/snmp.rs b/rust/src/snmp/snmp.rs index 3e68f70b08e6..b4bb6321a3ec 100644 --- a/rust/src/snmp/snmp.rs +++ b/rust/src/snmp/snmp.rs @@ -322,7 +322,7 @@ pub extern "C" fn rs_snmp_tx_get_alstate_progress(_tx: *mut std::os::raw::c_void 1 } -static mut ALPROTO_SNMP : AppProto = ALPROTO_UNKNOWN; +pub(super) static mut ALPROTO_SNMP : AppProto = ALPROTO_UNKNOWN; // Read PDU sequence and extract version, if similar to SNMP definition fn parse_pdu_envelope_version(i:&[u8]) -> IResult<&[u8],u32> { diff --git a/rust/src/websocket/detect.rs b/rust/src/websocket/detect.rs index 44737ae6f03d..b4457125a633 100644 --- a/rust/src/websocket/detect.rs +++ b/rust/src/websocket/detect.rs @@ -15,9 +15,15 @@ * 02110-1301, USA. */ -use super::websocket::WebSocketTransaction; +use super::websocket::{WebSocketTransaction, ALPROTO_WEBSOCKET}; use crate::detect::uint::{ - detect_parse_uint, detect_parse_uint_enum, DetectUintData, DetectUintMode, + detect_parse_uint, detect_parse_uint_enum, rs_detect_u32_free, rs_detect_u32_match, + rs_detect_u32_parse, rs_detect_u8_free, rs_detect_u8_match, DetectUintData, DetectUintMode, +}; +use crate::detect::{ + DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperBufferRegister, + DetectHelperGetData, DetectHelperKeywordRegister, DetectSignatureSetAppProto, SCSigTableElmt, + SigMatchAppendSMToList, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT, }; use crate::websocket::parser::WebSocketOpcode; @@ -28,39 +34,9 @@ use nom7::multi::many1; use nom7::IResult; use std::ffi::CStr; +use std::os::raw::{c_int, c_void}; -#[no_mangle] -pub unsafe extern "C" fn SCWebSocketGetOpcode(tx: &mut WebSocketTransaction) -> u8 { - return tx.pdu.opcode; -} - -#[no_mangle] -pub unsafe extern "C" fn SCWebSocketGetFlags(tx: &mut WebSocketTransaction) -> u8 { - return tx.pdu.flags; -} - -#[no_mangle] -pub unsafe extern "C" fn SCWebSocketGetPayload( - tx: &WebSocketTransaction, buffer: *mut *const u8, buffer_len: *mut u32, -) -> bool { - *buffer = tx.pdu.payload.as_ptr(); - *buffer_len = tx.pdu.payload.len() as u32; - return true; -} - -#[no_mangle] -pub unsafe extern "C" fn SCWebSocketGetMask( - tx: &mut WebSocketTransaction, value: *mut u32, -) -> bool { - if let Some(xorkey) = tx.pdu.mask { - *value = xorkey; - return true; - } - return false; -} - -#[no_mangle] -pub unsafe extern "C" fn SCWebSocketParseOpcode( +unsafe extern "C" fn websocket_parse_opcode( ustr: *const std::os::raw::c_char, ) -> *mut DetectUintData { let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe @@ -120,8 +96,7 @@ fn parse_flags(s: &str) -> Option> { return None; } -#[no_mangle] -pub unsafe extern "C" fn SCWebSocketParseFlags( +unsafe extern "C" fn websocket_parse_flags( ustr: *const std::os::raw::c_char, ) -> *mut DetectUintData { let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe @@ -133,3 +108,248 @@ pub unsafe extern "C" fn SCWebSocketParseFlags( } return std::ptr::null_mut(); } + +static mut G_WEBSOCKET_OPCODE_KW_ID: c_int = 0; +static mut G_WEBSOCKET_OPCODE_BUFFER_ID: c_int = 0; +static mut G_WEBSOCKET_MASK_KW_ID: c_int = 0; +static mut G_WEBSOCKET_MASK_BUFFER_ID: c_int = 0; +static mut G_WEBSOCKET_FLAGS_KW_ID: c_int = 0; +static mut G_WEBSOCKET_FLAGS_BUFFER_ID: c_int = 0; +static mut G_WEBSOCKET_PAYLOAD_BUFFER_ID: c_int = 0; + +unsafe extern "C" fn websocket_detect_opcode_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0 { + return -1; + } + let ctx = websocket_parse_opcode(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_WEBSOCKET_OPCODE_KW_ID, + ctx, + G_WEBSOCKET_OPCODE_BUFFER_ID, + ) + .is_null() + { + websocket_detect_opcode_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn websocket_detect_opcode_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, WebSocketTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + return rs_detect_u8_match(tx.pdu.opcode, ctx); +} + +unsafe extern "C" fn websocket_detect_opcode_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u8_free(ctx); +} + +unsafe extern "C" fn websocket_detect_mask_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0 { + return -1; + } + let ctx = rs_detect_u32_parse(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_WEBSOCKET_MASK_KW_ID, + ctx, + G_WEBSOCKET_MASK_BUFFER_ID, + ) + .is_null() + { + websocket_detect_mask_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn websocket_detect_mask_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, WebSocketTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + if let Some(xorkey) = tx.pdu.mask { + return rs_detect_u32_match(xorkey, ctx); + } + return 0; +} + +unsafe extern "C" fn websocket_detect_mask_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u32_free(ctx); +} + +unsafe extern "C" fn websocket_detect_flags_setup( + de: *mut c_void, s: *mut c_void, raw: *const libc::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0 { + return -1; + } + let ctx = websocket_parse_flags(raw) as *mut c_void; + if ctx.is_null() { + return -1; + } + if SigMatchAppendSMToList( + de, + s, + G_WEBSOCKET_FLAGS_KW_ID, + ctx, + G_WEBSOCKET_FLAGS_BUFFER_ID, + ) + .is_null() + { + websocket_detect_flags_free(std::ptr::null_mut(), ctx); + return -1; + } + return 0; +} + +unsafe extern "C" fn websocket_detect_flags_match( + _de: *mut c_void, _f: *mut c_void, _flags: u8, _state: *mut c_void, tx: *mut c_void, + _sig: *const c_void, ctx: *const c_void, +) -> c_int { + let tx = cast_pointer!(tx, WebSocketTransaction); + let ctx = cast_pointer!(ctx, DetectUintData); + return rs_detect_u8_match(tx.pdu.flags, ctx); +} + +unsafe extern "C" fn websocket_detect_flags_free(_de: *mut c_void, ctx: *mut c_void) { + // Just unbox... + let ctx = cast_pointer!(ctx, DetectUintData); + rs_detect_u8_free(ctx); +} + +pub unsafe extern "C" fn websocket_detect_payload_setup( + de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0 { + return -1; + } + if DetectBufferSetActiveList(de, s, G_WEBSOCKET_PAYLOAD_BUFFER_ID) < 0 { + return -1; + } + return 0; +} + +pub unsafe extern "C" fn websocket_detect_payload_get( + tx: *const c_void, _flow_flags: u8, buffer: *mut *const u8, buffer_len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, WebSocketTransaction); + *buffer = tx.pdu.payload.as_ptr(); + *buffer_len = tx.pdu.payload.len() as u32; + return true; +} + +pub unsafe extern "C" fn websocket_detect_payload_get_data( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, +) -> *mut c_void { + return DetectHelperGetData( + de, + transforms, + flow, + flow_flags, + tx, + list_id, + websocket_detect_payload_get, + ); +} + +#[no_mangle] +pub unsafe extern "C" fn ScDetectWebsocketRegister() { + let kw = SCSigTableElmt { + name: b"websocket.opcode\0".as_ptr() as *const libc::c_char, + desc: b"match WebSocket opcode\0".as_ptr() as *const libc::c_char, + url: b"/rules/websocket-keywords.html#websocket-opcode\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(websocket_detect_opcode_match), + Setup: websocket_detect_opcode_setup, + Free: Some(websocket_detect_opcode_free), + flags: 0, + }; + unsafe { + G_WEBSOCKET_OPCODE_KW_ID = DetectHelperKeywordRegister(&kw); + G_WEBSOCKET_OPCODE_BUFFER_ID = DetectHelperBufferRegister( + b"websocket.opcode\0".as_ptr() as *const libc::c_char, + ALPROTO_WEBSOCKET, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"websocket.mask\0".as_ptr() as *const libc::c_char, + desc: b"match WebSocket mask\0".as_ptr() as *const libc::c_char, + url: b"/rules/websocket-keywords.html#websocket-mask\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(websocket_detect_mask_match), + Setup: websocket_detect_mask_setup, + Free: Some(websocket_detect_mask_free), + flags: 0, + }; + unsafe { + G_WEBSOCKET_MASK_KW_ID = DetectHelperKeywordRegister(&kw); + G_WEBSOCKET_MASK_BUFFER_ID = DetectHelperBufferRegister( + b"websocket.mask\0".as_ptr() as *const libc::c_char, + ALPROTO_WEBSOCKET, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"websocket.flags\0".as_ptr() as *const libc::c_char, + desc: b"match WebSocket flags\0".as_ptr() as *const libc::c_char, + url: b"/rules/websocket-keywords.html#websocket-flags\0".as_ptr() as *const libc::c_char, + AppLayerTxMatch: Some(websocket_detect_flags_match), + Setup: websocket_detect_flags_setup, + Free: Some(websocket_detect_flags_free), + flags: 0, + }; + unsafe { + G_WEBSOCKET_FLAGS_KW_ID = DetectHelperKeywordRegister(&kw); + G_WEBSOCKET_FLAGS_BUFFER_ID = DetectHelperBufferRegister( + b"websocket.flags\0".as_ptr() as *const libc::c_char, + ALPROTO_WEBSOCKET, + true, + true, + ); + } + let kw = SCSigTableElmt { + name: b"websocket.payload\0".as_ptr() as *const libc::c_char, + desc: b"match WebSocket payload\0".as_ptr() as *const libc::c_char, + url: b"/rules/websocket-keywords.html#websocket-payload\0".as_ptr() as *const libc::c_char, + Setup: websocket_detect_payload_setup, + flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, + AppLayerTxMatch: None, + Free: None, + }; + unsafe { + let _g_ws_payload_kw_id = DetectHelperKeywordRegister(&kw); + G_WEBSOCKET_PAYLOAD_BUFFER_ID = DetectHelperBufferMpmRegister( + b"websocket.payload\0".as_ptr() as *const libc::c_char, + b"WebSocket payload\0".as_ptr() as *const libc::c_char, + ALPROTO_WEBSOCKET, + true, + true, + websocket_detect_payload_get_data, + ); + } +} diff --git a/rust/src/websocket/websocket.rs b/rust/src/websocket/websocket.rs index c5e1720b31df..26747525fbb2 100644 --- a/rust/src/websocket/websocket.rs +++ b/rust/src/websocket/websocket.rs @@ -32,7 +32,7 @@ use std::ffi::CString; use std::io::Read; use std::os::raw::{c_char, c_int, c_void}; -static mut ALPROTO_WEBSOCKET: AppProto = ALPROTO_UNKNOWN; +pub(super) static mut ALPROTO_WEBSOCKET: AppProto = ALPROTO_UNKNOWN; static mut WEBSOCKET_MAX_PAYLOAD_SIZE: u32 = 0xFFFF; diff --git a/scripts/docs-almalinux9-minimal-build.sh b/scripts/docs-almalinux9-minimal-build.sh new file mode 100755 index 000000000000..2b569ff72dc9 --- /dev/null +++ b/scripts/docs-almalinux9-minimal-build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Serves for RPM-based docs and is verified by Github Actions + +# install-guide-documentation tag start: Minimal RPM-based dependencies +sudo dnf install -y rustc cargo cbindgen +sudo dnf install -y gcc gcc-c++ jansson-devel libpcap-devel \ + libyaml-devel make pcre2-devel zlib-devel +# install-guide-documentation tag end: Minimal RPM-based dependencies \ No newline at end of file diff --git a/scripts/docs-ubuntu-debian-minimal-build.sh b/scripts/docs-ubuntu-debian-minimal-build.sh new file mode 100755 index 000000000000..41d163a94734 --- /dev/null +++ b/scripts/docs-ubuntu-debian-minimal-build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Serves for Ubuntu/Debian docs and is verified by Github Actions + +# install-guide-documentation tag start: Minimal dependencies +sudo apt -y install autoconf automake build-essential cargo \ + cbindgen libjansson-dev libpcap-dev libpcre2-dev libtool \ + libyaml-dev make pkg-config rustc zlib1g-dev +# install-guide-documentation tag end: Minimal dependencies \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am index 4ccc691802d2..5b83d60cfd42 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -98,7 +98,6 @@ noinst_HEADERS = \ detect-bytejump.h \ detect-bytemath.h \ detect-bytetest.h \ - detect-cipservice.h \ detect-classtype.h \ detect-config.h \ detect-content.h \ @@ -131,6 +130,7 @@ noinst_HEADERS = \ detect-engine-file.h \ detect-engine-frame.h \ detect-engine.h \ + detect-engine-helper.h \ detect-engine-iponly.h \ detect-engine-loader.h \ detect-engine-mpm.h \ @@ -147,24 +147,6 @@ noinst_HEADERS = \ detect-engine-tag.h \ detect-engine-threshold.h \ detect-engine-uint.h \ - detect-enip-command.h \ - detect-enip-status.h \ - detect-enip-product-name.h \ - detect-enip-protocol-version.h \ - detect-enip-cip-attribute.h \ - detect-enip-cip-instance.h \ - detect-enip-cip-class.h \ - detect-enip-cip-extendedstatus.h \ - detect-enip-cip-status.h \ - detect-enip-service-name.h \ - detect-enip-capabilities.h \ - detect-enip-revision.h \ - detect-enip-identity-status.h \ - detect-enip-state.h \ - detect-enip-serial.h \ - detect-enip-product-code.h \ - detect-enip-device-type.h \ - detect-enip-vendor-id.h \ detect-fast-pattern.h \ detect-file-data.h \ detect-file-hash-common.h \ @@ -309,13 +291,6 @@ noinst_HEADERS = \ detect-smb-ntlmssp.h \ detect-smb-share.h \ detect-smb-version.h \ - detect-snmp-community.h \ - detect-snmp-pdu_type.h \ - detect-snmp-usm.h \ - detect-snmp-version.h \ - detect-dhcp-leasetime.h \ - detect-dhcp-rebinding-time.h \ - detect-dhcp-renewal-time.h \ detect-ssh-hassh.h \ detect-ssh-hassh-server.h \ detect-ssh-hassh-server-string.h \ @@ -373,7 +348,6 @@ noinst_HEADERS = \ detect-urilen.h \ detect-within.h \ detect-xbits.h \ - detect-websocket.h \ device-storage.h \ feature.h \ flow-bit.h \ @@ -725,7 +699,6 @@ libsuricata_c_a_SOURCES = \ detect-bytemath.c \ detect-bytetest.c \ detect.c \ - detect-cipservice.c \ detect-classtype.c \ detect-config.c \ detect-content.c \ @@ -758,6 +731,7 @@ libsuricata_c_a_SOURCES = \ detect-engine-event.c \ detect-engine-file.c \ detect-engine-frame.c \ + detect-engine-helper.c \ detect-engine-iponly.c \ detect-engine-loader.c \ detect-engine-mpm.c \ @@ -774,24 +748,6 @@ libsuricata_c_a_SOURCES = \ detect-engine-tag.c \ detect-engine-threshold.c \ detect-engine-uint.c \ - detect-enip-command.c \ - detect-enip-status.c \ - detect-enip-product-name.c \ - detect-enip-protocol-version.c \ - detect-enip-cip-attribute.c \ - detect-enip-cip-instance.c \ - detect-enip-cip-class.c \ - detect-enip-cip-extendedstatus.c \ - detect-enip-cip-status.c \ - detect-enip-service-name.c \ - detect-enip-capabilities.c \ - detect-enip-revision.c \ - detect-enip-identity-status.c \ - detect-enip-state.c \ - detect-enip-serial.c \ - detect-enip-product-code.c \ - detect-enip-device-type.c \ - detect-enip-vendor-id.c \ detect-fast-pattern.c \ detect-file-data.c \ detect-file-hash-common.c \ @@ -934,13 +890,6 @@ libsuricata_c_a_SOURCES = \ detect-smb-ntlmssp.c \ detect-smb-share.c \ detect-smb-version.c \ - detect-snmp-community.c \ - detect-snmp-pdu_type.c \ - detect-snmp-usm.c \ - detect-snmp-version.c \ - detect-dhcp-leasetime.c \ - detect-dhcp-rebinding-time.c \ - detect-dhcp-renewal-time.c \ detect-ssh-hassh.c \ detect-ssh-hassh-server.c \ detect-ssh-hassh-server-string.c \ @@ -998,7 +947,6 @@ libsuricata_c_a_SOURCES = \ detect-urilen.c \ detect-within.c \ detect-xbits.c \ - detect-websocket.c \ device-storage.c \ feature.c \ flow-bit.c \ @@ -1261,8 +1209,6 @@ EXTRA_DIST = \ tests/detect-http2.c \ tests/detect-icmpv6-mtu.c \ tests/detect-icmpv6hdr.c \ - tests/detect-snmp-pdu_type.c \ - tests/detect-snmp-version.c \ tests/detect-template.c \ tests/detect-transform-pcrexform.c \ tests/detect-transform-xor.c \ @@ -1320,7 +1266,13 @@ suricata_SOURCES = main.c # the library search path. suricata_LDFLAGS = $(all_libraries) ${SECLDFLAGS} -suricata_LDADD = libsuricata_c.a $(RUST_SURICATA_LIB) $(HTP_LDADD) $(RUST_LDADD) +# rust library depends also on c +if LINKER_SUPPORTS_GROUP +LDADD_GENERIC = "-Wl,--start-group,libsuricata_c.a,$(RUST_SURICATA_LIB),--end-group" $(HTP_LDADD) $(RUST_LDADD) +else +LDADD_GENERIC = libsuricata_c.a $(RUST_SURICATA_LIB) libsuricata_c.a $(RUST_SURICATA_LIB) $(HTP_LDADD) $(RUST_LDADD) +endif +suricata_LDADD = $(LDADD_GENERIC) suricata_DEPENDENCIES = libsuricata_c.a $(RUST_SURICATA_LIB) if BUILD_SHARED_LIBRARY @@ -1356,7 +1308,7 @@ uninstall-local: if BUILD_FUZZTARGETS LDFLAGS_FUZZ = $(all_libraries) $(SECLDFLAGS) -LDADD_FUZZ = libsuricata_c.a $(RUST_SURICATA_LIB) $(HTP_LDADD) $(RUST_LDADD) +LDADD_FUZZ = $(LDADD_GENERIC) fuzz_applayerprotodetectgetproto_SOURCES = tests/fuzz/fuzz_applayerprotodetectgetproto.c fuzz_applayerprotodetectgetproto_LDFLAGS = $(LDFLAGS_FUZZ) diff --git a/src/detect-cipservice.c b/src/detect-cipservice.c deleted file mode 100644 index 69aad06b3eae..000000000000 --- a/src/detect-cipservice.c +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (C) 2015 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Kevin Wong - * - * Set up ENIP Command and CIP Service rule parsing and entry point for matching - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "rust.h" - -#include "detect-cipservice.h" - -/* - * CIP SERVICE CODE - */ - -static int g_cip_buffer_id = 0; - -/** - * \brief this function will free memory associated with DetectCipServiceData - * - * \param ptr pointer to DetectCipServiceData - */ -static void DetectCipServiceFree(DetectEngineCtx *de_ctx, void *ptr) -{ - SCEnipCipServiceFree(ptr); -} - -/** - * \brief this function is used to a cipserviced the parsed cip_service data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided cip_service options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectCipServiceSetup(DetectEngineCtx *de_ctx, Signature *s, - const char *rulestr) -{ - SCEnter(); - - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - void *cipserviced = SCEnipParseCipService(rulestr); - if (cipserviced == NULL) - return -1; - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_CIPSERVICE, (SigMatchCtx *)cipserviced, - g_cip_buffer_id) == NULL) { - DetectCipServiceFree(de_ctx, cipserviced); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip command type rule option on a transaction with those - * passed via enip_command: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectCipServiceMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - return SCEnipTxHasCipService(txv, flags, ctx); -} - -/** - * \brief Registration function for cip_service: keyword - */ -void DetectCipServiceRegister(void) -{ - SCEnter(); - sigmatch_table[DETECT_CIPSERVICE].name = "cip_service"; // rule keyword - sigmatch_table[DETECT_CIPSERVICE].desc = - "match on CIP Service, and optionnally class and attribute"; - sigmatch_table[DETECT_CIPSERVICE].url = "/rules/enip-keyword.html#cip_service"; - sigmatch_table[DETECT_CIPSERVICE].Match = NULL; - sigmatch_table[DETECT_CIPSERVICE].AppLayerTxMatch = DetectCipServiceMatch; - sigmatch_table[DETECT_CIPSERVICE].Setup = DetectCipServiceSetup; - sigmatch_table[DETECT_CIPSERVICE].Free = DetectCipServiceFree; - - DetectAppLayerInspectEngineRegister( - "cip", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister( - "cip", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL); - - g_cip_buffer_id = DetectBufferTypeGetByName("cip"); - - SCReturn; -} diff --git a/src/detect-cipservice.h b/src/detect-cipservice.h deleted file mode 100644 index f60b84a2b020..000000000000 --- a/src/detect-cipservice.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2015-2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Kevin Wong - */ - -#ifndef SURICATA_DETECT_CIPSERVICE_H -#define SURICATA_DETECT_CIPSERVICE_H - -void DetectCipServiceRegister(void); - -#endif /* SURICATA_DETECT_CIPSERVICE_H */ diff --git a/src/detect-dhcp-leasetime.c b/src/detect-dhcp-leasetime.c deleted file mode 100644 index f86d645dc633..000000000000 --- a/src/detect-dhcp-leasetime.c +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (C) 2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include "suricata-common.h" -#include "rust.h" -#include "detect-dhcp-leasetime.h" -#include "detect-engine.h" -#include "detect-engine-mpm.h" -#include "detect-engine-prefilter.h" -#include "detect-engine-uint.h" -#include "detect-parse.h" - -static int g_buffer_id = 0; - -/** - * \internal - * \brief Function to match leasetime of a TX - * - * \param t Pointer to thread vars. - * \param det_ctx Pointer to the pattern matcher thread. - * \param f Pointer to the current flow. - * \param flags Flags. - * \param state App layer state. - * \param s Pointer to the Signature. - * \param m Pointer to the sigmatch that we will cast into - * DetectU64Data. - * - * \retval 0 no match. - * \retval 1 match. - */ -static int DetectDHCPLeaseTimeMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) -{ - SCEnter(); - - uint64_t leasetime; - if (rs_dhcp_tx_get_leasetime(txv, &leasetime)) { - const DetectU64Data *dd = (const DetectU64Data *)ctx; - if (DetectU64Match(leasetime, dd)) { - SCReturnInt(1); - } - } - SCReturnInt(0); -} - -/** - * \internal - * \brief Function to free memory associated with DetectU64Data. - * - * \param de_ptr Pointer to DetectU64Data. - */ -static void DetectDHCPLeaseTimeFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u64_free(ptr); -} - -/** - * \brief Function to add the parsed dhcp leasetime field into the current signature. - * - * \param de_ctx Pointer to the Detection Engine Context. - * \param s Pointer to the Current Signature. - * \param rawstr Pointer to the user provided flags options. - * \param type Defines if this is notBefore or notAfter. - * - * \retval 0 on Success. - * \retval -1 on Failure. - */ -static int DetectDHCPLeaseTimeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_DHCP) != 0) - return -1; - - DetectU64Data *dd = DetectU64Parse(rawstr); - if (dd == NULL) { - SCLogError("Parsing \'%s\' failed for %s", rawstr, - sigmatch_table[DETECT_AL_DHCP_LEASETIME].name); - return -1; - } - - /* okay so far so good, lets get this into a SigMatch - * and put it in the Signature. */ - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_AL_DHCP_LEASETIME, (SigMatchCtx *)dd, g_buffer_id) == NULL) { - goto error; - } - return 0; - -error: - DetectDHCPLeaseTimeFree(de_ctx, dd); - return -1; -} - -/** - * \brief Registration function for dhcp.procedure keyword. - */ -void DetectDHCPLeaseTimeRegister(void) -{ - sigmatch_table[DETECT_AL_DHCP_LEASETIME].name = "dhcp.leasetime"; - sigmatch_table[DETECT_AL_DHCP_LEASETIME].desc = "match DHCP leasetime"; - sigmatch_table[DETECT_AL_DHCP_LEASETIME].url = "/rules/dhcp-keywords.html#dhcp-leasetime"; - sigmatch_table[DETECT_AL_DHCP_LEASETIME].AppLayerTxMatch = DetectDHCPLeaseTimeMatch; - sigmatch_table[DETECT_AL_DHCP_LEASETIME].Setup = DetectDHCPLeaseTimeSetup; - sigmatch_table[DETECT_AL_DHCP_LEASETIME].Free = DetectDHCPLeaseTimeFree; - - DetectAppLayerInspectEngineRegister("dhcp.leasetime", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - - DetectAppLayerInspectEngineRegister("dhcp.leasetime", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_buffer_id = DetectBufferTypeGetByName("dhcp.leasetime"); -} diff --git a/src/detect-dhcp-leasetime.h b/src/detect-dhcp-leasetime.h deleted file mode 100644 index 53b1f42ac73d..000000000000 --- a/src/detect-dhcp-leasetime.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#ifndef SURICATA_DETECT_DHCP_LEASETIME_H -#define SURICATA_DETECT_DHCP_LEASETIME_H - -void DetectDHCPLeaseTimeRegister(void); - -#endif /* SURICATA_DETECT_DHCP_LEASETIME_H */ diff --git a/src/detect-dhcp-rebinding-time.c b/src/detect-dhcp-rebinding-time.c deleted file mode 100644 index 737d332841b7..000000000000 --- a/src/detect-dhcp-rebinding-time.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include "suricata-common.h" -#include "rust.h" -#include "detect-dhcp-rebinding-time.h" -#include "detect-engine.h" -#include "detect-engine-mpm.h" -#include "detect-engine-prefilter.h" -#include "detect-engine-uint.h" -#include "detect-parse.h" - -static int g_buffer_id = 0; - -/** - * \internal - * \brief Function to match rebinding time of a TX - * - * \param t Pointer to thread vars. - * \param det_ctx Pointer to the pattern matcher thread. - * \param f Pointer to the current flow. - * \param flags Flags. - * \param state App layer state. - * \param s Pointer to the Signature. - * \param m Pointer to the sigmatch that we will cast into - * DetectU64Data. - * - * \retval 0 no match. - * \retval 1 match. - */ -static int DetectDHCPRebindingTimeMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) -{ - SCEnter(); - - uint64_t res; - if (rs_dhcp_tx_get_rebinding_time(txv, &res)) { - const DetectU64Data *dd = (const DetectU64Data *)ctx; - if (DetectU64Match(res, dd)) { - SCReturnInt(1); - } - } - SCReturnInt(0); -} - -/** - * \internal - * \brief Function to free memory associated with DetectU64Data. - * - * \param de_ptr Pointer to DetectU64Data. - */ -static void DetectDHCPRebindingTimeFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u64_free(ptr); -} - -/** - * \brief Function to add the parsed dhcp rebinding time field into the current signature. - * - * \param de_ctx Pointer to the Detection Engine Context. - * \param s Pointer to the Current Signature. - * \param rawstr Pointer to the user provided flags options. - * \param type Defines if this is notBefore or notAfter. - * - * \retval 0 on Success. - * \retval -1 on Failure. - */ -static int DetectDHCPRebindingTimeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_DHCP) != 0) - return -1; - - DetectU64Data *dd = DetectU64Parse(rawstr); - if (dd == NULL) { - SCLogError("Parsing \'%s\' failed for %s", rawstr, - sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].name); - return -1; - } - - /* okay so far so good, lets get this into a SigMatch - * and put it in the Signature. */ - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_AL_DHCP_REBINDING_TIME, (SigMatchCtx *)dd, g_buffer_id) == NULL) { - goto error; - } - return 0; - -error: - DetectDHCPRebindingTimeFree(de_ctx, dd); - return -1; -} - -/** - * \brief Registration function for dhcp.procedure keyword. - */ -void DetectDHCPRebindingTimeRegister(void) -{ - sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].name = "dhcp.rebinding_time"; - sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].desc = "match DHCP rebinding time"; - sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].url = - "/rules/dhcp-keywords.html#dhcp-rebinding-time"; - sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].AppLayerTxMatch = DetectDHCPRebindingTimeMatch; - sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].Setup = DetectDHCPRebindingTimeSetup; - sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].Free = DetectDHCPRebindingTimeFree; - - DetectAppLayerInspectEngineRegister("dhcp.rebinding-time", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - - DetectAppLayerInspectEngineRegister("dhcp.rebinding-time", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_buffer_id = DetectBufferTypeGetByName("dhcp.rebinding-time"); -} diff --git a/src/detect-dhcp-rebinding-time.h b/src/detect-dhcp-rebinding-time.h deleted file mode 100644 index b14f0af66139..000000000000 --- a/src/detect-dhcp-rebinding-time.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#ifndef SURICATA_DETECT_DHCP_REBINDING_TIME_H -#define SURICATA_DETECT_DHCP_REBINDING_TIME_H - -void DetectDHCPRebindingTimeRegister(void); - -#endif /* SURICATA_DETECT_DHCP_REBINDING_TIME_H */ diff --git a/src/detect-dhcp-renewal-time.c b/src/detect-dhcp-renewal-time.c deleted file mode 100644 index d991fa1d2a4f..000000000000 --- a/src/detect-dhcp-renewal-time.c +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (C) 2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include "suricata-common.h" -#include "rust.h" -#include "detect-dhcp-renewal-time.h" -#include "detect-engine.h" -#include "detect-engine-mpm.h" -#include "detect-engine-prefilter.h" -#include "detect-engine-uint.h" -#include "detect-parse.h" - -static int g_buffer_id = 0; - -/** - * \internal - * \brief Function to match renewal time of a TX - * - * \param t Pointer to thread vars. - * \param det_ctx Pointer to the pattern matcher thread. - * \param f Pointer to the current flow. - * \param flags Flags. - * \param state App layer state. - * \param s Pointer to the Signature. - * \param m Pointer to the sigmatch that we will cast into - * DetectU64Data. - * - * \retval 0 no match. - * \retval 1 match. - */ -static int DetectDHCPRenewalTimeMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) -{ - SCEnter(); - - uint64_t res; - if (rs_dhcp_tx_get_renewal_time(txv, &res)) { - const DetectU64Data *dd = (const DetectU64Data *)ctx; - if (DetectU64Match(res, dd)) { - SCReturnInt(1); - } - } - SCReturnInt(0); -} - -/** - * \internal - * \brief Function to free memory associated with DetectU64Data. - * - * \param de_ptr Pointer to DetectU64Data. - */ -static void DetectDHCPRenewalTimeFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u64_free(ptr); -} - -/** - * \brief Function to add the parsed dhcp renewal time field into the current signature. - * - * \param de_ctx Pointer to the Detection Engine Context. - * \param s Pointer to the Current Signature. - * \param rawstr Pointer to the user provided flags options. - * \param type Defines if this is notBefore or notAfter. - * - * \retval 0 on Success. - * \retval -1 on Failure. - */ -static int DetectDHCPRenewalTimeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_DHCP) != 0) - return -1; - - DetectU64Data *dd = DetectU64Parse(rawstr); - if (dd == NULL) { - SCLogError("Parsing \'%s\' failed for %s", rawstr, - sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].name); - return -1; - } - - /* okay so far so good, lets get this into a SigMatch - * and put it in the Signature. */ - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_AL_DHCP_RENEWAL_TIME, (SigMatchCtx *)dd, g_buffer_id) == NULL) { - goto error; - } - return 0; - -error: - DetectDHCPRenewalTimeFree(de_ctx, dd); - return -1; -} - -/** - * \brief Registration function for dhcp.procedure keyword. - */ -void DetectDHCPRenewalTimeRegister(void) -{ - sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].name = "dhcp.renewal_time"; - sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].desc = "match DHCP renewal time"; - sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].url = "/rules/dhcp-keywords.html#dhcp-renewal-time"; - sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].AppLayerTxMatch = DetectDHCPRenewalTimeMatch; - sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].Setup = DetectDHCPRenewalTimeSetup; - sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].Free = DetectDHCPRenewalTimeFree; - - DetectAppLayerInspectEngineRegister("dhcp.renewal-time", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - - DetectAppLayerInspectEngineRegister("dhcp.renewal-time", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_buffer_id = DetectBufferTypeGetByName("dhcp.renewal-time"); -} diff --git a/src/detect-dhcp-renewal-time.h b/src/detect-dhcp-renewal-time.h deleted file mode 100644 index 06d64c5560b3..000000000000 --- a/src/detect-dhcp-renewal-time.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#ifndef SURICATA_DETECT_DHCP_RENEWAL_TIME_H -#define SURICATA_DETECT_DHCP_RENEWAL_TIME_H - -void DetectDHCPRenewalTimeRegister(void); - -#endif /* SURICATA_DETECT_DHCP_RENEWAL_TIME_H */ diff --git a/src/detect-engine-helper.c b/src/detect-engine-helper.c new file mode 100644 index 000000000000..0b7c9ccb2077 --- /dev/null +++ b/src/detect-engine-helper.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2023 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Philippe Antoine + * + */ + +#include "suricata-common.h" +#include "detect-engine.h" +#include "detect-engine-helper.h" +#include "detect-engine-mpm.h" +#include "detect-engine-prefilter.h" +#include "detect-parse.h" + +int DetectHelperBufferRegister(const char *name, AppProto alproto, bool toclient, bool toserver) +{ + if (toserver) { + DetectAppLayerInspectEngineRegister( + name, alproto, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); + } + if (toclient) { + DetectAppLayerInspectEngineRegister( + name, alproto, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL); + } + return DetectBufferTypeRegister(name); +} + +InspectionBuffer *DetectHelperGetData(struct DetectEngineThreadCtx_ *det_ctx, + const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, + const int list_id, + bool (*GetBuf)(void *txv, const uint8_t flow_flags, const uint8_t **buf, uint32_t *buf_len)) +{ + InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); + if (buffer->inspect == NULL) { + const uint8_t *b = NULL; + uint32_t b_len = 0; + + if (!GetBuf(txv, flow_flags, &b, &b_len)) + return NULL; + + InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len); + InspectionBufferApplyTransforms(buffer, transforms); + } + return buffer; +} + +int DetectHelperBufferMpmRegister(const char *name, const char *desc, AppProto alproto, + bool toclient, bool toserver, InspectionBufferGetDataPtr GetData) +{ + if (toserver) { + DetectAppLayerInspectEngineRegister( + name, alproto, SIG_FLAG_TOSERVER, 0, DetectEngineInspectBufferGeneric, GetData); + DetectAppLayerMpmRegister( + name, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister, GetData, alproto, 0); + } + if (toclient) { + DetectAppLayerInspectEngineRegister( + name, alproto, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectBufferGeneric, GetData); + DetectAppLayerMpmRegister( + name, SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister, GetData, alproto, 0); + } + DetectBufferTypeSetDescriptionByName(name, desc); + return DetectBufferTypeGetByName(name); +} + +int DetectHelperKeywordRegister(const SCSigTableElmt *kw) +{ + if (DETECT_TBLSIZE_IDX >= DETECT_TBLSIZE) { + void *tmp = SCRealloc( + sigmatch_table, (DETECT_TBLSIZE + DETECT_TBLSIZE_STEP) * sizeof(SigTableElmt)); + if (unlikely(tmp == NULL)) { + return -1; + } + sigmatch_table = tmp; + DETECT_TBLSIZE += DETECT_TBLSIZE_STEP; + } + + sigmatch_table[DETECT_TBLSIZE_IDX].name = kw->name; + sigmatch_table[DETECT_TBLSIZE_IDX].desc = kw->desc; + sigmatch_table[DETECT_TBLSIZE_IDX].url = kw->url; + sigmatch_table[DETECT_TBLSIZE_IDX].flags = kw->flags; + sigmatch_table[DETECT_TBLSIZE_IDX].AppLayerTxMatch = + (int (*)(DetectEngineThreadCtx * det_ctx, Flow * f, uint8_t flags, void *alstate, + void *txv, const Signature *s, const SigMatchCtx *ctx)) kw->AppLayerTxMatch; + sigmatch_table[DETECT_TBLSIZE_IDX].Setup = + (int (*)(DetectEngineCtx * de, Signature * s, const char *raw)) kw->Setup; + sigmatch_table[DETECT_TBLSIZE_IDX].Free = (void (*)(DetectEngineCtx * de, void *ptr)) kw->Free; + DETECT_TBLSIZE_IDX++; + return DETECT_TBLSIZE_IDX - 1; +} diff --git a/src/detect-engine-helper.h b/src/detect-engine-helper.h new file mode 100644 index 000000000000..bd8fe6cce5a6 --- /dev/null +++ b/src/detect-engine-helper.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2023 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Philippe Antoine + */ + +#ifndef SURICATA_DETECT_ENGINE_HELPER_H +#define SURICATA_DETECT_ENGINE_HELPER_H + +#include "app-layer-protos.h" +#include "detect.h" +#include "rust.h" + +int DetectHelperKeywordRegister(const SCSigTableElmt *kw); +int DetectHelperBufferRegister(const char *name, AppProto alproto, bool toclient, bool toserver); + +typedef bool (*SimpleGetTxBuffer)(void *, uint8_t, const uint8_t **, uint32_t *); +InspectionBuffer *DetectHelperGetData(struct DetectEngineThreadCtx_ *det_ctx, + const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, + const int list_id, SimpleGetTxBuffer GetBuf); +int DetectHelperBufferMpmRegister(const char *name, const char *desc, AppProto alproto, + bool toclient, bool toserver, InspectionBufferGetDataPtr GetData); + +#endif /* SURICATA_DETECT_ENGINE_HELPER_H */ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 7b7e5442aad1..5d4438485811 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -212,13 +212,6 @@ #include "detect-rfb-name.h" #include "detect-target.h" #include "detect-template-rust-buffer.h" -#include "detect-dhcp-leasetime.h" -#include "detect-dhcp-rebinding-time.h" -#include "detect-dhcp-renewal-time.h" -#include "detect-snmp-usm.h" -#include "detect-snmp-version.h" -#include "detect-snmp-community.h" -#include "detect-snmp-pdu_type.h" #include "detect-mqtt-type.h" #include "detect-mqtt-flags.h" #include "detect-mqtt-qos.h" @@ -242,7 +235,6 @@ #include "detect-quic-cyu-hash.h" #include "detect-quic-cyu-string.h" #include "detect-ja4-hash.h" -#include "detect-websocket.h" #include "detect-bypass.h" #include "detect-ftpdata.h" @@ -283,25 +275,6 @@ #include "detect-ssl-version.h" #include "detect-ssl-state.h" #include "detect-modbus.h" -#include "detect-cipservice.h" -#include "detect-enip-command.h" -#include "detect-enip-status.h" -#include "detect-enip-product-name.h" -#include "detect-enip-protocol-version.h" -#include "detect-enip-cip-attribute.h" -#include "detect-enip-cip-instance.h" -#include "detect-enip-cip-class.h" -#include "detect-enip-cip-extendedstatus.h" -#include "detect-enip-cip-status.h" -#include "detect-enip-service-name.h" -#include "detect-enip-capabilities.h" -#include "detect-enip-revision.h" -#include "detect-enip-identity-status.h" -#include "detect-enip-state.h" -#include "detect-enip-serial.h" -#include "detect-enip-product-code.h" -#include "detect-enip-device-type.h" -#include "detect-enip-vendor-id.h" #include "detect-dnp3.h" #include "detect-ike-exch-type.h" #include "detect-ike-spi.h" @@ -340,6 +313,9 @@ #include "util-mpm-ac.h" #include "runmodes.h" +int DETECT_TBLSIZE = 0; +int DETECT_TBLSIZE_IDX = DETECT_TBLSIZE_STATIC; + static void PrintFeatureList(const SigTableElmt *e, char sep) { const uint16_t flags = e->flags; @@ -408,7 +384,7 @@ static void SigMultilinePrint(int i, const char *prefix) int SigTableList(const char *keyword) { - size_t size = sizeof(sigmatch_table) / sizeof(SigTableElmt); + size_t size = DETECT_TBLSIZE; size_t i; if (keyword == NULL) { @@ -483,15 +459,32 @@ int SigTableList(const char *keyword) static void DetectFileHandlerRegister(void) { - for (int i = 0; i < DETECT_TBLSIZE; i++) { + for (int i = 0; i < DETECT_TBLSIZE_STATIC; i++) { if (filehandler_table[i].name) DetectFileRegisterFileProtocols(&filehandler_table[i]); } } +void SigTableCleanup(void) +{ + if (sigmatch_table != NULL) { + SCFree(sigmatch_table); + sigmatch_table = NULL; + DETECT_TBLSIZE = 0; + } +} + void SigTableSetup(void) { - memset(sigmatch_table, 0, sizeof(sigmatch_table)); + if (sigmatch_table == NULL) { + DETECT_TBLSIZE = DETECT_TBLSIZE_STATIC + DETECT_TBLSIZE_STEP; + sigmatch_table = SCCalloc(DETECT_TBLSIZE, sizeof(SigTableElmt)); + if (sigmatch_table == NULL) { + DETECT_TBLSIZE = 0; + FatalError("Could not allocate sigmatch_table"); + return; + } + } DetectSidRegister(); DetectPriorityRegister(); @@ -550,25 +543,6 @@ void SigTableSetup(void) DetectDnsAnswerNameRegister(); DetectDnsQueryNameRegister(); DetectModbusRegister(); - DetectCipServiceRegister(); - DetectEnipCommandRegister(); - DetectEnipStatusRegister(); - DetectEnipProductNameRegister(); - DetectEnipProtocolVersionRegister(); - DetectEnipCipAttributeRegister(); - DetectEnipCipInstanceRegister(); - DetectEnipCipClassRegister(); - DetectEnipCipExtendedstatusRegister(); - DetectEnipCipStatusRegister(); - DetectEnipServiceNameRegister(); - DetectEnipCapabilitiesRegister(); - DetectEnipRevisionRegister(); - DetectEnipIdentityStatusRegister(); - DetectEnipStateRegister(); - DetectEnipSerialRegister(); - DetectEnipProductCodeRegister(); - DetectEnipDeviceTypeRegister(); - DetectEnipVendorIdRegister(); DetectDNP3Register(); DetectIkeExchTypeRegister(); @@ -717,13 +691,6 @@ void SigTableSetup(void) DetectRfbNameRegister(); DetectTargetRegister(); DetectTemplateRustBufferRegister(); - DetectDHCPLeaseTimeRegister(); - DetectDHCPRebindingTimeRegister(); - DetectDHCPRenewalTimeRegister(); - DetectSNMPUsmRegister(); - DetectSNMPVersionRegister(); - DetectSNMPCommunityRegister(); - DetectSNMPPduTypeRegister(); DetectMQTTTypeRegister(); DetectMQTTFlagsRegister(); DetectMQTTQosRegister(); @@ -747,7 +714,6 @@ void SigTableSetup(void) DetectQuicCyuHashRegister(); DetectQuicCyuStringRegister(); DetectJa4HashRegister(); - DetectWebsocketRegister(); DetectBypassRegister(); DetectConfigRegister(); @@ -768,6 +734,11 @@ void SigTableSetup(void) DetectFileHandlerRegister(); + ScDetectSNMPRegister(); + ScDetectDHCPRegister(); + ScDetectWebsocketRegister(); + ScDetectEnipRegister(); + /* close keyword registration */ DetectBufferTypeCloseRegistration(); } diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index 58908c05d756..71af4c3a1659 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -252,25 +252,6 @@ enum DetectKeywordId { DETECT_AL_TLS_JA3S_STRING, DETECT_AL_MODBUS, - DETECT_CIPSERVICE, - DETECT_ENIPCOMMAND, - DETECT_ENIPSTATUS, - DETECT_ENIP_PRODUCTNAME, - DETECT_ENIP_PROTOCOLVERSION, - DETECT_ENIP_CIPATTRIBUTE, - DETECT_ENIP_CIPINSTANCE, - DETECT_ENIP_CIPCLASS, - DETECT_ENIP_CIPEXTENDEDSTATUS, - DETECT_ENIP_CIPSTATUS, - DETECT_ENIP_SERVICENAME, - DETECT_ENIP_CAPABILITIES, - DETECT_ENIP_REVISION, - DETECT_ENIP_IDENTITYSTATUS, - DETECT_ENIP_STATE, - DETECT_ENIP_SERIAL, - DETECT_ENIP_PRODUCTCODE, - DETECT_ENIP_DEVICETYPE, - DETECT_ENIP_VENDORID, DETECT_AL_DNP3DATA, DETECT_AL_DNP3FUNC, @@ -309,13 +290,6 @@ enum DetectKeywordId { DETECT_FTPDATA, DETECT_TARGET, DETECT_AL_TEMPLATE_BUFFER, - DETECT_AL_DHCP_LEASETIME, - DETECT_AL_DHCP_REBINDING_TIME, - DETECT_AL_DHCP_RENEWAL_TIME, - DETECT_AL_SNMP_USM, - DETECT_AL_SNMP_VERSION, - DETECT_AL_SNMP_COMMUNITY, - DETECT_AL_SNMP_PDU_TYPE, DETECT_AL_MQTT_TYPE, DETECT_AL_MQTT_FLAGS, DETECT_AL_MQTT_QOS, @@ -338,10 +312,6 @@ enum DetectKeywordId { DETECT_AL_QUIC_UA, DETECT_AL_QUIC_CYU_HASH, DETECT_AL_QUIC_CYU_STRING, - DETECT_WEBSOCKET_MASK, - DETECT_WEBSOCKET_OPCODE, - DETECT_WEBSOCKET_FLAGS, - DETECT_WEBSOCKET_PAYLOAD, DETECT_BYPASS, @@ -374,10 +344,15 @@ enum DetectKeywordId { DETECT_AL_JA4_HASH, /* make sure this stays last */ - DETECT_TBLSIZE, + DETECT_TBLSIZE_STATIC, }; +extern int DETECT_TBLSIZE; +extern int DETECT_TBLSIZE_IDX; +// step for reallocating sigmatch_table +#define DETECT_TBLSIZE_STEP 256 int SigTableList(const char *keyword); +void SigTableCleanup(void); void SigTableSetup(void); void SigTableRegisterTests(void); diff --git a/src/detect-engine.c b/src/detect-engine.c index 995d285f7489..efb480f59088 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -2493,6 +2493,14 @@ static DetectEngineCtx *DetectEngineCtxInitReal( goto error; } + de_ctx->sm_types_prefilter = SCCalloc(DETECT_TBLSIZE, sizeof(bool)); + if (de_ctx->sm_types_prefilter == NULL) { + goto error; + } + de_ctx->sm_types_silent_error = SCCalloc(DETECT_TBLSIZE, sizeof(bool)); + if (de_ctx->sm_types_silent_error == NULL) { + goto error; + } if (DetectEngineCtxLoadConf(de_ctx) == -1) { goto error; } @@ -2625,6 +2633,8 @@ void DetectEngineCtxFree(DetectEngineCtx *de_ctx) SigGroupCleanup(de_ctx); SpmDestroyGlobalThreadCtx(de_ctx->spm_global_thread_ctx); + SCFree(de_ctx->sm_types_prefilter); + SCFree(de_ctx->sm_types_silent_error); MpmFactoryDeRegisterAllMpmCtxProfiles(de_ctx); diff --git a/src/detect-enip-capabilities.c b/src/detect-enip-capabilities.c deleted file mode 100644 index 13adecb10d07..000000000000 --- a/src/detect-enip-capabilities.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP capabilities keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-capabilities.h" - -static int g_enip_capabilities_id = 0; - -static void DetectEnipCapabilitiesFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used to parse enip_capabilities data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip capabilities options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipCapabilitiesSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *du16 = DetectU16Parse(rulestr); - if (du16 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_CAPABILITIES, (SigMatchCtx *)du16, - g_enip_capabilities_id) == NULL) { - DetectEnipCapabilitiesFree(de_ctx, du16); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip capabilities type rule option on a transaction - * with those passed via enip_capabilities: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipCapabilitiesMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint16_t value; - if (!SCEnipTxGetCapabilities(txv, &value)) - SCReturnInt(0); - const DetectU16Data *du16 = (const DetectU16Data *)ctx; - return DetectU16Match(value, du16); -} - -/** - * \brief Registration function for enip_capabilities: keyword - */ -void DetectEnipCapabilitiesRegister(void) -{ - sigmatch_table[DETECT_ENIP_CAPABILITIES].name = "enip.capabilities"; // rule keyword - sigmatch_table[DETECT_ENIP_CAPABILITIES].desc = "rules for detecting EtherNet/IP capabilities"; - sigmatch_table[DETECT_ENIP_CAPABILITIES].url = "/rules/enip-keyword.html#enip-capabilities"; - sigmatch_table[DETECT_ENIP_CAPABILITIES].Match = NULL; - sigmatch_table[DETECT_ENIP_CAPABILITIES].AppLayerTxMatch = DetectEnipCapabilitiesMatch; - sigmatch_table[DETECT_ENIP_CAPABILITIES].Setup = DetectEnipCapabilitiesSetup; - sigmatch_table[DETECT_ENIP_CAPABILITIES].Free = DetectEnipCapabilitiesFree; - - DetectAppLayerInspectEngineRegister("enip.capabilities", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.capabilities", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_capabilities_id = DetectBufferTypeGetByName("enip.capabilities"); -} diff --git a/src/detect-enip-capabilities.h b/src/detect-enip-capabilities.h deleted file mode 100644 index cba028ac9835..000000000000 --- a/src/detect-enip-capabilities.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_CAPABILITIES_H -#define SURICATA_DETECT_ENIP_CAPABILITIES_H - -void DetectEnipCapabilitiesRegister(void); - -#endif /* SURICATA_DETECT_ENIP_CAPABILITIES_H */ diff --git a/src/detect-enip-cip-attribute.c b/src/detect-enip-cip-attribute.c deleted file mode 100644 index 19b0e16227c4..000000000000 --- a/src/detect-enip-cip-attribute.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP cip attribute keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-cip-attribute.h" - -static int g_enip_cip_attribute_id = 0; - -static void DetectEnipCipAttributeFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u32_free(ptr); -} - -/** - * \brief this function is used to parse enip_cip_attribute data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip cip_attribute options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipCipAttributeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU32Data *du32 = DetectU32Parse(rulestr); - if (du32 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_CIPATTRIBUTE, (SigMatchCtx *)du32, - g_enip_cip_attribute_id) == NULL) { - DetectEnipCipAttributeFree(de_ctx, du32); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip cip_attribute type rule option on a transaction - * with those passed via enip_cip_attribute: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipCipAttributeMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - return SCEnipTxHasCipAttribute(txv, ctx); -} - -/** - * \brief Registration function for enip_cip_attribute: keyword - */ -void DetectEnipCipAttributeRegister(void) -{ - sigmatch_table[DETECT_ENIP_CIPATTRIBUTE].name = "enip.cip_attribute"; // rule keyword - sigmatch_table[DETECT_ENIP_CIPATTRIBUTE].desc = "rules for detecting EtherNet/IP cip_attribute"; - sigmatch_table[DETECT_ENIP_CIPATTRIBUTE].url = "/rules/enip-keyword.html#enip-cip-attribute"; - sigmatch_table[DETECT_ENIP_CIPATTRIBUTE].Match = NULL; - sigmatch_table[DETECT_ENIP_CIPATTRIBUTE].AppLayerTxMatch = DetectEnipCipAttributeMatch; - sigmatch_table[DETECT_ENIP_CIPATTRIBUTE].Setup = DetectEnipCipAttributeSetup; - sigmatch_table[DETECT_ENIP_CIPATTRIBUTE].Free = DetectEnipCipAttributeFree; - - DetectAppLayerInspectEngineRegister("enip.cip_attribute", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.cip_attribute", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_cip_attribute_id = DetectBufferTypeGetByName("enip.cip_attribute"); -} diff --git a/src/detect-enip-cip-attribute.h b/src/detect-enip-cip-attribute.h deleted file mode 100644 index 5c8256917e13..000000000000 --- a/src/detect-enip-cip-attribute.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_CIP_ATTRIBUTE_H -#define SURICATA_DETECT_ENIP_CIP_ATTRIBUTE_H - -void DetectEnipCipAttributeRegister(void); - -#endif /* SURICATA_DETECT_ENIP_CIP_ATTRIBUTE_H */ diff --git a/src/detect-enip-cip-class.c b/src/detect-enip-cip-class.c deleted file mode 100644 index bf4474ad0102..000000000000 --- a/src/detect-enip-cip-class.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP cip class keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-cip-class.h" - -static int g_enip_cip_class_id = 0; - -static void DetectEnipCipClassFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u32_free(ptr); -} - -/** - * \brief this function is used to parse enip_cip_class data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip cip_class options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipCipClassSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - SCReturnInt(-1); - - DetectU32Data *du32 = DetectU32Parse(rulestr); - if (du32 == NULL) - SCReturnInt(-1); - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_CIPCLASS, (SigMatchCtx *)du32, - g_enip_cip_class_id) == NULL) { - DetectEnipCipClassFree(de_ctx, du32); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip cip_class type rule option on a transaction - * with those passed via enip_cip_class: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipCipClassMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - return SCEnipTxHasCipClass(txv, ctx); -} - -/** - * \brief Registration function for enip_cip_class: keyword - */ -void DetectEnipCipClassRegister(void) -{ - sigmatch_table[DETECT_ENIP_CIPCLASS].name = "enip.cip_class"; // rule keyword - sigmatch_table[DETECT_ENIP_CIPCLASS].desc = "rules for detecting EtherNet/IP cip_class"; - sigmatch_table[DETECT_ENIP_CIPCLASS].url = "/rules/enip-keyword.html#enip-cip-class"; - sigmatch_table[DETECT_ENIP_CIPCLASS].Match = NULL; - sigmatch_table[DETECT_ENIP_CIPCLASS].AppLayerTxMatch = DetectEnipCipClassMatch; - sigmatch_table[DETECT_ENIP_CIPCLASS].Setup = DetectEnipCipClassSetup; - sigmatch_table[DETECT_ENIP_CIPCLASS].Free = DetectEnipCipClassFree; - - DetectAppLayerInspectEngineRegister("enip.cip_class", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.cip_class", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_cip_class_id = DetectBufferTypeGetByName("enip.cip_class"); -} diff --git a/src/detect-enip-cip-class.h b/src/detect-enip-cip-class.h deleted file mode 100644 index 9e853a3a122d..000000000000 --- a/src/detect-enip-cip-class.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_CIP_CLASS_H -#define SURICATA_DETECT_ENIP_CIP_CLASS_H - -void DetectEnipCipClassRegister(void); - -#endif /* SURICATA_DETECT_ENIP_CIP_CLASS_H */ diff --git a/src/detect-enip-cip-extendedstatus.c b/src/detect-enip-cip-extendedstatus.c deleted file mode 100644 index 7865cbf806f7..000000000000 --- a/src/detect-enip-cip-extendedstatus.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP cip extendedstatus keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-cip-extendedstatus.h" - -static int g_enip_cip_extendedstatus_id = 0; - -static void DetectEnipCipExtendedstatusFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used to parse enip_cip_extendedstatus data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip cip_extendedstatus options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipCipExtendedstatusSetup( - DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *du16 = DetectU16Parse(rulestr); - if (du16 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_CIPEXTENDEDSTATUS, (SigMatchCtx *)du16, - g_enip_cip_extendedstatus_id) == NULL) { - DetectEnipCipExtendedstatusFree(de_ctx, du16); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip cip_extendedstatus type rule option on a transaction - * with those passed via enip_cip_extendedstatus: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipCipExtendedstatusMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - return SCEnipTxHasCipExtendedstatus(txv, ctx); -} - -/** - * \brief Registration function for enip_cip_extendedstatus: keyword - */ -void DetectEnipCipExtendedstatusRegister(void) -{ - sigmatch_table[DETECT_ENIP_CIPEXTENDEDSTATUS].name = "enip.cip_extendedstatus"; // rule keyword - sigmatch_table[DETECT_ENIP_CIPEXTENDEDSTATUS].desc = - "rules for detecting EtherNet/IP cip_extendedstatus"; - sigmatch_table[DETECT_ENIP_CIPEXTENDEDSTATUS].url = - "/rules/enip-keyword.html#enip-cip-extendedstatus"; - sigmatch_table[DETECT_ENIP_CIPEXTENDEDSTATUS].Match = NULL; - sigmatch_table[DETECT_ENIP_CIPEXTENDEDSTATUS].AppLayerTxMatch = - DetectEnipCipExtendedstatusMatch; - sigmatch_table[DETECT_ENIP_CIPEXTENDEDSTATUS].Setup = DetectEnipCipExtendedstatusSetup; - sigmatch_table[DETECT_ENIP_CIPEXTENDEDSTATUS].Free = DetectEnipCipExtendedstatusFree; - - DetectAppLayerInspectEngineRegister("enip.cip_extendedstatus", ALPROTO_ENIP, SIG_FLAG_TOSERVER, - 0, DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.cip_extendedstatus", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, - 0, DetectEngineInspectGenericList, NULL); - - g_enip_cip_extendedstatus_id = DetectBufferTypeGetByName("enip.cip_extendedstatus"); -} diff --git a/src/detect-enip-cip-extendedstatus.h b/src/detect-enip-cip-extendedstatus.h deleted file mode 100644 index 09bb9bc9f879..000000000000 --- a/src/detect-enip-cip-extendedstatus.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_CIP_EXTENDEDSTATUS_H -#define SURICATA_DETECT_ENIP_CIP_EXTENDEDSTATUS_H - -void DetectEnipCipExtendedstatusRegister(void); - -#endif /* SURICATA_DETECT_ENIP_CIP_EXTENDEDSTATUS_H */ diff --git a/src/detect-enip-cip-instance.c b/src/detect-enip-cip-instance.c deleted file mode 100644 index 46808f7f6029..000000000000 --- a/src/detect-enip-cip-instance.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP cip instance keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-cip-instance.h" - -static int g_enip_cip_instance_id = 0; - -static void DetectEnipCipInstanceFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u32_free(ptr); -} - -/** - * \brief this function is used to parse enip_cip_instance data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip cip_instance options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipCipInstanceSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU32Data *du32 = DetectU32Parse(rulestr); - if (du32 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_CIPINSTANCE, (SigMatchCtx *)du32, - g_enip_cip_instance_id) == NULL) { - DetectEnipCipInstanceFree(de_ctx, du32); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip cip_instance type rule option on a transaction - * with those passed via enip_cip_instance: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipCipInstanceMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - return SCEnipTxHasCipInstance(txv, ctx); -} - -/** - * \brief Registration function for enip_cip_instance: keyword - */ -void DetectEnipCipInstanceRegister(void) -{ - sigmatch_table[DETECT_ENIP_CIPINSTANCE].name = "enip.cip_instance"; // rule keyword - sigmatch_table[DETECT_ENIP_CIPINSTANCE].desc = "rules for detecting EtherNet/IP cip_instance"; - sigmatch_table[DETECT_ENIP_CIPINSTANCE].url = "/rules/enip-keyword.html#enip-cip-instance"; - sigmatch_table[DETECT_ENIP_CIPINSTANCE].Match = NULL; - sigmatch_table[DETECT_ENIP_CIPINSTANCE].AppLayerTxMatch = DetectEnipCipInstanceMatch; - sigmatch_table[DETECT_ENIP_CIPINSTANCE].Setup = DetectEnipCipInstanceSetup; - sigmatch_table[DETECT_ENIP_CIPINSTANCE].Free = DetectEnipCipInstanceFree; - - DetectAppLayerInspectEngineRegister("enip.cip_instance", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.cip_instance", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_cip_instance_id = DetectBufferTypeGetByName("enip.cip_instance"); -} diff --git a/src/detect-enip-cip-instance.h b/src/detect-enip-cip-instance.h deleted file mode 100644 index c1235a990992..000000000000 --- a/src/detect-enip-cip-instance.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_CIP_INSTANCE_H -#define SURICATA_DETECT_ENIP_CIP_INSTANCE_H - -void DetectEnipCipInstanceRegister(void); - -#endif /* SURICATA_DETECT_ENIP_CIP_INSTANCE_H */ diff --git a/src/detect-enip-cip-status.c b/src/detect-enip-cip-status.c deleted file mode 100644 index 97fa0c393604..000000000000 --- a/src/detect-enip-cip-status.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP cip status keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-cip-status.h" - -static int g_enip_cip_status_id = 0; - -static void DetectEnipCipStatusFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u8_free(ptr); -} - -/** - * \brief this function is used to parse enip_cip_status data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip cip_status options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipCipStatusSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU8Data *du8 = DetectU8Parse(rulestr); - if (du8 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_CIPSTATUS, (SigMatchCtx *)du8, - g_enip_cip_status_id) == NULL) { - DetectEnipCipStatusFree(de_ctx, du8); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip cip_status type rule option on a transaction - * with those passed via enip_cip_status: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipCipStatusMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - return SCEnipTxHasCipStatus(txv, ctx); -} - -/** - * \brief Registration function for enip_cip_status: keyword - */ -void DetectEnipCipStatusRegister(void) -{ - sigmatch_table[DETECT_ENIP_CIPSTATUS].name = "enip.cip_status"; // rule keyword - sigmatch_table[DETECT_ENIP_CIPSTATUS].desc = "rules for detecting EtherNet/IP cip_status"; - sigmatch_table[DETECT_ENIP_CIPSTATUS].url = "/rules/enip-keyword.html#enip-cip-status"; - sigmatch_table[DETECT_ENIP_CIPSTATUS].Match = NULL; - sigmatch_table[DETECT_ENIP_CIPSTATUS].AppLayerTxMatch = DetectEnipCipStatusMatch; - sigmatch_table[DETECT_ENIP_CIPSTATUS].Setup = DetectEnipCipStatusSetup; - sigmatch_table[DETECT_ENIP_CIPSTATUS].Free = DetectEnipCipStatusFree; - - DetectAppLayerInspectEngineRegister("enip.cip_status", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.cip_status", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_cip_status_id = DetectBufferTypeGetByName("enip.cip_status"); -} diff --git a/src/detect-enip-cip-status.h b/src/detect-enip-cip-status.h deleted file mode 100644 index 93de881a8234..000000000000 --- a/src/detect-enip-cip-status.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_CIP_STATUS_H -#define SURICATA_DETECT_ENIP_CIP_STATUS_H - -void DetectEnipCipStatusRegister(void); - -#endif /* SURICATA_DETECT_ENIP_CIP_STATUS_H */ diff --git a/src/detect-enip-command.c b/src/detect-enip-command.c deleted file mode 100644 index 12977ab9589c..000000000000 --- a/src/detect-enip-command.c +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP Command rule parsing and entry point for matching - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-command.h" - -static int g_enip_buffer_id = 0; - -/** - * \brief this function will free memory associated - * - * \param ptr pointer to u16 - */ -static void DetectEnipCommandFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used by enipcmdd to parse enip_command data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip command options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipCommandSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *enipcmdd = SCEnipParseCommand(rulestr); - if (enipcmdd == NULL) { - SCLogWarning("rule %u has invalid value for enip_command %s", s->id, rulestr); - return -1; - } - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_ENIPCOMMAND, (SigMatchCtx *)enipcmdd, g_enip_buffer_id) == NULL) { - DetectEnipCommandFree(de_ctx, enipcmdd); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip command type rule option on a transaction with those - * passed via enip_command: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipCommandMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint16_t value; - if (!SCEnipTxGetCommand(txv, flags, &value)) - SCReturnInt(0); - const DetectU16Data *du16 = (const DetectU16Data *)ctx; - return DetectU16Match(value, du16); -} - -/** - * \brief Registration function for enip_command: keyword - */ -void DetectEnipCommandRegister(void) -{ - sigmatch_table[DETECT_ENIPCOMMAND].name = "enip_command"; // rule keyword - sigmatch_table[DETECT_ENIPCOMMAND].desc = "rules for detecting EtherNet/IP command"; - sigmatch_table[DETECT_ENIPCOMMAND].url = "/rules/enip-keyword.html#enip_command"; - sigmatch_table[DETECT_ENIPCOMMAND].Match = NULL; - sigmatch_table[DETECT_ENIPCOMMAND].AppLayerTxMatch = DetectEnipCommandMatch; - sigmatch_table[DETECT_ENIPCOMMAND].Setup = DetectEnipCommandSetup; - sigmatch_table[DETECT_ENIPCOMMAND].Free = DetectEnipCommandFree; - - DetectAppLayerInspectEngineRegister( - "enip", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister( - "enip", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL); - - g_enip_buffer_id = DetectBufferTypeGetByName("enip"); -} diff --git a/src/detect-enip-command.h b/src/detect-enip-command.h deleted file mode 100644 index e2b296b9f136..000000000000 --- a/src/detect-enip-command.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_COMMAND_H -#define SURICATA_DETECT_ENIP_COMMAND_H - -void DetectEnipCommandRegister(void); - -#endif /* SURICATA_DETECT_ENIP_COMMAND_H */ diff --git a/src/detect-enip-device-type.c b/src/detect-enip-device-type.c deleted file mode 100644 index 36bff86a1e1b..000000000000 --- a/src/detect-enip-device-type.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP device type keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-device-type.h" - -static int g_enip_device_type_id = 0; - -static void DetectEnipDeviceTypeFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used to parse enip_device_type data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip device_type options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipDeviceTypeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *du16 = DetectU16Parse(rulestr); - if (du16 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_DEVICETYPE, (SigMatchCtx *)du16, - g_enip_device_type_id) == NULL) { - DetectEnipDeviceTypeFree(de_ctx, du16); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip device_type type rule option on a transaction with - * those passed via enip_device_type: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipDeviceTypeMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint16_t value; - if (!SCEnipTxGetDeviceType(txv, &value)) - SCReturnInt(0); - const DetectU16Data *du16 = (const DetectU16Data *)ctx; - return DetectU16Match(value, du16); -} - -/** - * \brief Registration function for enip_device_type: keyword - */ -void DetectEnipDeviceTypeRegister(void) -{ - sigmatch_table[DETECT_ENIP_DEVICETYPE].name = "enip.device_type"; // rule keyword - sigmatch_table[DETECT_ENIP_DEVICETYPE].desc = "rules for detecting EtherNet/IP device_type"; - sigmatch_table[DETECT_ENIP_DEVICETYPE].url = "/rules/enip-keyword.html#enip-device-type"; - sigmatch_table[DETECT_ENIP_DEVICETYPE].Match = NULL; - sigmatch_table[DETECT_ENIP_DEVICETYPE].AppLayerTxMatch = DetectEnipDeviceTypeMatch; - sigmatch_table[DETECT_ENIP_DEVICETYPE].Setup = DetectEnipDeviceTypeSetup; - sigmatch_table[DETECT_ENIP_DEVICETYPE].Free = DetectEnipDeviceTypeFree; - - DetectAppLayerInspectEngineRegister("enip.device_type", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.device_type", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_device_type_id = DetectBufferTypeGetByName("enip.device_type"); -} diff --git a/src/detect-enip-device-type.h b/src/detect-enip-device-type.h deleted file mode 100644 index f3511033720c..000000000000 --- a/src/detect-enip-device-type.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_DEVICE_TYPE_H -#define SURICATA_DETECT_ENIP_DEVICE_TYPE_H - -void DetectEnipDeviceTypeRegister(void); - -#endif /* SURICATA_DETECT_ENIP_DEVICE_TYPE_H */ diff --git a/src/detect-enip-identity-status.c b/src/detect-enip-identity-status.c deleted file mode 100644 index 92a065db5edf..000000000000 --- a/src/detect-enip-identity-status.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP identity status keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-identity-status.h" - -static int g_enip_identity_status_id = 0; - -static void DetectEnipIdentityStatusFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used to parse enip_identity_status data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip identity_status options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipIdentityStatusSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *du16 = DetectU16Parse(rulestr); - if (du16 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_IDENTITYSTATUS, (SigMatchCtx *)du16, - g_enip_identity_status_id) == NULL) { - DetectEnipIdentityStatusFree(de_ctx, du16); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip identity_status type rule option on a transaction with - * those passed via enip_identity_status: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipIdentityStatusMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint16_t value; - if (!SCEnipTxGetIdentityStatus(txv, &value)) - SCReturnInt(0); - const DetectU16Data *du16 = (const DetectU16Data *)ctx; - return DetectU16Match(value, du16); -} - -/** - * \brief Registration function for enip_identity_status: keyword - */ -void DetectEnipIdentityStatusRegister(void) -{ - sigmatch_table[DETECT_ENIP_IDENTITYSTATUS].name = "enip.identity_status"; // rule keyword - sigmatch_table[DETECT_ENIP_IDENTITYSTATUS].desc = - "rules for detecting EtherNet/IP identity_status"; - sigmatch_table[DETECT_ENIP_IDENTITYSTATUS].url = - "/rules/enip-keyword.html#enip-identity-status"; - sigmatch_table[DETECT_ENIP_IDENTITYSTATUS].Match = NULL; - sigmatch_table[DETECT_ENIP_IDENTITYSTATUS].AppLayerTxMatch = DetectEnipIdentityStatusMatch; - sigmatch_table[DETECT_ENIP_IDENTITYSTATUS].Setup = DetectEnipIdentityStatusSetup; - sigmatch_table[DETECT_ENIP_IDENTITYSTATUS].Free = DetectEnipIdentityStatusFree; - - DetectAppLayerInspectEngineRegister("enip.identity_status", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.identity_status", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_identity_status_id = DetectBufferTypeGetByName("enip.identity_status"); -} diff --git a/src/detect-enip-identity-status.h b/src/detect-enip-identity-status.h deleted file mode 100644 index f4577150d97c..000000000000 --- a/src/detect-enip-identity-status.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_IDENTITY_STATUS_H -#define SURICATA_DETECT_ENIP_IDENTITY_STATUS_H - -void DetectEnipIdentityStatusRegister(void); - -#endif /* SURICATA_DETECT_ENIP_IDENTITY_STATUS_H */ diff --git a/src/detect-enip-product-code.c b/src/detect-enip-product-code.c deleted file mode 100644 index 1ed2c915549a..000000000000 --- a/src/detect-enip-product-code.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP product code keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-product-code.h" - -static int g_enip_product_code_id = 0; - -static void DetectEnipProductCodeFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used to parse enip_product_code data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip product_code options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipProductCodeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *du16 = DetectU16Parse(rulestr); - if (du16 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_PRODUCTCODE, (SigMatchCtx *)du16, - g_enip_product_code_id) == NULL) { - DetectEnipProductCodeFree(de_ctx, du16); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip product_code type rule option on a transaction with - * those passed via enip_product_code: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipProductCodeMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint16_t value; - if (!SCEnipTxGetProductCode(txv, &value)) - SCReturnInt(0); - const DetectU16Data *du16 = (const DetectU16Data *)ctx; - return DetectU16Match(value, du16); -} - -/** - * \brief Registration function for enip_product_code: keyword - */ -void DetectEnipProductCodeRegister(void) -{ - sigmatch_table[DETECT_ENIP_PRODUCTCODE].name = "enip.product_code"; // rule keyword - sigmatch_table[DETECT_ENIP_PRODUCTCODE].desc = "rules for detecting EtherNet/IP product_code"; - sigmatch_table[DETECT_ENIP_PRODUCTCODE].url = "/rules/enip-keyword.html#enip-product-code"; - sigmatch_table[DETECT_ENIP_PRODUCTCODE].Match = NULL; - sigmatch_table[DETECT_ENIP_PRODUCTCODE].AppLayerTxMatch = DetectEnipProductCodeMatch; - sigmatch_table[DETECT_ENIP_PRODUCTCODE].Setup = DetectEnipProductCodeSetup; - sigmatch_table[DETECT_ENIP_PRODUCTCODE].Free = DetectEnipProductCodeFree; - - DetectAppLayerInspectEngineRegister("enip.product_code", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.product_code", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_product_code_id = DetectBufferTypeGetByName("enip.product_code"); -} diff --git a/src/detect-enip-product-code.h b/src/detect-enip-product-code.h deleted file mode 100644 index a04c52ec5921..000000000000 --- a/src/detect-enip-product-code.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_PRODUCT_CODE_H -#define SURICATA_DETECT_ENIP_PRODUCT_CODE_H - -void DetectEnipProductCodeRegister(void); - -#endif /* SURICATA_DETECT_ENIP_PRODUCT_CODE_H */ diff --git a/src/detect-enip-product-name.c b/src/detect-enip-product-name.c deleted file mode 100644 index 520a53e29d7b..000000000000 --- a/src/detect-enip-product-name.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP Product name keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-prefilter.h" -#include "rust.h" - -#include "detect-enip-product-name.h" - -static int g_enip_product_name_id = 0; - -/** - * \brief this function is used to setup sticky buffer inspection for product_name - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip product name options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipProductNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectBufferSetActiveList(de_ctx, s, g_enip_product_name_id) < 0) - return -1; - - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - return 0; -} - -static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv, - const int list_id) -{ - InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); - if (buffer->inspect == NULL) { - const uint8_t *b = NULL; - uint32_t b_len = 0; - - if (SCEnipTxGetProductName(txv, &b, &b_len) != 1) - return NULL; - if (b == NULL || b_len == 0) - return NULL; - - InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len); - InspectionBufferApplyTransforms(buffer, transforms); - } - return buffer; -} - -/** - * \brief Registration function for enip.product_name: keyword - */ -void DetectEnipProductNameRegister(void) -{ - sigmatch_table[DETECT_ENIP_PRODUCTNAME].name = "enip.product_name"; // rule keyword - sigmatch_table[DETECT_ENIP_PRODUCTNAME].desc = - "sticky buffer to match EtherNet/IP product name"; - sigmatch_table[DETECT_ENIP_PRODUCTNAME].url = "/rules/enip-keyword.html#enip-product-name"; - sigmatch_table[DETECT_ENIP_PRODUCTNAME].Setup = DetectEnipProductNameSetup; - sigmatch_table[DETECT_ENIP_PRODUCTNAME].flags |= SIGMATCH_NOOPT; - - DetectAppLayerInspectEngineRegister("enip.product_name", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectBufferGeneric, GetData); - - DetectAppLayerMpmRegister("enip.product_name", SIG_FLAG_TOCLIENT, 2, - PrefilterGenericMpmRegister, GetData, ALPROTO_ENIP, 1); - - DetectBufferTypeSetDescriptionByName("enip.product_name", "ENIP product name"); - g_enip_product_name_id = DetectBufferTypeGetByName("enip.product_name"); -} diff --git a/src/detect-enip-product-name.h b/src/detect-enip-product-name.h deleted file mode 100644 index 8d76e6880020..000000000000 --- a/src/detect-enip-product-name.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_PRODUCT_NAME_H -#define SURICATA_DETECT_ENIP_PRODUCT_NAME_H - -void DetectEnipProductNameRegister(void); - -#endif /* SURICATA_DETECT_ENIP_PRODUCT_NAME_H */ diff --git a/src/detect-enip-protocol-version.c b/src/detect-enip-protocol-version.c deleted file mode 100644 index 75290714484c..000000000000 --- a/src/detect-enip-protocol-version.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP protocol version keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-protocol-version.h" - -static int g_enip_protocol_version_id = 0; - -static void DetectEnipProtocolVersionFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used to parse enip_protocol_version data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip protocol_version options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipProtocolVersionSetup( - DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *du16 = DetectU16Parse(rulestr); - if (du16 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_PROTOCOLVERSION, (SigMatchCtx *)du16, - g_enip_protocol_version_id) == NULL) { - DetectEnipProtocolVersionFree(de_ctx, du16); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip protocol_version type rule option on a transaction - * with those passed via enip_protocol_version: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipProtocolVersionMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint16_t value; - if (!SCEnipTxGetProtocolVersion(txv, flags, &value)) - SCReturnInt(0); - const DetectU16Data *du16 = (const DetectU16Data *)ctx; - return DetectU16Match(value, du16); -} - -/** - * \brief Registration function for enip_protocol_version: keyword - */ -void DetectEnipProtocolVersionRegister(void) -{ - sigmatch_table[DETECT_ENIP_PROTOCOLVERSION].name = "enip.protocol_version"; // rule keyword - sigmatch_table[DETECT_ENIP_PROTOCOLVERSION].desc = - "rules for detecting EtherNet/IP protocol_version"; - sigmatch_table[DETECT_ENIP_PROTOCOLVERSION].url = - "/rules/enip-keyword.html#enip-protocol-version"; - sigmatch_table[DETECT_ENIP_PROTOCOLVERSION].Match = NULL; - sigmatch_table[DETECT_ENIP_PROTOCOLVERSION].AppLayerTxMatch = DetectEnipProtocolVersionMatch; - sigmatch_table[DETECT_ENIP_PROTOCOLVERSION].Setup = DetectEnipProtocolVersionSetup; - sigmatch_table[DETECT_ENIP_PROTOCOLVERSION].Free = DetectEnipProtocolVersionFree; - - DetectAppLayerInspectEngineRegister("enip.protocol_version", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.protocol_version", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_protocol_version_id = DetectBufferTypeGetByName("enip.protocol_version"); -} diff --git a/src/detect-enip-protocol-version.h b/src/detect-enip-protocol-version.h deleted file mode 100644 index a1cb654f87bd..000000000000 --- a/src/detect-enip-protocol-version.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_PROTOCOL_VERSION_H -#define SURICATA_DETECT_ENIP_PROTOCOL_VERSION_H - -void DetectEnipProtocolVersionRegister(void); - -#endif /* SURICATA_DETECT_ENIP_PROTOCOL_VERSION_H */ diff --git a/src/detect-enip-revision.c b/src/detect-enip-revision.c deleted file mode 100644 index 70bce0b78e59..000000000000 --- a/src/detect-enip-revision.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP revision keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-revision.h" - -static int g_enip_revision_id = 0; - -static void DetectEnipRevisionFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used to parse enip_revision data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip revision options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipRevisionSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *du16 = DetectU16Parse(rulestr); - if (du16 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_ENIP_REVISION, (SigMatchCtx *)du16, g_enip_revision_id) == NULL) { - DetectEnipRevisionFree(de_ctx, du16); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip revision type rule option on a transaction with those - * passed via enip_revision: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipRevisionMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint16_t value; - if (!SCEnipTxGetRevision(txv, &value)) - SCReturnInt(0); - const DetectU16Data *du16 = (const DetectU16Data *)ctx; - return DetectU16Match(value, du16); -} - -/** - * \brief Registration function for enip_revision: keyword - */ -void DetectEnipRevisionRegister(void) -{ - sigmatch_table[DETECT_ENIP_REVISION].name = "enip.revision"; // rule keyword - sigmatch_table[DETECT_ENIP_REVISION].desc = "rules for detecting EtherNet/IP revision"; - sigmatch_table[DETECT_ENIP_REVISION].url = "/rules/enip-keyword.html#enip-revision"; - sigmatch_table[DETECT_ENIP_REVISION].Match = NULL; - sigmatch_table[DETECT_ENIP_REVISION].AppLayerTxMatch = DetectEnipRevisionMatch; - sigmatch_table[DETECT_ENIP_REVISION].Setup = DetectEnipRevisionSetup; - sigmatch_table[DETECT_ENIP_REVISION].Free = DetectEnipRevisionFree; - - DetectAppLayerInspectEngineRegister("enip.revision", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.revision", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_revision_id = DetectBufferTypeGetByName("enip.revision"); -} diff --git a/src/detect-enip-revision.h b/src/detect-enip-revision.h deleted file mode 100644 index e7432b707e76..000000000000 --- a/src/detect-enip-revision.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_REVISION_H -#define SURICATA_DETECT_ENIP_REVISION_H - -void DetectEnipRevisionRegister(void); - -#endif /* SURICATA_DETECT_ENIP_REVISION_H */ diff --git a/src/detect-enip-serial.c b/src/detect-enip-serial.c deleted file mode 100644 index 71e88d99bc0c..000000000000 --- a/src/detect-enip-serial.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP serial keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-serial.h" - -static int g_enip_serial_id = 0; - -static void DetectEnipSerialFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u32_free(ptr); -} - -/** - * \brief this function is used to parse enip_serial data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip serial options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipSerialSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU32Data *du32 = DetectU32Parse(rulestr); - if (du32 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_ENIP_SERIAL, (SigMatchCtx *)du32, g_enip_serial_id) == NULL) { - DetectEnipSerialFree(de_ctx, du32); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip serial type rule option on a transaction with those - * passed via enip_serial: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipSerialMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint32_t value; - if (!SCEnipTxGetSerial(txv, &value)) - SCReturnInt(0); - const DetectU32Data *du32 = (const DetectU32Data *)ctx; - return DetectU32Match(value, du32); -} - -/** - * \brief Registration function for enip_serial: keyword - */ -void DetectEnipSerialRegister(void) -{ - sigmatch_table[DETECT_ENIP_SERIAL].name = "enip.serial"; // rule keyword - sigmatch_table[DETECT_ENIP_SERIAL].desc = "rules for detecting EtherNet/IP serial"; - sigmatch_table[DETECT_ENIP_SERIAL].url = "/rules/enip-keyword.html#enip-serial"; - sigmatch_table[DETECT_ENIP_SERIAL].Match = NULL; - sigmatch_table[DETECT_ENIP_SERIAL].AppLayerTxMatch = DetectEnipSerialMatch; - sigmatch_table[DETECT_ENIP_SERIAL].Setup = DetectEnipSerialSetup; - sigmatch_table[DETECT_ENIP_SERIAL].Free = DetectEnipSerialFree; - - DetectAppLayerInspectEngineRegister("enip.serial", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.serial", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_serial_id = DetectBufferTypeGetByName("enip.serial"); -} diff --git a/src/detect-enip-serial.h b/src/detect-enip-serial.h deleted file mode 100644 index 20aa27041533..000000000000 --- a/src/detect-enip-serial.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_SERIAL_H -#define SURICATA_DETECT_ENIP_SERIAL_H - -void DetectEnipSerialRegister(void); - -#endif /* SURICATA_DETECT_ENIP_SERIAL_H */ diff --git a/src/detect-enip-service-name.c b/src/detect-enip-service-name.c deleted file mode 100644 index 2ee2c885eacc..000000000000 --- a/src/detect-enip-service-name.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP service name keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-prefilter.h" -#include "rust.h" - -#include "detect-enip-service-name.h" - -static int g_enip_service_name_id = 0; - -/** - * \brief this function is used to parse enip_service_name data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip service_name options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipServiceNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectBufferSetActiveList(de_ctx, s, g_enip_service_name_id) < 0) - return -1; - - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - return 0; -} - -static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv, - const int list_id) -{ - InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); - if (buffer->inspect == NULL) { - const uint8_t *b = NULL; - uint32_t b_len = 0; - - if (SCEnipTxGetServiceName(txv, &b, &b_len) != 1) - return NULL; - if (b == NULL || b_len == 0) - return NULL; - - InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len); - InspectionBufferApplyTransforms(buffer, transforms); - } - return buffer; -} - -/** - * \brief Registration function for enip_service_name: keyword - */ -void DetectEnipServiceNameRegister(void) -{ - sigmatch_table[DETECT_ENIP_SERVICENAME].name = "enip.service_name"; // rule keyword - sigmatch_table[DETECT_ENIP_SERVICENAME].desc = "rules for detecting EtherNet/IP service_name"; - sigmatch_table[DETECT_ENIP_SERVICENAME].url = "/rules/enip-keyword.html#enip-service-name"; - sigmatch_table[DETECT_ENIP_SERVICENAME].Setup = DetectEnipServiceNameSetup; - sigmatch_table[DETECT_ENIP_PRODUCTNAME].flags |= SIGMATCH_NOOPT; - - DetectAppLayerInspectEngineRegister("enip.service_name", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerMpmRegister("enip.service_name", SIG_FLAG_TOCLIENT, 2, - PrefilterGenericMpmRegister, GetData, ALPROTO_ENIP, 1); - - DetectBufferTypeSetDescriptionByName("enip.service_name", "ENIP service name"); - g_enip_service_name_id = DetectBufferTypeGetByName("enip.service_name"); -} diff --git a/src/detect-enip-service-name.h b/src/detect-enip-service-name.h deleted file mode 100644 index 009f3ed320ca..000000000000 --- a/src/detect-enip-service-name.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_SERVICE_NAME_H -#define SURICATA_DETECT_ENIP_SERVICE_NAME_H - -void DetectEnipServiceNameRegister(void); - -#endif /* SURICATA_DETECT_ENIP_SERVICE_NAME_H */ diff --git a/src/detect-enip-state.c b/src/detect-enip-state.c deleted file mode 100644 index 2924391dacff..000000000000 --- a/src/detect-enip-state.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP state keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-state.h" - -static int g_enip_state_id = 0; - -static void DetectEnipStateFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u8_free(ptr); -} - -/** - * \brief this function is used to parse enip_state data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip state options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipStateSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU8Data *du8 = DetectU8Parse(rulestr); - if (du8 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_STATE, (SigMatchCtx *)du8, g_enip_state_id) == - NULL) { - DetectEnipStateFree(de_ctx, du8); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip state type rule option on a transaction with those - * passed via enip_state: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipStateMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, - void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint8_t value; - if (!SCEnipTxGetState(txv, &value)) - SCReturnInt(0); - const DetectU8Data *du8 = (const DetectU8Data *)ctx; - return DetectU8Match(value, du8); -} - -/** - * \brief Registration function for enip_state: keyword - */ -void DetectEnipStateRegister(void) -{ - sigmatch_table[DETECT_ENIP_STATE].name = "enip.state"; // rule keyword - sigmatch_table[DETECT_ENIP_STATE].desc = "rules for detecting EtherNet/IP state"; - sigmatch_table[DETECT_ENIP_STATE].url = "/rules/enip-keyword.html#enip-state"; - sigmatch_table[DETECT_ENIP_STATE].Match = NULL; - sigmatch_table[DETECT_ENIP_STATE].AppLayerTxMatch = DetectEnipStateMatch; - sigmatch_table[DETECT_ENIP_STATE].Setup = DetectEnipStateSetup; - sigmatch_table[DETECT_ENIP_STATE].Free = DetectEnipStateFree; - - DetectAppLayerInspectEngineRegister( - "enip.state", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister( - "enip.state", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL); - - g_enip_state_id = DetectBufferTypeGetByName("enip.state"); -} diff --git a/src/detect-enip-state.h b/src/detect-enip-state.h deleted file mode 100644 index eb0e4baaa85f..000000000000 --- a/src/detect-enip-state.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_STATE_H -#define SURICATA_DETECT_ENIP_STATE_H - -void DetectEnipStateRegister(void); - -#endif /* SURICATA_DETECT_ENIP_STATE_H */ diff --git a/src/detect-enip-status.c b/src/detect-enip-status.c deleted file mode 100644 index eb9a662c3e81..000000000000 --- a/src/detect-enip-status.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP Status rule parsing and entry point for matching - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-status.h" - -static int g_enip_status_id = 0; - -/** - * \brief this function will free memory associated - * - * \param ptr pointer to u16 - */ -static void DetectEnipStatusFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u32_free(ptr); -} - -/** - * \brief this function is used by enipcmdd to parse enip_status data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip status options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipStatusSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU32Data *du32 = SCEnipParseStatus(rulestr); - if (du32 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_ENIPSTATUS, (SigMatchCtx *)du32, g_enip_status_id) == NULL) { - DetectEnipStatusFree(de_ctx, du32); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip status type rule option on a transaction with those - * passed via enip_status: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipStatusMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint32_t status; - if (!SCEnipTxGetStatus(txv, flags, &status)) - SCReturnInt(0); - const DetectU32Data *du32 = (const DetectU32Data *)ctx; - return DetectU32Match(status, du32); -} - -/** - * \brief Registration function for enip_status: keyword - */ -void DetectEnipStatusRegister(void) -{ - sigmatch_table[DETECT_ENIPSTATUS].name = "enip.status"; // rule keyword - sigmatch_table[DETECT_ENIPSTATUS].desc = "rules for detecting EtherNet/IP status"; - sigmatch_table[DETECT_ENIPSTATUS].url = "/rules/enip-keyword.html#enip-status"; - sigmatch_table[DETECT_ENIPSTATUS].Match = NULL; - sigmatch_table[DETECT_ENIPSTATUS].AppLayerTxMatch = DetectEnipStatusMatch; - sigmatch_table[DETECT_ENIPSTATUS].Setup = DetectEnipStatusSetup; - sigmatch_table[DETECT_ENIPSTATUS].Free = DetectEnipStatusFree; - - DetectAppLayerInspectEngineRegister("enip.status", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.status", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_status_id = DetectBufferTypeGetByName("enip.status"); -} diff --git a/src/detect-enip-status.h b/src/detect-enip-status.h deleted file mode 100644 index 871be3c714c1..000000000000 --- a/src/detect-enip-status.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_STATUS_H -#define SURICATA_DETECT_ENIP_STATUS_H - -void DetectEnipStatusRegister(void); - -#endif /* SURICATA_DETECT_ENIP_STATUS_H */ diff --git a/src/detect-enip-vendor-id.c b/src/detect-enip-vendor-id.c deleted file mode 100644 index 75966c8a5d07..000000000000 --- a/src/detect-enip-vendor-id.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - * - * Set up ENIP vendor id keyword - */ - -#include "suricata-common.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-uint.h" -#include "rust.h" - -#include "detect-enip-vendor-id.h" - -static int g_enip_vendor_id_id = 0; - -static void DetectEnipVendorIdFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u16_free(ptr); -} - -/** - * \brief this function is used to parse enip_vendor_id data into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rulestr pointer to the user provided enip vendor_id options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectEnipVendorIdSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_ENIP) != 0) - return -1; - - DetectU16Data *du16 = DetectU16Parse(rulestr); - if (du16 == NULL) { - return -1; - } - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_ENIP_VENDORID, (SigMatchCtx *)du16, - g_enip_vendor_id_id) == NULL) { - DetectEnipVendorIdFree(de_ctx, du16); - SCReturnInt(-1); - } - SCReturnInt(0); -} - -/** - * \brief This function is used to match enip vendor_id type rule option on a transaction with those - * passed via enip_vendor_id: - * - * \retval 0 no match - * \retval 1 match - */ -static int DetectEnipVendorIdMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) - -{ - uint16_t value; - if (!SCEnipTxGetVendorId(txv, &value)) - SCReturnInt(0); - const DetectU16Data *du16 = (const DetectU16Data *)ctx; - return DetectU16Match(value, du16); -} - -/** - * \brief Registration function for enip_vendor_id: keyword - */ -void DetectEnipVendorIdRegister(void) -{ - sigmatch_table[DETECT_ENIP_VENDORID].name = "enip.vendor_id"; // rule keyword - sigmatch_table[DETECT_ENIP_VENDORID].desc = "rules for detecting EtherNet/IP vendor_id"; - sigmatch_table[DETECT_ENIP_VENDORID].url = "/rules/enip-keyword.html#enip-vendor-id"; - sigmatch_table[DETECT_ENIP_VENDORID].Match = NULL; - sigmatch_table[DETECT_ENIP_VENDORID].AppLayerTxMatch = DetectEnipVendorIdMatch; - sigmatch_table[DETECT_ENIP_VENDORID].Setup = DetectEnipVendorIdSetup; - sigmatch_table[DETECT_ENIP_VENDORID].Free = DetectEnipVendorIdFree; - - DetectAppLayerInspectEngineRegister("enip.vendor_id", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("enip.vendor_id", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_enip_vendor_id_id = DetectBufferTypeGetByName("enip.vendor_id"); -} diff --git a/src/detect-enip-vendor-id.h b/src/detect-enip-vendor-id.h deleted file mode 100644 index 8f99325851eb..000000000000 --- a/src/detect-enip-vendor-id.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef SURICATA_DETECT_ENIP_VENDOR_ID_H -#define SURICATA_DETECT_ENIP_VENDOR_ID_H - -void DetectEnipVendorIdRegister(void); - -#endif /* SURICATA_DETECT_ENIP_VENDOR_ID_H */ diff --git a/src/detect-iprep.c b/src/detect-iprep.c index e5069b7072f0..d4ba6ced55af 100644 --- a/src/detect-iprep.c +++ b/src/detect-iprep.c @@ -158,18 +158,37 @@ static int DetectIPRepMatch (DetectEngineThreadCtx *det_ctx, Packet *p, SCLogDebug("rd->cmd %u", rd->cmd); switch (rd->cmd) { case IPRepCmdAny: - val = GetHostRepSrc(p, rd->cat, version); - if (val < 0) - val = SRepCIDRGetIPRepSrc(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); - if (val >= 0) { - if (DetectU8Match((uint8_t)val, &rd->du8)) + if (!rd->isnotset) { + val = GetHostRepSrc(p, rd->cat, version); + if (val < 0) + val = SRepCIDRGetIPRepSrc(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); + if (val >= 0) { + if (DetectU8Match((uint8_t)val, &rd->du8)) + return 1; + } + val = GetHostRepDst(p, rd->cat, version); + if (val < 0) + val = SRepCIDRGetIPRepDst(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); + if (val >= 0) { + return DetectU8Match((uint8_t)val, &rd->du8); + } + } else { + /* isnotset for any */ + + val = GetHostRepSrc(p, rd->cat, version); + if (val < 0) + val = SRepCIDRGetIPRepSrc(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); + if (val < 0) { return 1; - } - val = GetHostRepDst(p, rd->cat, version); - if (val < 0) - val = SRepCIDRGetIPRepDst(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); - if (val >= 0) { - return DetectU8Match((uint8_t)val, &rd->du8); + } + val = GetHostRepDst(p, rd->cat, version); + if (val < 0) + val = SRepCIDRGetIPRepDst(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); + if (val < 0) { + return 1; + } + /* both have a value, so none 'isnotset' */ + return 0; } break; @@ -182,6 +201,10 @@ static int DetectIPRepMatch (DetectEngineThreadCtx *det_ctx, Packet *p, if (val >= 0) { return DetectU8Match((uint8_t)val, &rd->du8); } + /* implied: no value found */ + if (rd->isnotset) { + return 1; + } break; case IPRepCmdDst: @@ -192,19 +215,39 @@ static int DetectIPRepMatch (DetectEngineThreadCtx *det_ctx, Packet *p, if (val >= 0) { return DetectU8Match((uint8_t)val, &rd->du8); } + /* implied: no value found */ + if (rd->isnotset) { + return 1; + } break; case IPRepCmdBoth: - val = GetHostRepSrc(p, rd->cat, version); - if (val < 0) + if (!rd->isnotset) { + val = GetHostRepSrc(p, rd->cat, version); + if (val < 0) + val = SRepCIDRGetIPRepSrc(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); + if (val < 0 || DetectU8Match((uint8_t)val, &rd->du8) == 0) + return 0; + val = GetHostRepDst(p, rd->cat, version); + if (val < 0) + val = SRepCIDRGetIPRepDst(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); + if (val >= 0) { + return DetectU8Match((uint8_t)val, &rd->du8); + } + } else { + val = GetHostRepSrc(p, rd->cat, version); + if (val >= 0) + return 0; val = SRepCIDRGetIPRepSrc(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); - if (val < 0 || DetectU8Match((uint8_t)val, &rd->du8) == 0) - return 0; - val = GetHostRepDst(p, rd->cat, version); - if (val < 0) + if (val >= 0) + return 0; + val = GetHostRepDst(p, rd->cat, version); + if (val >= 0) + return 0; val = SRepCIDRGetIPRepDst(det_ctx->de_ctx->srepCIDR_ctx, p, rd->cat, version); - if (val >= 0) { - return DetectU8Match((uint8_t)val, &rd->du8); + if (val >= 0) + return 0; + return 1; } break; } @@ -214,7 +257,7 @@ static int DetectIPRepMatch (DetectEngineThreadCtx *det_ctx, Packet *p, int DetectIPRepSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { - DetectIPRepData *cd = rs_detect_iprep_parse(rawstr); + DetectIPRepData *cd = SCDetectIPRepParse(rawstr); if (cd == NULL) { SCLogError("\"%s\" is not a valid setting for iprep", rawstr); goto error; @@ -244,7 +287,7 @@ void DetectIPRepFree (DetectEngineCtx *de_ctx, void *ptr) if (fd == NULL) return; - rs_detect_iprep_free(fd); + SCDetectIPRepFree(fd); } #ifdef UNITTESTS @@ -775,6 +818,118 @@ static int DetectIPRepTest09(void) PASS; } +static FILE *DetectIPRepGenerateNetworksDummy3(void) +{ + FILE *fd = NULL; + const char *buffer = "192.168.0.0/16,1,127"; // BadHosts + + fd = SCFmemopen((void *)buffer, strlen(buffer), "r"); + if (fd == NULL) + SCLogDebug("Error with SCFmemopen()"); + + return fd; +} + +static int DetectIPRepTest10(void) +{ + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx = NULL; + Signature *sig = NULL; + FILE *fd = NULL; + int r = 0; + Packet *p = UTHBuildPacket((uint8_t *)"lalala", 6, IPPROTO_TCP); + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + HostInitConfig(HOST_QUIET); + memset(&th_v, 0, sizeof(th_v)); + + FAIL_IF_NULL(de_ctx); + FAIL_IF_NULL(p); + + p->src.addr_data32[0] = UTHSetIPv4Address("192.168.0.1"); + p->dst.addr_data32[0] = UTHSetIPv4Address("192.168.0.2"); + de_ctx->flags |= DE_QUIET; + + SRepInit(de_ctx); + SRepResetVersion(); + + fd = DetectIPRepGenerateCategoriesDummy2(); + r = SRepLoadCatFileFromFD(fd); + FAIL_IF(r < 0); + + fd = DetectIPRepGenerateNetworksDummy3(); + r = SRepLoadFileFromFD(de_ctx->srepCIDR_ctx, fd); + FAIL_IF(r < 0); + + sig = DetectEngineAppendSig(de_ctx, + "alert tcp any any -> any any (msg:\"test\"; iprep:src,BadHosts,isset; sid:1; rev:1;)"); + FAIL_IF_NULL(sig); + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + FAIL_IF_NOT(p->alerts.cnt == 1); + + UTHFreePacket(p); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + + HostShutdown(); + PASS; +} + +static int DetectIPRepTest11(void) +{ + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx = NULL; + Signature *sig = NULL; + FILE *fd = NULL; + int r = 0; + Packet *p = UTHBuildPacket((uint8_t *)"lalala", 6, IPPROTO_TCP); + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + HostInitConfig(HOST_QUIET); + memset(&th_v, 0, sizeof(th_v)); + + FAIL_IF_NULL(de_ctx); + FAIL_IF_NULL(p); + + p->src.addr_data32[0] = UTHSetIPv4Address("10.0.0.1"); + p->dst.addr_data32[0] = UTHSetIPv4Address("10.0.0.2"); + de_ctx->flags |= DE_QUIET; + + SRepInit(de_ctx); + SRepResetVersion(); + + fd = DetectIPRepGenerateCategoriesDummy2(); + r = SRepLoadCatFileFromFD(fd); + FAIL_IF(r < 0); + + fd = DetectIPRepGenerateNetworksDummy3(); + r = SRepLoadFileFromFD(de_ctx->srepCIDR_ctx, fd); + FAIL_IF(r < 0); + + sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"test\"; " + "iprep:src,BadHosts,isnotset; sid:1; rev:1;)"); + FAIL_IF_NULL(sig); + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, p); + FAIL_IF_NOT(p->alerts.cnt == 1); + + UTHFreePacket(p); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + + HostShutdown(); + PASS; +} + /** * \brief this function registers unit tests for IPRep */ @@ -789,5 +944,7 @@ void IPRepRegisterTests(void) UtRegisterTest("DetectIPRepTest07", DetectIPRepTest07); UtRegisterTest("DetectIPRepTest08", DetectIPRepTest08); UtRegisterTest("DetectIPRepTest09", DetectIPRepTest09); + UtRegisterTest("DetectIPRepTest10 -- isset", DetectIPRepTest10); + UtRegisterTest("DetectIPRepTest11 -- isnotset", DetectIPRepTest11); } #endif /* UNITTESTS */ diff --git a/src/detect-parse.c b/src/detect-parse.c index 67d68c57cb86..61318521f45d 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -74,7 +74,7 @@ #include "util-validate.h" /* Table with all filehandler registrations */ -DetectFileHandlerTableElmt filehandler_table[DETECT_TBLSIZE]; +DetectFileHandlerTableElmt filehandler_table[DETECT_TBLSIZE_STATIC]; void DetectFileRegisterFileProtocols(DetectFileHandlerTableElmt *reg) { @@ -124,7 +124,7 @@ void DetectFileRegisterFileProtocols(DetectFileHandlerTableElmt *reg) } /* Table with all SigMatch registrations */ -SigTableElmt sigmatch_table[DETECT_TBLSIZE]; +SigTableElmt *sigmatch_table = NULL; extern bool sc_set_caps; @@ -383,7 +383,7 @@ bool SigMatchSilentErrorEnabled(const DetectEngineCtx *de_ctx, bool SigMatchStrictEnabled(const enum DetectKeywordId id) { - if (id < DETECT_TBLSIZE) { + if ((int)id < DETECT_TBLSIZE) { return ((sigmatch_table[id].flags & SIGMATCH_STRICT_PARSING) != 0); } return false; diff --git a/src/detect-parse.h b/src/detect-parse.h index 0a993a794f84..ec2c204c0f42 100644 --- a/src/detect-parse.h +++ b/src/detect-parse.h @@ -42,7 +42,7 @@ typedef struct DetectFileHandlerTableElmt_ { void DetectFileRegisterFileProtocols(DetectFileHandlerTableElmt *entry); /* File registration table */ -extern DetectFileHandlerTableElmt filehandler_table[DETECT_TBLSIZE]; +extern DetectFileHandlerTableElmt filehandler_table[DETECT_TBLSIZE_STATIC]; /** Flags to indicate if the Signature parsing must be done * switching the source and dest (for ip addresses and ports) diff --git a/src/detect-snmp-community.c b/src/detect-snmp-community.c deleted file mode 100644 index 76c4bddd0ab6..000000000000 --- a/src/detect-snmp-community.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 2015-2019 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Pierre Chifflier - * - * Set up of the "snmp.community" keyword to allow content - * inspections on the decoded snmp community. - */ - -#include "suricata-common.h" -#include "conf.h" -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-mpm.h" -#include "detect-engine-prefilter.h" -#include "detect-engine-content-inspection.h" -#include "detect-snmp-community.h" -#include "app-layer-parser.h" -#include "rust.h" - -static int DetectSNMPCommunitySetup(DetectEngineCtx *, Signature *, - const char *); -static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, - const int list_id); -static int g_snmp_rust_id = 0; - -void DetectSNMPCommunityRegister(void) -{ - sigmatch_table[DETECT_AL_SNMP_COMMUNITY].name = "snmp.community"; - sigmatch_table[DETECT_AL_SNMP_COMMUNITY].desc = - "SNMP content modifier to match on the SNMP community"; - sigmatch_table[DETECT_AL_SNMP_COMMUNITY].Setup = DetectSNMPCommunitySetup; - sigmatch_table[DETECT_AL_SNMP_COMMUNITY].url = "/rules/snmp-keywords.html#snmp-community"; - sigmatch_table[DETECT_AL_SNMP_COMMUNITY].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER; - - /* register inspect engines */ - DetectAppLayerInspectEngineRegister("snmp.community", ALPROTO_SNMP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerMpmRegister("snmp.community", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister, - GetData, ALPROTO_SNMP, 0); - DetectAppLayerInspectEngineRegister("snmp.community", ALPROTO_SNMP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerMpmRegister("snmp.community", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister, - GetData, ALPROTO_SNMP, 0); - - DetectBufferTypeSetDescriptionByName("snmp.community", "SNMP Community identifier"); - - g_snmp_rust_id = DetectBufferTypeGetByName("snmp.community"); -} - -static int DetectSNMPCommunitySetup(DetectEngineCtx *de_ctx, Signature *s, - const char *str) -{ - if (DetectBufferSetActiveList(de_ctx, s, g_snmp_rust_id) < 0) - return -1; - - if (DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0) - return -1; - - return 0; -} - -static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *f, - const uint8_t flow_flags, void *txv, const int list_id) -{ - InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); - if (buffer->inspect == NULL) { - uint32_t data_len = 0; - const uint8_t *data = NULL; - - rs_snmp_tx_get_community(txv, &data, &data_len); - if (data == NULL || data_len == 0) { - return NULL; - } - - InspectionBufferSetup(det_ctx, list_id, buffer, data, data_len); - InspectionBufferApplyTransforms(buffer, transforms); - } - - return buffer; -} diff --git a/src/detect-snmp-community.h b/src/detect-snmp-community.h deleted file mode 100644 index 082d9c1970f6..000000000000 --- a/src/detect-snmp-community.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2015-2019 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author FirstName LastName - */ - -#ifndef SURICATA_DETECT_SNMP_COMMUNITY_H -#define SURICATA_DETECT_SNMP_COMMUNITY_H - -void DetectSNMPCommunityRegister(void); - -#endif /* SURICATA_DETECT_SNMP_COMMUNITY_H */ diff --git a/src/detect-snmp-pdu_type.c b/src/detect-snmp-pdu_type.c deleted file mode 100644 index 331abce7f355..000000000000 --- a/src/detect-snmp-pdu_type.c +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright (C) 2015-2020 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Pierre Chifflier - */ - -#include "suricata-common.h" -#include "conf.h" -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-content-inspection.h" -#include "detect-snmp-pdu_type.h" -#include "app-layer-parser.h" -#include "rust.h" - -/** - * [snmp.pdu_type]:; - */ -#define PARSE_REGEX "^\\s*([0-9]+)\\s*$" -static DetectParseRegex parse_regex; - -typedef struct DetectSNMPPduTypeData_ { - uint32_t pdu_type; -} DetectSNMPPduTypeData; - -static DetectSNMPPduTypeData *DetectSNMPPduTypeParse (const char *); -static int DetectSNMPPduTypeSetup (DetectEngineCtx *, Signature *s, const char *str); -static void DetectSNMPPduTypeFree(DetectEngineCtx *, void *); -#ifdef UNITTESTS -static void DetectSNMPPduTypeRegisterTests(void); -#endif -static int g_snmp_pdu_type_buffer_id = 0; - -static int DetectSNMPPduTypeMatch (DetectEngineThreadCtx *, Flow *, - uint8_t, void *, void *, const Signature *, - const SigMatchCtx *); - -void DetectSNMPPduTypeRegister(void) -{ - sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].name = "snmp.pdu_type"; - sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].desc = "match SNMP PDU type"; - sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].url = "/rules/snmp-keywords.html#snmp-pdu-type"; - sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].Match = NULL; - sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].AppLayerTxMatch = DetectSNMPPduTypeMatch; - sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].Setup = DetectSNMPPduTypeSetup; - sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].Free = DetectSNMPPduTypeFree; -#ifdef UNITTESTS - sigmatch_table[DETECT_AL_SNMP_PDU_TYPE].RegisterTests = DetectSNMPPduTypeRegisterTests; -#endif - - DetectSetupParseRegexes(PARSE_REGEX, &parse_regex); - - DetectAppLayerInspectEngineRegister("snmp.pdu_type", ALPROTO_SNMP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - - DetectAppLayerInspectEngineRegister("snmp.pdu_type", ALPROTO_SNMP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_snmp_pdu_type_buffer_id = DetectBufferTypeGetByName("snmp.pdu_type"); -} - -/** - * \internal - * \brief Function to match pdu_type of a TX - * - * \param t Pointer to thread vars. - * \param det_ctx Pointer to the pattern matcher thread. - * \param f Pointer to the current flow. - * \param flags Flags. - * \param state App layer state. - * \param s Pointer to the Signature. - * \param m Pointer to the sigmatch that we will cast into - * DetectSNMPPduTypeData. - * - * \retval 0 no match. - * \retval 1 match. - */ -static int DetectSNMPPduTypeMatch (DetectEngineThreadCtx *det_ctx, - Flow *f, uint8_t flags, void *state, - void *txv, const Signature *s, - const SigMatchCtx *ctx) -{ - SCEnter(); - - const DetectSNMPPduTypeData *dd = (const DetectSNMPPduTypeData *)ctx; - uint32_t pdu_type; - rs_snmp_tx_get_pdu_type(txv, &pdu_type); - SCLogDebug("pdu_type %u ref_pdu_type %d", - pdu_type, dd->pdu_type); - if (pdu_type == dd->pdu_type) - SCReturnInt(1); - SCReturnInt(0); -} - -/** - * \internal - * \brief Function to parse options passed via snmp.pdu_type keywords. - * - * \param rawstr Pointer to the user provided options. - * - * \retval dd pointer to DetectSNMPPduTypeData on success. - * \retval NULL on failure. - */ -static DetectSNMPPduTypeData *DetectSNMPPduTypeParse (const char *rawstr) -{ - DetectSNMPPduTypeData *dd = NULL; - int res = 0; - size_t pcre2len; - char value1[20] = ""; - char *endptr = NULL; - - pcre2_match_data *match = NULL; - int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0); - if (ret != 2) { - SCLogError("Parse error %s", rawstr); - goto error; - } - - pcre2len = sizeof(value1); - res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)value1, &pcre2len); - if (res < 0) { - SCLogError("pcre2_substring_copy_bynumber failed"); - goto error; - } - - dd = SCCalloc(1, sizeof(DetectSNMPPduTypeData)); - if (unlikely(dd == NULL)) - goto error; - - /* set the value */ - dd->pdu_type = strtoul(value1, &endptr, 10); - if (endptr == NULL || *endptr != '\0') { - SCLogError("invalid character as arg " - "to snmp.pdu_type keyword"); - goto error; - } - - pcre2_match_data_free(match); - return dd; - -error: - if (match) { - pcre2_match_data_free(match); - } - if (dd) - SCFree(dd); - return NULL; -} - -/** - * \brief Function to add the parsed snmp pdu_type field into the current signature. - * - * \param de_ctx Pointer to the Detection Engine Context. - * \param s Pointer to the Current Signature. - * \param rawstr Pointer to the user provided flags options. - * \param type Defines if this is notBefore or notAfter. - * - * \retval 0 on Success. - * \retval -1 on Failure. - */ -static int DetectSNMPPduTypeSetup (DetectEngineCtx *de_ctx, Signature *s, - const char *rawstr) -{ - DetectSNMPPduTypeData *dd = NULL; - - if (DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0) - return -1; - - dd = DetectSNMPPduTypeParse(rawstr); - if (dd == NULL) { - SCLogError("Parsing \'%s\' failed", rawstr); - goto error; - } - - /* okay so far so good, lets get this into a SigMatch - * and put it in the Signature. */ - - SCLogDebug("snmp.pdu_type %d", dd->pdu_type); - if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_SNMP_PDU_TYPE, (SigMatchCtx *)dd, - g_snmp_pdu_type_buffer_id) == NULL) { - goto error; - } - return 0; - -error: - DetectSNMPPduTypeFree(de_ctx, dd); - return -1; -} - -/** - * \internal - * \brief Function to free memory associated with DetectSNMPPduTypeData. - * - * \param de_ptr Pointer to DetectSNMPPduTypeData. - */ -static void DetectSNMPPduTypeFree(DetectEngineCtx *de_ctx, void *ptr) -{ - SCFree(ptr); -} - -#ifdef UNITTESTS -#include "tests/detect-snmp-pdu_type.c" -#endif /* UNITTESTS */ diff --git a/src/detect-snmp-pdu_type.h b/src/detect-snmp-pdu_type.h deleted file mode 100644 index a01dc98d4580..000000000000 --- a/src/detect-snmp-pdu_type.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2015-2019 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Pierre Chifflier - */ - -#ifndef SURICATA_DETECT_SNMP_PDU_TYPE_H -#define SURICATA_DETECT_SNMP_PDU_TYPE_H - -void DetectSNMPPduTypeRegister(void); - -#endif /* SURICATA_DETECT_SNMP_PDU_TYPE_H */ diff --git a/src/detect-snmp-usm.c b/src/detect-snmp-usm.c deleted file mode 100644 index fd1a814d164d..000000000000 --- a/src/detect-snmp-usm.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include "suricata-common.h" -#include "rust.h" -#include "detect-snmp-usm.h" -#include "detect-engine.h" -#include "detect-engine-mpm.h" -#include "detect-engine-prefilter.h" -#include "detect-parse.h" - -static int g_buffer_id = 0; - -static int DetectSNMPUsmSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) -{ - if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0) - return -1; - - if (DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0) - return -1; - - return 0; -} - -static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, - const int list_id) -{ - InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); - if (buffer->inspect == NULL) { - uint32_t data_len = 0; - const uint8_t *data = NULL; - - rs_snmp_tx_get_usm(txv, &data, &data_len); - if (data == NULL || data_len == 0) { - return NULL; - } - - InspectionBufferSetup(det_ctx, list_id, buffer, data, data_len); - InspectionBufferApplyTransforms(buffer, transforms); - } - - return buffer; -} - -void DetectSNMPUsmRegister(void) -{ - sigmatch_table[DETECT_AL_SNMP_USM].name = "snmp.usm"; - sigmatch_table[DETECT_AL_SNMP_USM].desc = "SNMP content modifier to match on the SNMP usm"; - sigmatch_table[DETECT_AL_SNMP_USM].Setup = DetectSNMPUsmSetup; - - sigmatch_table[DETECT_AL_SNMP_USM].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; - - /* register inspect engines */ - DetectAppLayerInspectEngineRegister("snmp.usm", ALPROTO_SNMP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerMpmRegister("snmp.usm", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister, - GetData, ALPROTO_SNMP, 0); - DetectAppLayerInspectEngineRegister("snmp.usm", ALPROTO_SNMP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerMpmRegister("snmp.usm", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister, - GetData, ALPROTO_SNMP, 0); - - DetectBufferTypeSetDescriptionByName("snmp.usm", "SNMP USM"); - - g_buffer_id = DetectBufferTypeGetByName("snmp.usm"); -} diff --git a/src/detect-snmp-usm.h b/src/detect-snmp-usm.h deleted file mode 100644 index 9c86dad807b7..000000000000 --- a/src/detect-snmp-usm.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#ifndef SURICATA_DETECT_SNMP_USM_H -#define SURICATA_DETECT_SNMP_USM_H - -void DetectSNMPUsmRegister(void); - -#endif /* SURICATA_DETECT_SNMP_USM_H */ diff --git a/src/detect-snmp-version.c b/src/detect-snmp-version.c deleted file mode 100644 index cde70f251024..000000000000 --- a/src/detect-snmp-version.c +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2015-2020 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Pierre Chifflier - */ - -#include "suricata-common.h" -#include "conf.h" -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-content-inspection.h" -#include "detect-snmp-version.h" -#include "detect-engine-uint.h" -#include "app-layer-parser.h" -#include "rust.h" - - -static int DetectSNMPVersionSetup (DetectEngineCtx *, Signature *s, const char *str); -static void DetectSNMPVersionFree(DetectEngineCtx *, void *); -#ifdef UNITTESTS -static void DetectSNMPVersionRegisterTests(void); -#endif -static int g_snmp_version_buffer_id = 0; - -static int DetectSNMPVersionMatch (DetectEngineThreadCtx *, Flow *, - uint8_t, void *, void *, const Signature *, - const SigMatchCtx *); - -/** - * \brief Registration function for snmp.procedure keyword. - */ -void DetectSNMPVersionRegister (void) -{ - sigmatch_table[DETECT_AL_SNMP_VERSION].name = "snmp.version"; - sigmatch_table[DETECT_AL_SNMP_VERSION].desc = "match SNMP version"; - sigmatch_table[DETECT_AL_SNMP_VERSION].url = "/rules/snmp-keywords.html#snmp-version"; - sigmatch_table[DETECT_AL_SNMP_VERSION].Match = NULL; - sigmatch_table[DETECT_AL_SNMP_VERSION].AppLayerTxMatch = DetectSNMPVersionMatch; - sigmatch_table[DETECT_AL_SNMP_VERSION].Setup = DetectSNMPVersionSetup; - sigmatch_table[DETECT_AL_SNMP_VERSION].Free = DetectSNMPVersionFree; -#ifdef UNITTESTS - sigmatch_table[DETECT_AL_SNMP_VERSION].RegisterTests = DetectSNMPVersionRegisterTests; -#endif - - DetectAppLayerInspectEngineRegister("snmp.version", ALPROTO_SNMP, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectGenericList, NULL); - - DetectAppLayerInspectEngineRegister("snmp.version", ALPROTO_SNMP, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectGenericList, NULL); - - g_snmp_version_buffer_id = DetectBufferTypeGetByName("snmp.version"); -} - -/** - * \internal - * \brief Function to match version of a TX - * - * \param t Pointer to thread vars. - * \param det_ctx Pointer to the pattern matcher thread. - * \param f Pointer to the current flow. - * \param flags Flags. - * \param state App layer state. - * \param s Pointer to the Signature. - * \param m Pointer to the sigmatch that we will cast into - * DetectU32Data. - * - * \retval 0 no match. - * \retval 1 match. - */ -static int DetectSNMPVersionMatch (DetectEngineThreadCtx *det_ctx, - Flow *f, uint8_t flags, void *state, - void *txv, const Signature *s, - const SigMatchCtx *ctx) -{ - SCEnter(); - - const DetectU32Data *dd = (const DetectU32Data *)ctx; - uint32_t version; - rs_snmp_tx_get_version(txv, &version); - SCLogDebug("version %u mode %u ref_version %d", version, dd->mode, dd->arg1); - if (DetectU32Match(version, dd)) - SCReturnInt(1); - SCReturnInt(0); -} - -/** - * \internal - * \brief Function to parse options passed via snmp.version keywords. - * - * \param rawstr Pointer to the user provided options. - * - * \retval dd pointer to DetectU32Data on success. - * \retval NULL on failure. - */ -static DetectU32Data *DetectSNMPVersionParse(const char *rawstr) -{ - return DetectU32Parse(rawstr); -} - - - -/** - * \brief Function to add the parsed snmp version field into the current signature. - * - * \param de_ctx Pointer to the Detection Engine Context. - * \param s Pointer to the Current Signature. - * \param rawstr Pointer to the user provided flags options. - * \param type Defines if this is notBefore or notAfter. - * - * \retval 0 on Success. - * \retval -1 on Failure. - */ -static int DetectSNMPVersionSetup (DetectEngineCtx *de_ctx, Signature *s, - const char *rawstr) -{ - DetectU32Data *dd = NULL; - - if (DetectSignatureSetAppProto(s, ALPROTO_SNMP) != 0) - return -1; - - dd = DetectSNMPVersionParse(rawstr); - if (dd == NULL) { - SCLogError("Parsing \'%s\' failed", rawstr); - goto error; - } - - /* okay so far so good, lets get this into a SigMatch - * and put it in the Signature. */ - - SCLogDebug("snmp.version %d", dd->arg1); - if (SigMatchAppendSMToList(de_ctx, s, DETECT_AL_SNMP_VERSION, (SigMatchCtx *)dd, - g_snmp_version_buffer_id) == NULL) { - goto error; - } - return 0; - -error: - DetectSNMPVersionFree(de_ctx, dd); - return -1; -} - -/** - * \internal - * \brief Function to free memory associated with DetectU32Data. - * - * \param de_ptr Pointer to DetectU32Data. - */ -static void DetectSNMPVersionFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u32_free(ptr); -} - - -#ifdef UNITTESTS -#include "tests/detect-snmp-version.c" -#endif /* UNITTESTS */ diff --git a/src/detect-snmp-version.h b/src/detect-snmp-version.h deleted file mode 100644 index cd71b59a245c..000000000000 --- a/src/detect-snmp-version.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2015-2019 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Pierre Chifflier - */ - -#ifndef SURICATA_DETECT_SNMP_VERSION_H -#define SURICATA_DETECT_SNMP_VERSION_H - -void DetectSNMPVersionRegister(void); - -#endif /* SURICATA_DETECT_SNMP_VERSION_H */ diff --git a/src/detect-websocket.c b/src/detect-websocket.c deleted file mode 100644 index 91f650c85c55..000000000000 --- a/src/detect-websocket.c +++ /dev/null @@ -1,251 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#include "suricata-common.h" -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-content-inspection.h" -#include "detect-engine-uint.h" -#include "detect-engine-prefilter.h" -#include "detect-websocket.h" - -#include "rust.h" - -static int websocket_tx_id = 0; -static int websocket_payload_id = 0; - -/** - * \internal - * \brief this function will free memory associated with DetectWebSocketOpcodeData - * - * \param de pointer to DetectWebSocketOpcodeData - */ -static void DetectWebSocketOpcodeFree(DetectEngineCtx *de_ctx, void *de_ptr) -{ - rs_detect_u8_free(de_ptr); -} - -/** - * \internal - * \brief Function to match opcode of a websocket tx - * - * \param det_ctx Pointer to the pattern matcher thread. - * \param f Pointer to the current flow. - * \param flags Flags. - * \param state App layer state. - * \param txv Pointer to the transaction. - * \param s Pointer to the Signature. - * \param ctx Pointer to the sigmatch that we will cast into DetectWebSocketOpcodeData. - * - * \retval 0 no match. - * \retval 1 match. - */ -static int DetectWebSocketOpcodeMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) -{ - const DetectU8Data *de = (const DetectU8Data *)ctx; - uint8_t opc = SCWebSocketGetOpcode(txv); - return DetectU8Match(opc, de); -} - -/** - * \internal - * \brief this function is used to add the parsed sigmatch into the current signature - * - * \param de_ctx pointer to the Detection Engine Context - * \param s pointer to the Current Signature - * \param rawstr pointer to the user provided options - * - * \retval 0 on Success - * \retval -1 on Failure - */ -static int DetectWebSocketOpcodeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) < 0) - return -1; - - DetectU8Data *de = SCWebSocketParseOpcode(rawstr); - if (de == NULL) - return -1; - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_WEBSOCKET_OPCODE, (SigMatchCtx *)de, websocket_tx_id) == NULL) { - DetectWebSocketOpcodeFree(de_ctx, de); - return -1; - } - - return 0; -} - -/** - * \internal - * \brief this function will free memory associated with DetectWebSocketMaskData - * - * \param de pointer to DetectWebSocketMaskData - */ -static void DetectWebSocketMaskFree(DetectEngineCtx *de_ctx, void *de_ptr) -{ - rs_detect_u32_free(de_ptr); -} - -static int DetectWebSocketMaskMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) -{ - uint32_t val; - const DetectU32Data *du32 = (const DetectU32Data *)ctx; - if (SCWebSocketGetMask(txv, &val)) { - return DetectU32Match(val, du32); - } - return 0; -} - -static int DetectWebSocketMaskSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) < 0) - return -1; - - DetectU32Data *du32 = DetectU32Parse(rawstr); - if (du32 == NULL) - return -1; - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_WEBSOCKET_MASK, (SigMatchCtx *)du32, websocket_tx_id) == NULL) { - DetectWebSocketMaskFree(de_ctx, du32); - return -1; - } - - return 0; -} - -static void DetectWebSocketFlagsFree(DetectEngineCtx *de_ctx, void *de_ptr) -{ - rs_detect_u8_free(de_ptr); -} - -static int DetectWebSocketFlagsMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, - void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) -{ - const DetectU8Data *de = (const DetectU8Data *)ctx; - uint8_t val = SCWebSocketGetFlags(txv); - return DetectU8Match(val, de); -} - -static int DetectWebSocketFlagsSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) -{ - if (DetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) < 0) - return -1; - - DetectU8Data *de = SCWebSocketParseFlags(rawstr); - if (de == NULL) - return -1; - - if (SigMatchAppendSMToList( - de_ctx, s, DETECT_WEBSOCKET_FLAGS, (SigMatchCtx *)de, websocket_tx_id) == NULL) { - DetectWebSocketOpcodeFree(de_ctx, de); - return -1; - } - - return 0; -} - -static int DetectWebSocketPayloadSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rulestr) -{ - if (DetectBufferSetActiveList(de_ctx, s, websocket_payload_id) < 0) - return -1; - - if (DetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0) - return -1; - - return 0; -} - -static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv, - const int list_id) -{ - InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); - if (buffer->inspect == NULL) { - const uint8_t *b = NULL; - uint32_t b_len = 0; - - if (!SCWebSocketGetPayload(txv, &b, &b_len)) - return NULL; - if (b == NULL || b_len == 0) - return NULL; - - InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len); - InspectionBufferApplyTransforms(buffer, transforms); - } - return buffer; -} - -/** - * \brief Registration function for websocket.opcode: keyword - */ -void DetectWebsocketRegister(void) -{ - sigmatch_table[DETECT_WEBSOCKET_OPCODE].name = "websocket.opcode"; - sigmatch_table[DETECT_WEBSOCKET_OPCODE].desc = "match WebSocket opcode"; - sigmatch_table[DETECT_WEBSOCKET_OPCODE].url = "/rules/websocket-keywords.html#websocket-opcode"; - sigmatch_table[DETECT_WEBSOCKET_OPCODE].AppLayerTxMatch = DetectWebSocketOpcodeMatch; - sigmatch_table[DETECT_WEBSOCKET_OPCODE].Setup = DetectWebSocketOpcodeSetup; - sigmatch_table[DETECT_WEBSOCKET_OPCODE].Free = DetectWebSocketOpcodeFree; - - DetectAppLayerInspectEngineRegister("websocket.tx", ALPROTO_WEBSOCKET, SIG_FLAG_TOSERVER, 1, - DetectEngineInspectGenericList, NULL); - DetectAppLayerInspectEngineRegister("websocket.tx", ALPROTO_WEBSOCKET, SIG_FLAG_TOCLIENT, 1, - DetectEngineInspectGenericList, NULL); - - websocket_tx_id = DetectBufferTypeGetByName("websocket.tx"); - - sigmatch_table[DETECT_WEBSOCKET_MASK].name = "websocket.mask"; - sigmatch_table[DETECT_WEBSOCKET_MASK].desc = "match WebSocket mask"; - sigmatch_table[DETECT_WEBSOCKET_MASK].url = "/rules/websocket-keywords.html#websocket-mask"; - sigmatch_table[DETECT_WEBSOCKET_MASK].AppLayerTxMatch = DetectWebSocketMaskMatch; - sigmatch_table[DETECT_WEBSOCKET_MASK].Setup = DetectWebSocketMaskSetup; - sigmatch_table[DETECT_WEBSOCKET_MASK].Free = DetectWebSocketMaskFree; - - sigmatch_table[DETECT_WEBSOCKET_FLAGS].name = "websocket.flags"; - sigmatch_table[DETECT_WEBSOCKET_FLAGS].desc = "match WebSocket flags"; - sigmatch_table[DETECT_WEBSOCKET_FLAGS].url = "/rules/websocket-keywords.html#websocket-flags"; - sigmatch_table[DETECT_WEBSOCKET_FLAGS].AppLayerTxMatch = DetectWebSocketFlagsMatch; - sigmatch_table[DETECT_WEBSOCKET_FLAGS].Setup = DetectWebSocketFlagsSetup; - sigmatch_table[DETECT_WEBSOCKET_FLAGS].Free = DetectWebSocketFlagsFree; - - sigmatch_table[DETECT_WEBSOCKET_PAYLOAD].name = "websocket.payload"; - sigmatch_table[DETECT_WEBSOCKET_PAYLOAD].desc = "match WebSocket payload"; - sigmatch_table[DETECT_WEBSOCKET_PAYLOAD].url = - "/rules/websocket-keywords.html#websocket-payload"; - sigmatch_table[DETECT_WEBSOCKET_PAYLOAD].Setup = DetectWebSocketPayloadSetup; - sigmatch_table[DETECT_WEBSOCKET_PAYLOAD].flags |= SIGMATCH_NOOPT; - DetectAppLayerInspectEngineRegister("websocket.payload", ALPROTO_WEBSOCKET, SIG_FLAG_TOSERVER, - 0, DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerInspectEngineRegister("websocket.payload", ALPROTO_WEBSOCKET, SIG_FLAG_TOCLIENT, - 0, DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerMpmRegister("websocket.payload", SIG_FLAG_TOSERVER, 2, - PrefilterGenericMpmRegister, GetData, ALPROTO_WEBSOCKET, 1); - DetectAppLayerMpmRegister("websocket.payload", SIG_FLAG_TOCLIENT, 2, - PrefilterGenericMpmRegister, GetData, ALPROTO_WEBSOCKET, 1); - websocket_payload_id = DetectBufferTypeGetByName("websocket.payload"); -} diff --git a/src/detect-websocket.h b/src/detect-websocket.h deleted file mode 100644 index 54e8a22ae4a8..000000000000 --- a/src/detect-websocket.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Philippe Antoine - */ - -#ifndef __DETECT_WEBSOCKET_H__ -#define __DETECT_WEBSOCKET_H__ - -void DetectWebsocketRegister(void); - -#endif /* __DETECT_WEBSOCKET_H__ */ diff --git a/src/detect.h b/src/detect.h index 5c1583074f05..87a4219de917 100644 --- a/src/detect.h +++ b/src/detect.h @@ -1029,8 +1029,8 @@ typedef struct DetectEngineCtx_ { /** per keyword flag indicating if a prefilter has been * set for it. If true, the setup function will have to * run. */ - bool sm_types_prefilter[DETECT_TBLSIZE]; - bool sm_types_silent_error[DETECT_TBLSIZE]; + bool *sm_types_prefilter; + bool *sm_types_silent_error; /* classification config parsing */ @@ -1574,7 +1574,7 @@ typedef struct DetectEngineMasterCtx_ { } DetectEngineMasterCtx; /* Table with all SigMatch registrations */ -extern SigTableElmt sigmatch_table[DETECT_TBLSIZE]; +extern SigTableElmt *sigmatch_table; /** Remember to add the options in SignatureIsIPOnly() at detect.c otherwise it wont be part of a signature group */ diff --git a/src/reputation.c b/src/reputation.c index 055aca13908f..88ee1b7ce5e3 100644 --- a/src/reputation.c +++ b/src/reputation.c @@ -580,18 +580,12 @@ int SRepInit(DetectEngineCtx *de_ctx) ConfNode *file = NULL; const char *filename = NULL; int init = 0; - int i = 0; de_ctx->srepCIDR_ctx = (SRepCIDRTree *)SCCalloc(1, sizeof(SRepCIDRTree)); if (de_ctx->srepCIDR_ctx == NULL) exit(EXIT_FAILURE); SRepCIDRTree *cidr_ctx = de_ctx->srepCIDR_ctx; - for (i = 0; i < SREP_MAX_CATS; i++) { - cidr_ctx->srepIPV4_tree[i] = NULL; - cidr_ctx->srepIPV6_tree[i] = NULL; - } - if (SRepGetVersion() == 0) { SC_ATOMIC_INIT(srep_eversion); init = 1; diff --git a/src/suricata.c b/src/suricata.c index 48a51b815f4b..0ff1bdbb8398 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -393,6 +393,7 @@ void GlobalsDestroy(void) FeatureTrackingRelease(); SCProtoNameRelease(); TimeDeinit(); + SigTableCleanup(); TmqhCleanup(); TmModuleRunDeInit(); ParseSizeDeinit(); diff --git a/src/tests/detect-snmp-pdu_type.c b/src/tests/detect-snmp-pdu_type.c deleted file mode 100644 index 0e7693bcc625..000000000000 --- a/src/tests/detect-snmp-pdu_type.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 2019 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include "util-unittest.h" -#include "util-unittest-helper.h" - -/** - * \test This is a test for a valid value 2. - * - * \retval 1 on success. - * \retval 0 on failure. - */ -static int SNMPValidityTestParse01 (void) -{ - DetectSNMPPduTypeData *dd = NULL; - dd = DetectSNMPPduTypeParse("2"); - FAIL_IF_NULL(dd); - FAIL_IF_NOT(dd->pdu_type == 2); - DetectSNMPPduTypeFree(NULL, dd); - PASS; -} - -static void DetectSNMPPduTypeRegisterTests(void) -{ - UtRegisterTest("SNMPValidityTestParse01", SNMPValidityTestParse01); -} diff --git a/src/tests/detect-snmp-version.c b/src/tests/detect-snmp-version.c deleted file mode 100644 index 5da24b1b8700..000000000000 --- a/src/tests/detect-snmp-version.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (C) 2019 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include "util-unittest.h" -#include "util-unittest-helper.h" - -/** - * \test This is a test for a valid value 2. - * - * \retval 1 on success. - * \retval 0 on failure. - */ -static int SNMPValidityTestParse01 (void) -{ - DetectU32Data *dd = NULL; - dd = DetectSNMPVersionParse("2"); - FAIL_IF_NULL(dd); - FAIL_IF_NOT(dd->arg1 == 2 && dd->mode == DETECT_UINT_EQ); - DetectSNMPVersionFree(NULL, dd); - PASS; -} - -/** - * \test This is a test for a valid value >2. - * - * \retval 1 on success. - * \retval 0 on failure. - */ -static int SNMPValidityTestParse02 (void) -{ - DetectU32Data *dd = NULL; - dd = DetectSNMPVersionParse(">2"); - FAIL_IF_NULL(dd); - FAIL_IF_NOT(dd->arg1 == 2 && dd->mode == DETECT_UINT_GT); - DetectSNMPVersionFree(NULL, dd); - PASS; -} - -static void DetectSNMPVersionRegisterTests(void) -{ - UtRegisterTest("SNMPValidityTestParse01", SNMPValidityTestParse01); - UtRegisterTest("SNMPValidityTestParse02", SNMPValidityTestParse02); -} diff --git a/src/util-profiling.c b/src/util-profiling.c index 70b187e97a8f..11b853566278 100644 --- a/src/util-profiling.c +++ b/src/util-profiling.c @@ -1432,6 +1432,7 @@ void SCProfilingInit(void) SC_ATOMIC_INIT(profiling_rules_active); SC_ATOMIC_INIT(samples); intmax_t rate_v = 0; + ConfNode *conf; (void)ConfGetInt("profiling.sample-rate", &rate_v); if (rate_v > 0 && rate_v < INT_MAX) { @@ -1448,6 +1449,11 @@ void SCProfilingInit(void) else SCLogInfo("profiling runs for every packet"); } + + conf = ConfGetNode("profiling.rules"); + if (ConfNodeChildValueIsTrue(conf, "active")) { + SC_ATOMIC_SET(profiling_rules_active, 1); + } } /* see if we want to profile rules for this packet */ @@ -1466,7 +1472,6 @@ int SCProfileRuleStart(Packet *p) p->flags |= PKT_PROFILE; return 1; } - return 0; } diff --git a/suricata.yaml.in b/suricata.yaml.in index 1150f7ab9a97..897c71027a62 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -1810,6 +1810,10 @@ profiling: enabled: yes filename: rule_perf.log append: yes + # Set active to yes to enable rules profiling at start + # if set to no (default), the rules profiling will have to be started + # via unix socket commands. + #active:no # Sort options: ticks, avgticks, checks, matches, maxticks # If commented out all the sort options will be used.