Skip to content

Commit

Permalink
Decoders improvements 3 - another batch (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrouaix authored Dec 21, 2024
1 parent ec1e17d commit 7d132c4
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 306 deletions.
10 changes: 5 additions & 5 deletions src/decoders/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ pub(crate) fn check_objects(
} else if format_string.contains("odtypes:mbridtype") {
Ok(member_id_type(&message_values[index].message_strings))
} else if format_string.contains("odtypes:mbr_details") {
Ok(member_details(&message_values[index].message_strings))
member_details(&message_values[index].message_strings)
} else if format_string.contains("odtypes:nt_sid_t") {
Ok(sid_details(&message_values[index].message_strings))
sid_details(&message_values[index].message_strings)
} else if format_string.contains("location:CLClientAuthorizationStatus") {
client_authorization_status(&message_values[index].message_strings)
} else if format_string.contains("location:CLDaemonStatus_Type::Reachability") {
Expand All @@ -86,11 +86,11 @@ pub(crate) fn check_objects(
} else if format_string.contains("location:_CLLocationManagerStateTrackerState") {
location_manager_state_tracker_state(&message_values[index].message_strings)
} else if format_string.contains("network:in6_addr") {
Ok(ipv_six(&message_values[index].message_strings))
ipv_six(&message_values[index].message_strings).map(|ip| ip.to_string())
} else if format_string.contains("network:in_addr") {
Ok(ipv_four(&message_values[index].message_strings))
ipv_four(&message_values[index].message_strings).map(|ip| ip.to_string())
} else if format_string.contains("network:sockaddr") {
Ok(sockaddr(&message_values[index].message_strings))
sockaddr(&message_values[index].message_strings)
} else if format_string.contains("time_t") {
Ok(parse_time(&message_values[index].message_strings))
} else if format_string.contains("mdns:dnshdr") {
Expand Down
22 changes: 11 additions & 11 deletions src/decoders/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,17 @@ fn get_dns_flags(input: &[u8]) -> IResult<(&[u8], usize), String> {
const Z: usize = 3;
const RCODE: usize = 4;

type RET<'a> = ((&'a [u8], usize), u8);
type Ret<'a> = ((&'a [u8], usize), u8);
use nom::bits::complete::take as bits;
// Have to work with bits instead of bytes for the DNS flags
let ((input, offset), query): RET<'_> = bits(QR)((input, 0))?;
let ((input, offset), opcode): RET<'_> = bits(OPCODE)((input, offset))?;
let ((input, offset), authoritative_flag): RET<'_> = bits(AA)((input, offset))?;
let ((input, offset), truncation_flag): RET<'_> = bits(TC)((input, offset))?;
let ((input, offset), recursion_desired): RET<'_> = bits(RD)((input, offset))?;
let ((input, offset), recursion_available): RET<'_> = bits(RA)((input, offset))?;
let ((input, offset), _reserved): RET<'_> = bits(Z)((input, offset))?;
let ((input, _), response_code): RET<'_> = bits(RCODE)((input, offset))?;
let ((input, offset), query): Ret<'_> = bits(QR)((input, 0))?;
let ((input, offset), opcode): Ret<'_> = bits(OPCODE)((input, offset))?;
let ((input, offset), authoritative_flag): Ret<'_> = bits(AA)((input, offset))?;
let ((input, offset), truncation_flag): Ret<'_> = bits(TC)((input, offset))?;
let ((input, offset), recursion_desired): Ret<'_> = bits(RD)((input, offset))?;
let ((input, offset), recursion_available): Ret<'_> = bits(RA)((input, offset))?;
let ((input, offset), _reserved): Ret<'_> = bits(Z)((input, offset))?;
let ((input, _), response_code): Ret<'_> = bits(RCODE)((input, offset))?;

let opcode_message = match opcode {
0 => "QUERY",
Expand Down Expand Up @@ -324,9 +324,9 @@ fn parse_dns_ip_addr(data: &[u8]) -> nom::IResult<&[u8], String> {
const IPV4: u32 = 4;
const IPV6: u32 = 6;
if ip_version == IPV4 {
return get_ip_four(data);
get_ip_four(data).map(|(data, result)| (data, result.to_string()))
} else if ip_version == IPV6 {
return get_ip_six(data);
get_ip_six(data).map(|(data, result)| (data, result.to_string()))
} else {
fail(data)
}
Expand Down
6 changes: 3 additions & 3 deletions src/decoders/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ pub enum DecoderError<'a> {
},
}

impl<'a> std::error::Error for DecoderError<'a> {}
impl std::error::Error for DecoderError<'_> {}

impl<'a> std::fmt::Display for DecoderError<'a> {
impl std::fmt::Display for DecoderError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Parse { message, .. } => write!(f, "{message}"),
}
}
}

impl<'a> std::fmt::Debug for DecoderError<'a> {
impl std::fmt::Debug for DecoderError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Parse {
Expand Down
207 changes: 82 additions & 125 deletions src/decoders/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,159 +5,117 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and limitations under the License.

use super::DecoderError;
use crate::util::decode_standard;
use log::{error, warn};
use log::warn;
use nom::{
bytes::complete::take,
combinator::map,
number::complete::{be_u128, be_u16, be_u32, be_u8},
sequence::tuple,
};
use std::net::Ipv6Addr;
use std::{mem::size_of, net::Ipv4Addr};
use std::net::{Ipv4Addr, Ipv6Addr};

/// Parse an IPv6 address
pub(crate) fn ipv_six(data: &str) -> String {
let decoded_data_result = decode_standard(data);
let decoded_data = match decoded_data_result {
Ok(result) => result,
Err(err) => {
error!(
"[macos-unifiedlogs] Failed to base64 decode ipv6 data {}, error: {:?}",
data, err
);
return String::from("Failed to base64 decode ipv6 data");
}
};
let message_result = get_ip_six(&decoded_data);

match message_result {
Ok((_, result)) => result,
Err(err) => {
error!("[macos-unifiedlogs] Failed to get ipv6: {:?}", err);
format!("Failed to get ipv6: {}", data)
}
}
pub(crate) fn ipv_six(input: &str) -> Result<Ipv6Addr, DecoderError<'_>> {
let decoded_data = decode_standard(input).map_err(|_| DecoderError::Parse {
input: input.as_bytes(),
parser_name: "ipv vix",
message: "Failed to base64 decode ipv6 data",
})?;

let (_, result) = get_ip_six(&decoded_data).map_err(|_| DecoderError::Parse {
input: input.as_bytes(),
parser_name: "ipv vix",
message: "Failed to get ipv6",
})?;

Ok(result)
}

/// Parse an IPv4 address
pub(crate) fn ipv_four(data: &str) -> String {
let decoded_data_result = decode_standard(data);
let decoded_data = match decoded_data_result {
Ok(result) => result,
Err(err) => {
error!(
"[macos-unifiedlogs] Failed to base64 decode ipv4 data {}, error: {:?}",
data, err
);
return String::from("Failed to base64 decode ipv4 data");
}
};
let message_result = get_ip_four(&decoded_data);

match message_result {
Ok((_, result)) => result,
Err(err) => {
error!("[macos-unifiedlogs] Failed to get ipv4: {:?}", err);
format!("Failed to get ipv4: {}", data)
}
}
pub(crate) fn ipv_four(input: &str) -> Result<Ipv4Addr, DecoderError<'_>> {
let decoded_data = decode_standard(input).map_err(|_| DecoderError::Parse {
input: input.as_bytes(),
parser_name: "ipv four",
message: "Failed to base64 decode ipv4 data",
})?;

let (_, result) = get_ip_four(&decoded_data).map_err(|_| DecoderError::Parse {
input: input.as_bytes(),
parser_name: "ipv four",
message: "Failed to get ipv4",
})?;

Ok(result)
}

/// Parse a sockaddr structure
pub(crate) fn sockaddr(data: &str) -> String {
if data.is_empty() {
return String::from("<NULL>");
}
let decoded_data_result = decode_standard(data);
let decoded_data = match decoded_data_result {
Ok(result) => result,
Err(err) => {
error!(
"[macos-unifiedlogs] Failed to bas64 decode sockaddr data {}, error: {:?}",
data, err
);
return String::from("Failed to base64 decode sockaddr data");
}
};
let message_result = get_sockaddr_data(&decoded_data);
match message_result {
Ok((_, result)) => result,
Err(err) => {
error!(
"[macos-unifiedlogs] Failed to get sockaddr structure: {:?}",
err
);
format!("Failed to get sockaddr: {}", data)
}
pub(crate) fn sockaddr(input: &str) -> Result<String, DecoderError<'_>> {
if input.is_empty() {
return Ok(String::from("<NULL>"));
}

let decoded_data = decode_standard(input).map_err(|_| DecoderError::Parse {
input: input.as_bytes(),
parser_name: "sock addr",
message: "Failed to bas64 decode sockaddr data",
})?;

let (_, result) = get_sockaddr_data(&decoded_data).map_err(|_| DecoderError::Parse {
input: input.as_bytes(),
parser_name: "ipv four",
message: "Failed to get sockaddr structure",
})?;

Ok(result)
}

/// Get the sockaddr data
fn get_sockaddr_data(data: &[u8]) -> nom::IResult<&[u8], String> {
let message;
let (sock_data, _total_length) = take(size_of::<u8>())(data)?;

let (sock_data, family_data) = take(size_of::<u8>())(sock_data)?;
let (_, family) = be_u8(family_data)?;
fn get_sockaddr_data(input: &[u8]) -> nom::IResult<&[u8], String> {
let (input, (_total_length, family)) = tuple((be_u8, be_u8))(input)?;

// Family types seen so far (AF_INET should be used most often)
match family {
2 => {
// AF_INET
let (sock_data, port_data) = take(size_of::<u16>())(sock_data)?;
let (_, ip_data) = take(size_of::<u32>())(sock_data)?;
let (input, port) = be_u16(input)?;
let (input, ip_addr) = get_ip_four(input)?;

let (_, port) = be_u16(port_data)?;
let (_, ip) = be_u32(ip_data)?;
let ip_addr = Ipv4Addr::from(ip);

if port != 0 {
message = format!("{}:{}", ip_addr, port);
} else {
message = ip_addr.to_string();
match port {
0 => Ok((input, ip_addr.to_string())),
_ => Ok((input, format!("{ip_addr}:{port}"))),
}
}
30 => {
// AF_INET6
let (sock_data, port_data) = take(size_of::<u16>())(sock_data)?;
let (sock_data, flow_data) = take(size_of::<u32>())(sock_data)?;
let (sock_data, ip_data) = take(size_of::<u128>())(sock_data)?;
let (_, scope_data) = take(size_of::<u32>())(sock_data)?;

let (_, port) = be_u16(port_data)?;
let (_, flow) = be_u32(flow_data)?;
let (_, ip) = be_u128(ip_data)?;
let (_, scope) = be_u32(scope_data)?;

let ip_addr = Ipv6Addr::from(ip);
if port != 0 {
message = format!(
"{}:{}, Flow ID: {}, Scope ID: {}",
ip_addr, port, flow, scope
);
} else {
message = format!("{}, Flow ID: {}, Scope ID: {}", ip_addr, flow, scope);
let (input, (port, flow, ip_addr, scope)) =
tuple((be_u16, be_u32, get_ip_six, be_u32))(input)?;

match port {
0 => Ok((
input,
format!("{ip_addr}, Flow ID: {flow}, Scope ID: {scope}"),
)),
_ => Ok((
input,
format!("{ip_addr}:{port}, Flow ID: {flow}, Scope ID: {scope}"),
)),
}
}
_ => {
warn!(
"[macos-unifiedlogs] Unknown sockaddr family: {}. From: {:?}",
family, data
);
message = format!("Unknown sockaddr family: {}", family);
warn!("[macos-unifiedlogs] Unknown sockaddr family: {family}. From: {input:?}",);
Ok((input, format!("Unknown sockaddr family: {family}",)))
}
}
Ok((sock_data, message))
}

/// Get the IPv4 data
pub(crate) fn get_ip_four(input: &[u8]) -> nom::IResult<&[u8], String> {
map(be_u32, |val| Ipv4Addr::from(val).to_string())(input)
pub(crate) fn get_ip_four(input: &[u8]) -> nom::IResult<&[u8], Ipv4Addr> {
map(be_u32, Ipv4Addr::from)(input)
}

/// Get the IPv6 data
pub(crate) fn get_ip_six(input: &[u8]) -> nom::IResult<&[u8], String> {
map(be_u128, |val| Ipv6Addr::from(val).to_string())(input)
pub(crate) fn get_ip_six(input: &[u8]) -> nom::IResult<&[u8], Ipv6Addr> {
map(be_u128, Ipv6Addr::from)(input)
}

#[cfg(test)]
Expand All @@ -172,8 +130,8 @@ mod tests {
#[test]
fn test_ipv_six() {
let test_data = "/wIAAAAAAAAAAAAAAAAA+w==";
let result = ipv_six(test_data);
assert_eq!(result, "ff02::fb");
let result = ipv_six(test_data).unwrap();
assert_eq!(result.to_string(), "ff02::fb");
}

#[test]
Expand All @@ -182,14 +140,14 @@ mod tests {
let decoded_data_result = decode_standard(test_data).unwrap();

let (_, result) = get_ip_six(&decoded_data_result).unwrap();
assert_eq!(result, "ff02::fb");
assert_eq!(result.to_string(), "ff02::fb");
}

#[test]
fn test_ipv_four() {
let test_data = "4AAA+w==";
let result = ipv_four(test_data);
assert_eq!(result, "224.0.0.251");
let result = ipv_four(test_data).unwrap();
assert_eq!(result.to_string(), "224.0.0.251");
}

#[test]
Expand All @@ -198,17 +156,16 @@ mod tests {
let decoded_data_result = decode_standard(test_data).unwrap();

let (_, result) = get_ip_four(&decoded_data_result).unwrap();
assert_eq!(result, "224.0.0.251");
assert_eq!(result.to_string(), "224.0.0.251");
}

#[test]
fn test_sockaddr() {
let mut test_data = "EAIAALgciWcAAAAAAAAAAA==";
let mut result = sockaddr(test_data);
let mut result = sockaddr(test_data).unwrap();
assert_eq!(result, "184.28.137.103");

test_data = "HB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==";
result = sockaddr(test_data);
result = sockaddr(test_data).unwrap();
assert_eq!(result, "::, Flow ID: 0, Scope ID: 0");
}

Expand Down
Loading

0 comments on commit 7d132c4

Please sign in to comment.