From: Philippe Antoine Date: Wed, 30 Oct 2024 11:09:33 +0000 (+0100) Subject: transforms: move http headers transforms to rust X-Git-Tag: suricata-8.0.0-beta1~729 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45e0acf772cb30320b960bd4d224e2ec945e7c22;p=thirdparty%2Fsuricata.git transforms: move http headers transforms to rust Ticket: 7229 --- diff --git a/rust/src/detect/transforms/http_headers.rs b/rust/src/detect/transforms/http_headers.rs new file mode 100644 index 0000000000..939cbb3d33 --- /dev/null +++ b/rust/src/detect/transforms/http_headers.rs @@ -0,0 +1,187 @@ +/* Copyright (C) 2024 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. + */ + +use super::{ + DetectHelperTransformRegister, DetectSignatureAddTransform, InspectionBufferCheckAndExpand, + InspectionBufferLength, InspectionBufferPtr, InspectionBufferTruncate, SCTransformTableElmt, +}; +use crate::detect::SIGMATCH_NOOPT; + +use std::os::raw::{c_int, c_void}; +use std::ptr; + +static mut G_TRANSFORM_HEADER_LOWER_ID: c_int = 0; +static mut G_TRANSFORM_STRIP_PSEUDO_ID: c_int = 0; + +#[no_mangle] +unsafe extern "C" fn header_lowersetup( + _de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + return DetectSignatureAddTransform(s, G_TRANSFORM_HEADER_LOWER_ID, ptr::null_mut()); +} + +fn header_lowertransform_do(input: &[u8], output: &mut [u8]) { + let mut state_value = false; // false in name, true in value + for (i, o) in input.iter().zip(output.iter_mut()) { + if !state_value { + if (*i) == b':' { + state_value = true; + *o = *i; + } else { + *o = (*i).to_ascii_lowercase(); + } + } else { + *o = *i; + if (*i) == b'\n' { + state_value = false; + } + } + } +} + +#[no_mangle] +unsafe extern "C" fn header_lowertransform(buffer: *mut c_void, _ctx: *mut c_void) { + let input = InspectionBufferPtr(buffer); + let input_len = InspectionBufferLength(buffer); + if input.is_null() || input_len == 0 { + return; + } + let input = build_slice!(input, input_len as usize); + + let output = InspectionBufferCheckAndExpand(buffer, input_len); + if output.is_null() { + // allocation failure + return; + } + let output = std::slice::from_raw_parts_mut(output, input_len as usize); + + header_lowertransform_do(input, output); + + InspectionBufferTruncate(buffer, input_len); +} + +#[no_mangle] +pub unsafe extern "C" fn DetectTransformHeaderLowercaseRegister() { + let kw = SCTransformTableElmt { + name: b"header_lowercase\0".as_ptr() as *const libc::c_char, + desc: b"modify buffer via lowercaseing header names\0".as_ptr() as *const libc::c_char, + url: b"/rules/transforms.html#header_lowercase\0".as_ptr() as *const libc::c_char, + Setup: header_lowersetup, + flags: SIGMATCH_NOOPT, + Transform: header_lowertransform, + Free: None, + TransformValidate: None, + }; + unsafe { + G_TRANSFORM_HEADER_LOWER_ID = DetectHelperTransformRegister(&kw); + if G_TRANSFORM_HEADER_LOWER_ID < 0 { + SCLogWarning!("Failed registering transform tolower"); + } + } +} + +#[no_mangle] +unsafe extern "C" fn strip_pseudo_setup( + _de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + return DetectSignatureAddTransform(s, G_TRANSFORM_STRIP_PSEUDO_ID, ptr::null_mut()); +} + +fn strip_pseudo_transform_do(input: &[u8], output: &mut [u8]) -> u32 { + let mut nb = 0; + for subslice in input.split_inclusive(|c| *c == b'\n') { + if !subslice.is_empty() && subslice[0] != b':' { + output[nb..nb + subslice.len()].copy_from_slice(subslice); + nb += subslice.len(); + } + } + return nb as u32; +} + +#[no_mangle] +unsafe extern "C" fn strip_pseudo_transform(buffer: *mut c_void, _ctx: *mut c_void) { + let input = InspectionBufferPtr(buffer); + let input_len = InspectionBufferLength(buffer); + if input.is_null() || input_len == 0 { + return; + } + let input = build_slice!(input, input_len as usize); + + let output = InspectionBufferCheckAndExpand(buffer, input_len); + if output.is_null() { + // allocation failure + return; + } + let output = std::slice::from_raw_parts_mut(output, input_len as usize); + + let out_len = strip_pseudo_transform_do(input, output); + + InspectionBufferTruncate(buffer, out_len); +} + +#[no_mangle] +pub unsafe extern "C" fn DetectTransformStripPseudoHeadersRegister() { + let kw = SCTransformTableElmt { + name: b"strip_pseudo_headers\0".as_ptr() as *const libc::c_char, + desc: b"modify buffer via stripping pseudo headers\0".as_ptr() as *const libc::c_char, + url: b"/rules/transforms.html#strip_pseudo_headers\0".as_ptr() as *const libc::c_char, + Setup: strip_pseudo_setup, + flags: SIGMATCH_NOOPT, + Transform: strip_pseudo_transform, + Free: None, + TransformValidate: None, + }; + unsafe { + G_TRANSFORM_STRIP_PSEUDO_ID = DetectHelperTransformRegister(&kw); + if G_TRANSFORM_STRIP_PSEUDO_ID < 0 { + SCLogWarning!("Failed registering transform toupper"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_header_lowertransform() { + let buf = b"Header1: Value1\nheader2:Value2\n"; + let mut out = vec![0; buf.len()]; + header_lowertransform_do(buf, &mut out); + assert_eq!(out, b"header1: Value1\nheader2:Value2\n"); + } + + #[test] + fn test_strip_pseudo_transform() { + let buf = b"Header1: Value1\n:method:get\nheader2:Value2\n"; + let mut out = vec![0; buf.len()]; + let nb = strip_pseudo_transform_do(buf, &mut out); + assert_eq!(&out[..nb as usize], b"Header1: Value1\nheader2:Value2\n"); + let buf = b":method:get"; + let mut out = vec![0; buf.len()]; + let nb = strip_pseudo_transform_do(buf, &mut out); + assert_eq!(nb, 0); + let buf = b"Header1: Value1\n:method:get"; + let mut out = vec![0; buf.len()]; + let nb = strip_pseudo_transform_do(buf, &mut out); + assert_eq!(&out[..nb as usize], b"Header1: Value1\n"); + let buf = b":method:get\nheader2:Value2"; + let mut out = vec![0; buf.len()]; + let nb = strip_pseudo_transform_do(buf, &mut out); + assert_eq!(&out[..nb as usize], b"header2:Value2"); + } +} diff --git a/rust/src/detect/transforms/mod.rs b/rust/src/detect/transforms/mod.rs index 39f1bbac40..6e31de80fc 100644 --- a/rust/src/detect/transforms/mod.rs +++ b/rust/src/detect/transforms/mod.rs @@ -23,6 +23,7 @@ pub mod casechange; pub mod compress_whitespace; pub mod dotprefix; pub mod hash; +pub mod http_headers; pub mod strip_whitespace; #[repr(C)] diff --git a/src/Makefile.am b/src/Makefile.am index b7cc8ccd1d..353a486bf0 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -306,9 +306,7 @@ noinst_HEADERS = \ detect-tls-random.h \ detect-tos.h \ detect-transform-base64.h \ - detect-transform-header-lowercase.h \ detect-transform-pcrexform.h \ - detect-transform-strip-pseudo-headers.h \ detect-transform-urldecode.h \ detect-transform-xor.h \ detect-ttl.h \ @@ -868,9 +866,7 @@ libsuricata_c_a_SOURCES = \ detect-tls-random.c \ detect-tos.c \ detect-transform-base64.c \ - detect-transform-header-lowercase.c \ detect-transform-pcrexform.c \ - detect-transform-strip-pseudo-headers.c \ detect-transform-urldecode.c \ detect-transform-xor.c \ detect-ttl.c \ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index a5bc4ddb4c..3d5ba9eaf5 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -215,11 +215,9 @@ #include "detect-ftpdata.h" #include "detect-engine-content-inspection.h" -#include "detect-transform-strip-pseudo-headers.h" #include "detect-transform-pcrexform.h" #include "detect-transform-urldecode.h" #include "detect-transform-xor.h" -#include "detect-transform-header-lowercase.h" #include "detect-transform-base64.h" #include "util-rule-vars.h" diff --git a/src/detect-transform-header-lowercase.c b/src/detect-transform-header-lowercase.c deleted file mode 100644 index 7c776201b3..0000000000 --- a/src/detect-transform-header-lowercase.c +++ /dev/null @@ -1,88 +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 - * - * Implements the header_lowercase transform keyword with option support - */ - -#include "suricata-common.h" -#include "detect.h" -#include "detect-engine.h" -#include "detect-parse.h" -#include "detect-transform-header-lowercase.h" - -/** - * \internal - * \brief Apply the header_lowercase keyword to the last pattern match - * \param det_ctx detection engine ctx - * \param s signature - * \param optstr options string - * \retval 0 ok - * \retval -1 failure - */ -static int DetectTransformHeaderLowercaseSetup( - DetectEngineCtx *de_ctx, Signature *s, const char *optstr) -{ - SCEnter(); - int r = DetectSignatureAddTransform(s, DETECT_TRANSFORM_HEADER_LOWERCASE, NULL); - SCReturnInt(r); -} - -static void DetectTransformHeaderLowercase(InspectionBuffer *buffer, void *options) -{ - const uint8_t *input = buffer->inspect; - const uint32_t input_len = buffer->inspect_len; - if (input_len == 0) { - return; - } - uint8_t output[input_len]; - - // state 0 is header name, 1 is header value - int state = 0; - for (uint32_t i = 0; i < input_len; i++) { - if (state == 0) { - if (input[i] == ':') { - output[i] = input[i]; - state = 1; - } else { - output[i] = u8_tolower(input[i]); - } - } else { - output[i] = input[i]; - if (input[i] == '\n') { - state = 0; - } - } - } - InspectionBufferCopy(buffer, output, input_len); -} - -void DetectTransformHeaderLowercaseRegister(void) -{ - sigmatch_table[DETECT_TRANSFORM_HEADER_LOWERCASE].name = "header_lowercase"; - sigmatch_table[DETECT_TRANSFORM_HEADER_LOWERCASE].desc = - "modify buffer via lowercaseing header names"; - sigmatch_table[DETECT_TRANSFORM_HEADER_LOWERCASE].url = - "/rules/transforms.html#header_lowercase"; - sigmatch_table[DETECT_TRANSFORM_HEADER_LOWERCASE].Transform = DetectTransformHeaderLowercase; - sigmatch_table[DETECT_TRANSFORM_HEADER_LOWERCASE].Setup = DetectTransformHeaderLowercaseSetup; - sigmatch_table[DETECT_TRANSFORM_HEADER_LOWERCASE].flags |= SIGMATCH_NOOPT; -} diff --git a/src/detect-transform-header-lowercase.h b/src/detect-transform-header-lowercase.h deleted file mode 100644 index 55f194a86b..0000000000 --- a/src/detect-transform-header-lowercase.h +++ /dev/null @@ -1,30 +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_TRANSFORM_HEADER_LOWERCASE_H -#define SURICATA_DETECT_TRANSFORM_HEADER_LOWERCASE_H - -/* prototypes */ -void DetectTransformHeaderLowercaseRegister(void); - -#endif /* SURICATA_DETECT_TRANSFORM_HEADER_LOWERCASE_H */ diff --git a/src/detect-transform-strip-pseudo-headers.c b/src/detect-transform-strip-pseudo-headers.c deleted file mode 100644 index 450900d460..0000000000 --- a/src/detect-transform-strip-pseudo-headers.c +++ /dev/null @@ -1,100 +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 - * - * Implements the strip_pseudo_headers transform keyword with option support - */ - -#include "suricata-common.h" -#include "detect.h" -#include "detect-engine.h" -#include "detect-parse.h" -#include "detect-transform-strip-pseudo-headers.h" - -/** - * \internal - * \brief Apply the strip_pseudo_headers keyword to the last pattern match - * \param det_ctx detection engine ctx - * \param s signature - * \param optstr options string - * \retval 0 ok - * \retval -1 failure - */ -static int DetectTransformStripPseudoHeadersSetup( - DetectEngineCtx *de_ctx, Signature *s, const char *optstr) -{ - SCEnter(); - int r = DetectSignatureAddTransform(s, DETECT_TRANSFORM_STRIP_PSEUDO_HEADERS, NULL); - SCReturnInt(r); -} - -static void DetectTransformStripPseudoHeaders(InspectionBuffer *buffer, void *options) -{ - const uint8_t *input = buffer->inspect; - const uint32_t input_len = buffer->inspect_len; - if (input_len == 0) { - return; - } - uint8_t output[input_len]; - - bool new_line = true; - bool pseudo = false; - uint32_t j = 0; - for (uint32_t i = 0; i < input_len; i++) { - if (new_line) { - if (input[i] == ':') { - pseudo = true; - } - if (input[i] != '\r' && input[i] != '\n') { - new_line = false; - } - } else { - if (input[i] == '\n') { - new_line = true; - if (!pseudo) { - output[j] = input[i]; - j++; - } - pseudo = false; - continue; - } - } - if (!pseudo) { - output[j] = input[i]; - j++; - } - } - InspectionBufferCopy(buffer, output, j); -} - -void DetectTransformStripPseudoHeadersRegister(void) -{ - sigmatch_table[DETECT_TRANSFORM_STRIP_PSEUDO_HEADERS].name = "strip_pseudo_headers"; - sigmatch_table[DETECT_TRANSFORM_STRIP_PSEUDO_HEADERS].desc = - "modify buffer via stripping pseudo headers"; - sigmatch_table[DETECT_TRANSFORM_STRIP_PSEUDO_HEADERS].url = - "/rules/transforms.html#strip_pseudo_headers"; - sigmatch_table[DETECT_TRANSFORM_STRIP_PSEUDO_HEADERS].Transform = - DetectTransformStripPseudoHeaders; - sigmatch_table[DETECT_TRANSFORM_STRIP_PSEUDO_HEADERS].Setup = - DetectTransformStripPseudoHeadersSetup; - sigmatch_table[DETECT_TRANSFORM_STRIP_PSEUDO_HEADERS].flags |= SIGMATCH_NOOPT; -} diff --git a/src/detect-transform-strip-pseudo-headers.h b/src/detect-transform-strip-pseudo-headers.h deleted file mode 100644 index a0f9ebae31..0000000000 --- a/src/detect-transform-strip-pseudo-headers.h +++ /dev/null @@ -1,30 +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_TRANSFORM_STRIP_PSEUDOHEADERS_H -#define SURICATA_DETECT_TRANSFORM_STRIP_PSEUDOHEADERS_H - -/* prototypes */ -void DetectTransformStripPseudoHeadersRegister(void); - -#endif /* SURICATA_DETECT_TRANSFORM_STRIP_PSEUDOHEADERS_H */