mime: url decode value with charset and lang

Ticket: 9157
pull/16529/head
Philippe Antoine 3 weeks ago committed by Victor Julien
parent 164b57effc
commit 26605b7a66

@ -41,7 +41,8 @@ fn hex_value(i: u8) -> Option<u8> {
_ => None,
}
}
fn url_decode_transform_do(input: &[u8], output: &mut [u8]) -> u32 {
pub(crate) fn url_decode_transform_do(input: &[u8], output: &mut [u8], plus_space: bool) -> u32 {
let mut state = (0u8, 0u8);
let mut nb = 0;
for &i in input.iter() {
@ -68,7 +69,7 @@ fn url_decode_transform_do(input: &[u8], output: &mut [u8]) -> u32 {
} else if i == b'%' {
state = (1u8, 0u8);
} else {
if i == b'+' {
if i == b'+' && plus_space {
output[nb] = b' ';
} else {
output[nb] = i;
@ -104,7 +105,7 @@ unsafe extern "C" fn url_decode_transform(
}
let output = std::slice::from_raw_parts_mut(output, input_len as usize);
let out_len = url_decode_transform_do(input, output);
let out_len = url_decode_transform_do(input, output, true);
SCInspectionBufferTruncate(buffer, out_len);
}
@ -138,11 +139,11 @@ mod tests {
let mut buf = Vec::new();
buf.extend_from_slice(b"Suricata%20is+%27%61wesome%21%27%25%30%30%ZZ%4");
let mut out = vec![0; buf.len()];
let nb = url_decode_transform_do(&buf, &mut out);
let nb = url_decode_transform_do(&buf, &mut out, true);
assert_eq!(&out[..nb as usize], b"Suricata is 'awesome!'%00%ZZ%4");
// test in place
let still_buf = unsafe { std::slice::from_raw_parts(buf.as_ptr(), buf.len()) };
let nb = url_decode_transform_do(still_buf, &mut buf);
let nb = url_decode_transform_do(still_buf, &mut buf, true);
assert_eq!(&still_buf[..nb as usize], b"Suricata is 'awesome!'%00%ZZ%4");
}
}

@ -16,6 +16,7 @@
*/
use crate::common::nom8::take_until_and_consume;
use crate::detect::transforms::urldecode::url_decode_transform_do;
use nom8::branch::alt;
use nom8::bytes::complete::{tag, take, take_till, take_until, take_while};
use nom8::character::complete::char;
@ -118,8 +119,8 @@ fn mime_parse_token_name(input: &[u8]) -> IResult<&[u8], (bool, &[u8])> {
pub fn mime_parse_header_token_name(input: &[u8]) -> IResult<&[u8], (bool, &[u8])> {
// from RFC2047 : like ch.is_ascii_whitespace but without 0x0c FORM-FEED
let (input, _) = take_while(is_mime_space).parse(input)?;
let (input, name) = mime_parse_token_name(input)?;
return Ok((input, name));
let (input, (star, name)) = mime_parse_token_name(input)?;
return Ok((input, (star, name)));
}
pub fn mime_skip_header_token_value(input: &[u8]) -> IResult<&[u8], ()> {
@ -149,8 +150,9 @@ pub fn mime_parse_header_token_value(input: &[u8], star: bool) -> IResult<&[u8],
break;
}
}
let mut decoded = Vec::new();
decoded.extend_from_slice(&value[start..]);
let mut decoded = vec![0; value.len() - start];
let out_len = url_decode_transform_do(&value[start..], &mut decoded, false);
decoded.truncate(out_len as usize);
return Ok((input, decoded));
}
return Ok((input, value));
@ -680,5 +682,20 @@ mod test {
)
.unwrap();
assert_eq!(quote_after_lang, b"shell.php");
let encoded = mime_find_header_token(
"attachment; filename*=us-ascii'en-us'she%6c%6C.php".as_bytes(),
"filename".as_bytes(),
)
.unwrap();
assert_eq!(encoded, b"shell.php");
let multi_encoded = mime_find_header_token(
"attachment; filename*0*=us-ascii'en-us'sh%65; filename*1*=%6c%6C;filename*2=\".php\""
.as_bytes(),
"filename".as_bytes(),
)
.unwrap();
assert_eq!(multi_encoded, b"shell.php");
}
}

Loading…
Cancel
Save