diff --git a/rust/src/detect/transform_base64.rs b/rust/src/detect/transform_base64.rs index 7d867ff23e..9ac974ac31 100644 --- a/rust/src/detect/transform_base64.rs +++ b/rust/src/detect/transform_base64.rs @@ -47,11 +47,22 @@ pub struct SCDetectTransformFromBase64Data { offset: u32, offset_str: *const c_char, mode: SCBase64Mode, + + // serialized data for hashing + serialized: *const u8, + serialized_len: u32, } impl Drop for SCDetectTransformFromBase64Data { fn drop(&mut self) { unsafe { + if !self.serialized.is_null() { + drop(Vec::from_raw_parts( + self.serialized as *mut u8, + self.serialized_len as usize, + self.serialized_len as usize, + )); + } if !self.offset_str.is_null() { let _ = CString::from_raw(self.offset_str as *mut c_char); } @@ -70,6 +81,8 @@ impl Default for SCDetectTransformFromBase64Data { offset: 0, offset_str: std::ptr::null_mut(), mode: TRANSFORM_FROM_BASE64_MODE_DEFAULT, + serialized: std::ptr::null_mut(), + serialized_len: 0, } } } @@ -80,6 +93,22 @@ impl SCDetectTransformFromBase64Data { ..Default::default() } } + + pub fn serialize(&mut self, nbytes: &str, offset: &str) { + let mut r = Vec::with_capacity(12 + nbytes.len() + offset.len()); + r.push(self.flags); + r.push(self.mode as u8); + r.extend_from_slice(&self.nbytes.to_le_bytes()); + r.extend_from_slice(&self.offset.to_le_bytes()); + r.push(nbytes.len() as u8); + r.extend_from_slice(nbytes.as_bytes()); + r.push(offset.len() as u8); + r.extend_from_slice(offset.as_bytes()); + self.serialized_len = r.len() as u32; + let ptr = r.as_mut_ptr(); + std::mem::forget(r); + self.serialized = ptr; + } } fn get_mode_value(value: &str) -> Option { @@ -117,6 +146,8 @@ fn parse_transform_base64( DETECT_TRANSFORM_BASE64_MAX_PARAM_COUNT, input))); } + let mut nbytes_str = String::new(); + let mut offset_str = String::new(); for value in values { let (mut val, mut name) = take_until_whitespace(value)?; val = val.trim(); @@ -152,17 +183,10 @@ fn parse_transform_base64( ))); } } - ResultValue::String(val) => match CString::new(val) { - Ok(newval) => { - transform_base64.offset_str = newval.into_raw(); - transform_base64.flags |= DETECT_TRANSFORM_BASE64_FLAG_OFFSET_VAR; - } - _ => { - return Err(make_error( - "parse string not safely convertible to C".to_string(), - )) - } - }, + ResultValue::String(val) => { + offset_str = val.clone(); + transform_base64.flags |= DETECT_TRANSFORM_BASE64_FLAG_OFFSET_VAR; + } } transform_base64.flags |= DETECT_TRANSFORM_BASE64_FLAG_OFFSET; @@ -186,17 +210,10 @@ fn parse_transform_base64( ))); } } - ResultValue::String(val) => match CString::new(val) { - Ok(newval) => { - transform_base64.nbytes_str = newval.into_raw(); - transform_base64.flags |= DETECT_TRANSFORM_BASE64_FLAG_NBYTES_VAR; - } - _ => { - return Err(make_error( - "parse string not safely convertible to C".to_string(), - )) - } - }, + ResultValue::String(val) => { + nbytes_str = val.clone(); + transform_base64.flags |= DETECT_TRANSFORM_BASE64_FLAG_NBYTES_VAR; + } } transform_base64.flags |= DETECT_TRANSFORM_BASE64_FLAG_NBYTES; } @@ -206,6 +223,25 @@ fn parse_transform_base64( }; } + transform_base64.serialize(&nbytes_str, &offset_str); + if (transform_base64.flags & DETECT_TRANSFORM_BASE64_FLAG_NBYTES_VAR) != 0 { + if let Ok(newval) = CString::new(nbytes_str) { + transform_base64.nbytes_str = newval.into_raw(); + } else { + return Err(make_error( + "parse string not safely convertible to C".to_string(), + )); + } + } + if (transform_base64.flags & DETECT_TRANSFORM_BASE64_FLAG_OFFSET_VAR) != 0 { + if let Ok(newval) = CString::new(offset_str) { + transform_base64.offset_str = newval.into_raw(); + } else { + return Err(make_error( + "parse string not safely convertible to C".to_string(), + )); + } + } Ok((input, transform_base64)) } @@ -283,6 +319,8 @@ mod tests { std::ptr::null_mut() }, mode, + serialized: std::ptr::null_mut(), + serialized_len: 0, }; let (_, val) = parse_transform_base64(args).unwrap(); diff --git a/src/detect-transform-base64.c b/src/detect-transform-base64.c index 6e3b58c800..fa493042ae 100644 --- a/src/detect-transform-base64.c +++ b/src/detect-transform-base64.c @@ -46,11 +46,8 @@ static void DetectTransformFromBase64Id(const uint8_t **data, uint32_t *length, { if (context) { SCDetectTransformFromBase64Data *b64d = (SCDetectTransformFromBase64Data *)context; - /* Since the context structure contains the unique values for the keyword usage, - * a pointer to the context structure is returned. - */ - *data = (const uint8_t *)b64d; - *length = sizeof(*b64d); + *data = b64d->serialized; + *length = b64d->serialized_len; } }