Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 100 additions & 7 deletions src/security/ace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl Ace {
}
}

#[derive(FromPrimitive, ToPrimitive, Serialize, Debug, Clone)]
#[derive(FromPrimitive, ToPrimitive, Serialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[repr(u8)]
pub enum AceType {
Expand Down Expand Up @@ -134,18 +134,24 @@ impl AceBasic {
#[derive(Serialize, Debug, Clone)]
pub struct AceObject {
pub access_rights: u32,
pub flags: u32,
pub object_type: Guid,
pub inherited_type: Guid,
pub flags: AceObjectFlags,
pub object_type: Option<Guid>,
pub inherited_type: Option<Guid>,
pub sid: Sid,
}

impl AceObject {
pub fn from_reader<R: Read>(mut reader: &mut R) -> Result<AceObject> {
let access_rights = reader.read_u32::<LittleEndian>()?;
let flags = reader.read_u32::<LittleEndian>()?;
let object_type = Guid::from_reader(&mut reader)?;
let inherited_type = Guid::from_reader(&mut reader)?;
let flags = AceObjectFlags::from_bits_truncate(reader.read_u32::<LittleEndian>()?);
let mut object_type = None;
if flags.contains(AceObjectFlags::ACE_OBJECT_TYPE_PRESENT) {
object_type = Some(Guid::from_reader(&mut reader)?);
}
let mut inherited_type = None;
if flags.contains(AceObjectFlags::ACE_INHERITED_OBJECT_TYPE_PRESENT) {
inherited_type = Some(Guid::from_reader(&mut reader)?);
}
let sid = Sid::from_reader(&mut reader)?;

Ok(AceObject {
Expand Down Expand Up @@ -238,3 +244,90 @@ bitflags! {
}

impl_serialize_for_bitflags! {FolderAccessFlags}

bitflags! {
pub struct AceObjectFlags: u32 {
// Indicates whether the ObjectType and InheritedObjectType
// fields contain valid data
const ACE_OBJECT_TYPE_PRESENT = 0x00000001;
const ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x00000002;
}
}

impl_serialize_for_bitflags! {AceObjectFlags}

#[cfg(test)]
mod tests {
use crate::guid::Guid;
use crate::security::ace::{Ace, AceData, AceType};
use crate::security::sid::Sid;
use std::io::Cursor;

#[test]
fn test_parses_basic_ace() {
let buffer: &[u8] = &[
0x00, 0x00, 0x14, 0x00, 0xff, 0x01, 0x0f, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x05, 0x12, 0x00, 0x00, 0x00,
];
let ace = Ace::from_reader(&mut Cursor::new(buffer)).unwrap();

assert_eq!(ace.ace_type, AceType::AccessAllowed);
assert_eq!(ace.ace_flags.bits, 0);
assert_eq!(ace.size, 20);
assert!(ace.ace_type.is_basic());

if let AceData::Basic(data) = ace.data {
assert_eq!(data.access_rights, 983551);

let buffer_sid: &[u8] = &[
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00,
];
assert_eq!(data.sid, Sid::from_buffer(buffer_sid).unwrap());
} else {
panic!("ACE content does not match ACE type");
}
}

#[test]
fn test_parses_object_ace() {
let buffer: &[u8] = &[
0x05, 0x12, 0x38, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0xd6,
0x47, 0x5b, 0x90, 0x60, 0xb2, 0x40, 0x9f, 0x37, 0x2a, 0x4d, 0xe8, 0x8f, 0x30, 0x63,
0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0x3a, 0x31,
0xdc, 0x2b, 0x2a, 0x09, 0x33, 0x6f, 0x41, 0x04, 0xa0, 0x51, 0x0e, 0x02, 0x00, 0x00,
];

let ace = Ace::from_reader(&mut Cursor::new(buffer)).unwrap();

assert_eq!(ace.ace_type, AceType::AccessAllowedObject);
assert_eq!(ace.ace_flags.bits, 2);
assert_eq!(ace.size, 56);
assert!(ace.ace_type.is_object());

if let AceData::Object(data) = ace.data {
assert_eq!(data.access_rights, 48);

if let Some(ace_guid) = data.object_type {
let buffer_guid: &[u8] = &[
0x0f, 0xd6, 0x47, 0x5b, 0x90, 0x60, 0xb2, 0x40, 0x9f, 0x37, 0x2a, 0x4d, 0xe8,
0x8f, 0x30, 0x63,
];
assert_eq!(ace_guid, Guid::from_buffer(buffer_guid).unwrap());
} else {
panic!("ACE contains an object type GUID");
}

if let Some(_) = data.inherited_type {
panic!("ACE does not contain object inherited type");
}

let buffer_sid: &[u8] = &[
0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0x3a, 0x31,
0xdc, 0x2b, 0x2a, 0x09, 0x33, 0x6f, 0x41, 0x04, 0xa0, 0x51, 0x0e, 0x02, 0x00, 0x00,
];
assert_eq!(data.sid, Sid::from_buffer(buffer_sid).unwrap());
} else {
panic!("ACE content does not match ACE type");
}
}
}