From 5dbe910c5cd97f72f079c5556dce2ab403d4c80e Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 30 Nov 2023 14:32:08 +0100 Subject: [PATCH] detect: dns.opcode as first-class integer Ticket: 5446 That means it can accept ranges --- rust/src/detect/uint.rs | 2 +- rust/src/dns/detect.rs | 195 +++++++++++++--------------------------- src/detect-dns-opcode.c | 5 +- 3 files changed, 66 insertions(+), 136 deletions(-) diff --git a/rust/src/detect/uint.rs b/rust/src/detect/uint.rs index 3d6a5baab0ca..56c50aedb153 100644 --- a/rust/src/detect/uint.rs +++ b/rust/src/detect/uint.rs @@ -37,7 +37,7 @@ pub enum DetectUintMode { DetectUintModeNe, } -#[derive(Debug)] +#[derive(Debug, PartialEq)] #[repr(C)] pub struct DetectUintData { pub arg1: T, diff --git a/rust/src/dns/detect.rs b/rust/src/dns/detect.rs index 268a409eac8d..452d4e8380e1 100644 --- a/rust/src/dns/detect.rs +++ b/rust/src/dns/detect.rs @@ -16,49 +16,15 @@ */ use super::dns::DNSTransaction; -use crate::core::*; -use std::ffi::CStr; -use std::os::raw::{c_char, c_void}; - -#[derive(Debug, PartialEq, Eq)] -pub struct DetectDnsOpcode { - negate: bool, - opcode: u8, -} - -/// Parse a DNS opcode argument returning the code and if it is to be -/// negated or not. -/// -/// For now only an indication that an error occurred is returned, not -/// the details of the error. -fn parse_opcode(opcode: &str) -> Result { - let mut negated = false; - for (i, c) in opcode.chars().enumerate() { - match c { - ' ' | '\t' => { - continue; - } - '!' => { - negated = true; - } - _ => { - let code: u8 = opcode[i..].parse().map_err(|_| ())?; - return Ok(DetectDnsOpcode { - negate: negated, - opcode: code, - }); - } - } - } - Err(()) -} +use crate::core::Direction; +use crate::detect::uint::{detect_match_uint, DetectUintData}; /// Perform the DNS opcode match. /// /// 1 will be returned on match, otherwise 0 will be returned. #[no_mangle] pub extern "C" fn rs_dns_opcode_match( - tx: &mut DNSTransaction, detect: &mut DetectDnsOpcode, flags: u8, + tx: &mut DNSTransaction, detect: &mut DetectUintData, flags: u8, ) -> u8 { let header_flags = if flags & Direction::ToServer as u8 != 0 { if let Some(request) = &tx.request { @@ -76,124 +42,87 @@ pub extern "C" fn rs_dns_opcode_match( // Not to server or to client?? return 0; }; + let opcode = ((header_flags >> 11) & 0xf) as u8; - match_opcode(detect, header_flags).into() -} - -fn match_opcode(detect: &DetectDnsOpcode, flags: u16) -> bool { - let opcode = ((flags >> 11) & 0xf) as u8; - if detect.negate { - detect.opcode != opcode - } else { - detect.opcode == opcode - } -} - -#[no_mangle] -pub unsafe extern "C" fn rs_detect_dns_opcode_parse(carg: *const c_char) -> *mut c_void { - if carg.is_null() { - return std::ptr::null_mut(); - } - let arg = match CStr::from_ptr(carg).to_str() { - Ok(arg) => arg, - _ => { - return std::ptr::null_mut(); - } - }; - - match parse_opcode(arg) { - Ok(detect) => Box::into_raw(Box::new(detect)) as *mut _, - Err(_) => std::ptr::null_mut(), - } -} - -#[no_mangle] -pub unsafe extern "C" fn rs_dns_detect_opcode_free(ptr: *mut c_void) { - if !ptr.is_null() { - std::mem::drop(Box::from_raw(ptr as *mut DetectDnsOpcode)); + if detect_match_uint(detect, opcode) { + return 1; } + return 0; } #[cfg(test)] mod test { use super::*; + use crate::detect::uint::{detect_parse_uint, DetectUintMode}; #[test] fn parse_opcode_good() { assert_eq!( - parse_opcode("1"), - Ok(DetectDnsOpcode { - negate: false, - opcode: 1 - }) - ); - assert_eq!( - parse_opcode("123"), - Ok(DetectDnsOpcode { - negate: false, - opcode: 123 - }) + detect_parse_uint::("1").unwrap().1, + DetectUintData { + mode: DetectUintMode::DetectUintModeEqual, + arg1: 1, + arg2: 0, + } ); assert_eq!( - parse_opcode("!123"), - Ok(DetectDnsOpcode { - negate: true, - opcode: 123 - }) + detect_parse_uint::("123").unwrap().1, + DetectUintData { + mode: DetectUintMode::DetectUintModeEqual, + arg1: 123, + arg2: 0, + } ); assert_eq!( - parse_opcode("!123"), - Ok(DetectDnsOpcode { - negate: true, - opcode: 123 - }) + detect_parse_uint::("!123").unwrap().1, + DetectUintData { + mode: DetectUintMode::DetectUintModeNe, + arg1: 123, + arg2: 0, + } ); - assert_eq!(parse_opcode(""), Err(())); - assert_eq!(parse_opcode("!"), Err(())); - assert_eq!(parse_opcode("! "), Err(())); - assert_eq!(parse_opcode("!asdf"), Err(())); + assert!(detect_parse_uint::("").is_err()); + assert!(detect_parse_uint::("!").is_err()); + assert!(detect_parse_uint::("! ").is_err()); + assert!(detect_parse_uint::("!asdf").is_err()); } #[test] fn test_match_opcode() { - assert!( - match_opcode( - &DetectDnsOpcode { - negate: false, - opcode: 0, - }, - 0b0000_0000_0000_0000, - ) - ); + assert!(detect_match_uint( + &DetectUintData { + mode: DetectUintMode::DetectUintModeEqual, + arg1: 0, + arg2: 0, + }, + 0b0000_0000_0000_0000, + )); - assert!( - !match_opcode( - &DetectDnsOpcode { - negate: true, - opcode: 0, - }, - 0b0000_0000_0000_0000, - ) - ); + assert!(!detect_match_uint( + &DetectUintData { + mode: DetectUintMode::DetectUintModeNe, + arg1: 0, + arg2: 0, + }, + 0b0000_0000_0000_0000, + )); - assert!( - match_opcode( - &DetectDnsOpcode { - negate: false, - opcode: 4, - }, - 0b0010_0000_0000_0000, - ) - ); + assert!(detect_match_uint( + &DetectUintData { + mode: DetectUintMode::DetectUintModeEqual, + arg1: 4, + arg2: 0, + }, + ((0b0010_0000_0000_0000 >> 11) & 0xf) as u8, + )); - assert!( - !match_opcode( - &DetectDnsOpcode { - negate: true, - opcode: 4, - }, - 0b0010_0000_0000_0000, - ) - ); + assert!(!detect_match_uint( + &DetectUintData { + mode: DetectUintMode::DetectUintModeNe, + arg1: 4, + arg2: 0, + }, + ((0b0010_0000_0000_0000 >> 11) & 0xf) as u8, + )); } } diff --git a/src/detect-dns-opcode.c b/src/detect-dns-opcode.c index 853b01f0097d..f66bfe201e31 100644 --- a/src/detect-dns-opcode.c +++ b/src/detect-dns-opcode.c @@ -19,6 +19,7 @@ #include "detect-parse.h" #include "detect-engine.h" +#include "detect-engine-uint.h" #include "detect-dns-opcode.h" #include "rust.h" @@ -35,7 +36,7 @@ static int DetectDnsOpcodeSetup(DetectEngineCtx *de_ctx, Signature *s, return -1; } - void *detect = rs_detect_dns_opcode_parse(str); + void *detect = DetectU8Parse(str); if (detect == NULL) { SCLogError("failed to parse dns.opcode: %s", str); return -1; @@ -57,7 +58,7 @@ static void DetectDnsOpcodeFree(DetectEngineCtx *de_ctx, void *ptr) { SCEnter(); if (ptr != NULL) { - rs_dns_detect_opcode_free(ptr); + rs_detect_u8_free(ptr); } SCReturn; }