From: Philippe Antoine Date: Wed, 30 Oct 2024 10:35:39 +0000 (+0100) Subject: transforms: move casechange to rust X-Git-Tag: suricata-8.0.0-beta1~730 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0414570d2ffd4f01b72548c1fe1ffb26ea9c533;p=thirdparty%2Fsuricata.git transforms: move casechange to rust Ticket: 7229 --- diff --git a/rust/src/detect/transforms/casechange.rs b/rust/src/detect/transforms/casechange.rs new file mode 100644 index 0000000000..80b6b82a48 --- /dev/null +++ b/rust/src/detect/transforms/casechange.rs @@ -0,0 +1,179 @@ +/* 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_TOLOWER_ID: c_int = 0; +static mut G_TRANSFORM_TOUPPER_ID: c_int = 0; + +#[no_mangle] +unsafe extern "C" fn tolower_setup( + _de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + return DetectSignatureAddTransform(s, G_TRANSFORM_TOLOWER_ID, ptr::null_mut()); +} + +fn tolower_transform_do(input: &[u8], output: &mut [u8]) { + for (i, o) in input.iter().zip(output.iter_mut()) { + *o = (*i).to_ascii_lowercase(); + } +} + +#[no_mangle] +unsafe extern "C" fn tolower_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); + + tolower_transform_do(input, output); + + InspectionBufferTruncate(buffer, input_len); +} + +#[no_mangle] +unsafe extern "C" fn tolower_validate(content: *const u8, len: u16, _ctx: *mut c_void) -> bool { + let input = build_slice!(content, len as usize); + for &c in input { + if c.is_ascii_uppercase() { + return false; + } + } + return true; +} + +#[no_mangle] +pub unsafe extern "C" fn DetectTransformToLowerRegister() { + let kw = SCTransformTableElmt { + name: b"to_lowercase\0".as_ptr() as *const libc::c_char, + desc: b"convert buffer to lowercase\0".as_ptr() as *const libc::c_char, + url: b"/rules/transforms.html#to_lowercase\0".as_ptr() as *const libc::c_char, + Setup: tolower_setup, + flags: SIGMATCH_NOOPT, + Transform: tolower_transform, + Free: None, + TransformValidate: Some(tolower_validate), + }; + unsafe { + G_TRANSFORM_TOLOWER_ID = DetectHelperTransformRegister(&kw); + if G_TRANSFORM_TOLOWER_ID < 0 { + SCLogWarning!("Failed registering transform tolower"); + } + } +} + +#[no_mangle] +unsafe extern "C" fn toupper_setup( + _de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + return DetectSignatureAddTransform(s, G_TRANSFORM_TOUPPER_ID, ptr::null_mut()); +} + +fn toupper_transform_do(input: &[u8], output: &mut [u8]) { + for (i, o) in input.iter().zip(output.iter_mut()) { + *o = (*i).to_ascii_uppercase(); + } +} + +#[no_mangle] +unsafe extern "C" fn toupper_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); + + toupper_transform_do(input, output); + + InspectionBufferTruncate(buffer, input_len); +} + +#[no_mangle] +unsafe extern "C" fn toupper_validate(content: *const u8, len: u16, _ctx: *mut c_void) -> bool { + let input = build_slice!(content, len as usize); + for &c in input { + if c.is_ascii_lowercase() { + return false; + } + } + return true; +} + +#[no_mangle] +pub unsafe extern "C" fn DetectTransformToUpperRegister() { + let kw = SCTransformTableElmt { + name: b"to_uppercase\0".as_ptr() as *const libc::c_char, + desc: b"convert buffer to uppercase\0".as_ptr() as *const libc::c_char, + url: b"/rules/transforms.html#to_uppercase\0".as_ptr() as *const libc::c_char, + Setup: toupper_setup, + flags: SIGMATCH_NOOPT, + Transform: toupper_transform, + Free: None, + TransformValidate: Some(toupper_validate), + }; + unsafe { + G_TRANSFORM_TOUPPER_ID = DetectHelperTransformRegister(&kw); + if G_TRANSFORM_TOUPPER_ID < 0 { + SCLogWarning!("Failed registering transform toupper"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tolower_transform() { + let buf = b" A b C D "; + let mut out = vec![0; buf.len()]; + tolower_transform_do(buf, &mut out); + assert_eq!(out, b" a b c d "); + } + + #[test] + fn test_toupper_transform() { + let buf = b" A b C D "; + let mut out = vec![0; buf.len()]; + toupper_transform_do(buf, &mut out); + assert_eq!(out, b" A B C D "); + } +} diff --git a/rust/src/detect/transforms/mod.rs b/rust/src/detect/transforms/mod.rs index 56f5e01839..39f1bbac40 100644 --- a/rust/src/detect/transforms/mod.rs +++ b/rust/src/detect/transforms/mod.rs @@ -19,10 +19,11 @@ use std::os::raw::{c_char, c_int, c_void}; +pub mod casechange; pub mod compress_whitespace; pub mod dotprefix; -pub mod strip_whitespace; pub mod hash; +pub mod strip_whitespace; #[repr(C)] #[allow(non_snake_case)] diff --git a/src/Makefile.am b/src/Makefile.am index 66900005e9..b7cc8ccd1d 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -306,7 +306,6 @@ noinst_HEADERS = \ detect-tls-random.h \ detect-tos.h \ detect-transform-base64.h \ - detect-transform-casechange.h \ detect-transform-header-lowercase.h \ detect-transform-pcrexform.h \ detect-transform-strip-pseudo-headers.h \ @@ -869,7 +868,6 @@ libsuricata_c_a_SOURCES = \ detect-tls-random.c \ detect-tos.c \ detect-transform-base64.c \ - detect-transform-casechange.c \ detect-transform-header-lowercase.c \ detect-transform-pcrexform.c \ detect-transform-strip-pseudo-headers.c \ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index fde0aac7ac..a5bc4ddb4c 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -219,7 +219,6 @@ #include "detect-transform-pcrexform.h" #include "detect-transform-urldecode.h" #include "detect-transform-xor.h" -#include "detect-transform-casechange.h" #include "detect-transform-header-lowercase.h" #include "detect-transform-base64.h" diff --git a/src/detect-transform-casechange.c b/src/detect-transform-casechange.c deleted file mode 100644 index 851030828c..0000000000 --- a/src/detect-transform-casechange.c +++ /dev/null @@ -1,169 +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 Jeff Lucovsky - * - * Implements case changing transforms - */ - -#include "suricata-common.h" -#include "detect.h" -#include "detect-engine.h" -#include "detect-parse.h" -#include "detect-transform-casechange.h" - -/** - * \internal - * \brief Register the to_lowercase transform - * \param det_ctx detection engine ctx - * \param s signature - * \param optstr options string - * \retval 0 ok - * \retval -1 failure - */ -static int DetectTransformToLowerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr) -{ - SCEnter(); - - int r = DetectSignatureAddTransform(s, DETECT_TRANSFORM_TOLOWER, NULL); - - SCReturnInt(r); -} - -/** - * \internal - * \brief Apply the to_lowercase keyword to the last pattern match - * \param buffer Inspection buffer - * \param optstr options string - */ -static void DetectTransformToLower(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]; - for (uint32_t i = 0; i < input_len; i++) { - output[i] = u8_tolower(input[i]); - } - - InspectionBufferCopy(buffer, output, input_len); -} -/** - * \internal - * \brief Register the to_upperrcase transform - * \param det_ctx detection engine ctx - * \param s signature - * \param optstr options string - * \retval 0 ok - * \retval -1 failure - */ -static int DetectTransformToUpperSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr) -{ - SCEnter(); - - int r = DetectSignatureAddTransform(s, DETECT_TRANSFORM_TOUPPER, NULL); - - SCReturnInt(r); -} - -/** - * \internal - * \brief Apply the to_uppercase keyword to the last pattern match - * \param buffer Inspection buffer - * \param optstr options string - */ -static void DetectTransformToUpper(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]; - for (uint32_t i = 0; i < input_len; i++) { - output[i] = u8_toupper(input[i]); - } - - InspectionBufferCopy(buffer, output, input_len); -} - -/* - * \internal - * \brief Check if content is compatible with transform - * - * If the content contains any lowercase characters, than it is not compatible. - */ -static bool TransformToUpperValidate(const uint8_t *content, uint16_t content_len, void *options) -{ - if (content) { - for (uint32_t i = 0; i < content_len; i++) { - if (islower(*content++)) { - return false; - } - } - } - return true; -} - -/* - * \internal - * \brief Check if content is compatible with transform - * - * If the content contains any uppercase characters, than it is not compatible. - */ -static bool TransformToLowerValidate(const uint8_t *content, uint16_t content_len, void *options) -{ - if (content) { - for (uint32_t i = 0; i < content_len; i++) { - if (isupper(*content++)) { - return false; - } - } - } - return true; -} - -void DetectTransformToUpperRegister(void) -{ - sigmatch_table[DETECT_TRANSFORM_TOUPPER].name = "to_uppercase"; - sigmatch_table[DETECT_TRANSFORM_TOUPPER].desc = "convert buffer to uppercase"; - sigmatch_table[DETECT_TRANSFORM_TOUPPER].url = "/rules/transforms.html#to_uppercase"; - sigmatch_table[DETECT_TRANSFORM_TOUPPER].Transform = DetectTransformToUpper; - sigmatch_table[DETECT_TRANSFORM_TOUPPER].TransformValidate = TransformToUpperValidate; - sigmatch_table[DETECT_TRANSFORM_TOUPPER].Setup = DetectTransformToUpperSetup; - sigmatch_table[DETECT_TRANSFORM_TOUPPER].flags |= SIGMATCH_NOOPT; -} - -void DetectTransformToLowerRegister(void) -{ - sigmatch_table[DETECT_TRANSFORM_TOLOWER].name = "to_lowercase"; - sigmatch_table[DETECT_TRANSFORM_TOLOWER].desc = "convert buffer to lowercase"; - sigmatch_table[DETECT_TRANSFORM_TOLOWER].url = "/rules/transforms.html#to_lowercase"; - sigmatch_table[DETECT_TRANSFORM_TOLOWER].Transform = DetectTransformToLower; - sigmatch_table[DETECT_TRANSFORM_TOLOWER].TransformValidate = TransformToLowerValidate; - sigmatch_table[DETECT_TRANSFORM_TOLOWER].Setup = DetectTransformToLowerSetup; - sigmatch_table[DETECT_TRANSFORM_TOLOWER].flags |= SIGMATCH_NOOPT; -} diff --git a/src/detect-transform-casechange.h b/src/detect-transform-casechange.h deleted file mode 100644 index 383786ac2f..0000000000 --- a/src/detect-transform-casechange.h +++ /dev/null @@ -1,31 +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 Jeff Lucovsky - */ - -#ifndef SURICATA_DETECT_TRANSFORM_CASECHANGE_H -#define SURICATA_DETECT_TRANSFORM_CASECHANGE_H - -/* prototypes */ -void DetectTransformToLowerRegister(void); -void DetectTransformToUpperRegister(void); - -#endif /* SURICATA_DETECT_TRANSFORM_CASECHANGE_H */