use lalrpop_util::lalrpop_mod;
lalrpop_mod!(pub (crate) parser, "/security_descriptor/parser.rs");
use std::{fmt::Display, io::Cursor};
use binrw::{binread, BinReaderExt, FilePtr};
use getset::Getters;
use serde::Serialize;
use crate::*;
#[binread]
#[derive(Eq, PartialEq, Getters, Serialize)]
#[getset(get = "pub")]
pub struct SecurityDescriptor {
#[serde(skip)]
sd_offset: Offset,
#[br(assert(revision == 1))]
#[bw(assert(*revision == 1))]
revision: u8,
#[getset(skip)]
#[br(temp)]
#[serde(skip)]
_reserved1: u8,
flags: ControlFlags,
#[serde(skip)]
#[br(little,temp,
offset=sd_offset.0,
if(! flags.as_ref().contains(ControlFlag::OwnerDefaulted)))
]
owner_ref: Option<FilePtr<u32, Sid>>,
#[serde(skip)]
#[br(little,temp,
offset=sd_offset.0,
if(! flags.as_ref().contains(ControlFlag::GroupDefaulted)))
]
group_ref: Option<FilePtr<u32, Sid>>,
#[serde(skip)]
#[br(little,temp,
offset=sd_offset.0,
if(flags.as_ref().contains(ControlFlag::SystemAclPresent)),
args{inner: (flags, acl::Type::SACL)})
]
sacl_ref: Option<FilePtr<u32, Acl>>,
#[serde(skip)]
#[br(temp, if(! flags.as_ref().contains(ControlFlag::SystemAclPresent), 0))]
_sacl_ref: u32,
#[serde(skip)]
#[br(little,temp,
offset=sd_offset.0,
if(flags.as_ref().contains(ControlFlag::DiscretionaryAclPresent)),
args{inner: (flags, acl::Type::DACL)})
]
dacl_ref: Option<FilePtr<u32, Acl>>,
#[serde(skip)]
#[br(temp, if(! flags.as_ref().contains(ControlFlag::DiscretionaryAclPresent), 0))]
_dacl_ref: u32,
#[br(calc=owner_ref.as_ref().map(|d| d.value.clone()))]
owner: Option<Sid>,
#[br(calc=group_ref.as_ref().map(|d| d.value.clone()))]
group: Option<Sid>,
#[br(calc=dacl_ref.as_ref().map(|d| d.value.clone()))]
dacl: Option<Acl>,
#[br(calc=sacl_ref.as_ref().map(|d| d.value.clone()))]
sacl: Option<Acl>,
}
impl SecurityDescriptor {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
let mut cursor = Cursor::new(bytes);
Ok(cursor.read_le()?)
}
pub fn new(
owner: Option<Sid>,
group: Option<Sid>,
dacl: Option<Acl>,
sacl: Option<Acl>,
) -> Self {
let mut flags = ControlFlags::EMPTY;
if owner.is_some() {
flags |= ControlFlag::OwnerDefaulted
}
if group.is_some() {
flags |= ControlFlag::GroupDefaulted
}
if let Some(dacl) = &dacl {
flags |= *dacl.control_flags() | ControlFlag::DiscretionaryAclPresent;
}
if let Some(sacl) = &sacl {
flags |= *sacl.control_flags() | ControlFlag::SystemAclPresent;
}
Self {
sd_offset: Offset(0),
revision: 1,
flags,
owner,
group,
sacl,
dacl,
}
}
pub fn acl_flags_as_sddl_string(
&self,
acl_flags: &[(control_flags::ControlFlag, &str)],
) -> String {
acl_flags
.iter()
.filter(|(f, _)| self.flags().as_ref().contains(*f))
.map(|(_, s)| *s)
.collect::<Vec<&str>>()
.join("")
}
pub fn from_sddl(value: &str, domain_rid: Option<&[u32]>) -> Result<Self, Error> {
Ok(
crate::security_descriptor::parser::SecurityDescriptorParser::new()
.parse(domain_rid, value)?,
)
}
}
const DACL_FLAGS: [(control_flags::ControlFlag, &str); 3] = [
(ControlFlag::DiscretionaryAclProtected, SDDL_PROTECTED),
(
ControlFlag::DiscretionaryAclAutoInheritRequired,
SDDL_AUTO_INHERIT_REQ,
),
(
ControlFlag::DiscretionaryAclAutoInherited,
SDDL_AUTO_INHERITED,
),
];
const SACL_FLAGS: [(control_flags::ControlFlag, &str); 3] = [
(ControlFlag::SystemAclProtected, SDDL_PROTECTED),
(
ControlFlag::SystemAclAutoInheritRequired,
SDDL_AUTO_INHERIT_REQ,
),
(ControlFlag::SystemAclAutoInherited, SDDL_AUTO_INHERITED),
];
impl Display for SecurityDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(owner) = self.owner() {
write!(f, "{SDDL_OWNER}{SDDL_DELIMINATOR}{owner}")?;
}
if let Some(group) = self.group() {
write!(f, "{SDDL_GROUP}{SDDL_DELIMINATOR}{group}")?;
}
if let Some(dacl) = self.dacl() {
let flags = self.acl_flags_as_sddl_string(&DACL_FLAGS);
write!(f, "{SDDL_DACL}{SDDL_DELIMINATOR}{flags}")?;
dacl.fmt(f)?;
}
if let Some(sacl) = self.sacl() {
let flags = self.acl_flags_as_sddl_string(&SACL_FLAGS);
write!(f, "{SDDL_DACL}{SDDL_DELIMINATOR}{flags}")?;
sacl.fmt(f)?;
}
Ok(())
}
}
impl TryFrom<&[u8]> for SecurityDescriptor {
type Error = Error;
fn try_from(value: &[u8]) -> Result<SecurityDescriptor, Self::Error> {
Self::from_bytes(value)
}
}