use std::fmt::Display;
use crate::raw_size::RawSize;
use crate::sddl_h::*;
use crate::Ace;
use crate::ControlFlags;
use binrw::binrw;
use derivative::Derivative;
use getset::Getters;
use serde::Serialize;
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum AclType {
SACL,
DACL,
}
impl AclType {
pub fn sddl_string(&self) -> &'static str {
match self {
AclType::SACL => "S",
AclType::DACL => "D",
}
}
}
pub const ACL_HEADER_SIZE: u16 = 1 + 1 + 2 + 2 + 2;
#[binrw]
#[derive(Derivative, Getters, Debug, Clone, Serialize)]
#[derivative(Eq, PartialEq)]
#[getset(get = "pub")]
#[brw(little,import(control_flags: ControlFlags, acl_type: AclType))]
pub struct Acl {
acl_revision: AclRevision,
#[br(temp)]
#[bw(calc(0))]
#[getset(skip)]
#[serde(skip)]
_sbz1: u8,
#[serde(skip)]
acl_size: u16,
#[serde(skip)]
ace_count: u16,
#[br(temp)]
#[bw(calc(0))]
#[getset(skip)]
#[serde(skip)]
_sbz2: u16,
#[br(count=ace_count)]
ace_list: Vec<Ace>,
#[br(calc=acl_type)]
#[bw(ignore)]
#[serde(skip)]
acl_type: AclType,
#[br(calc=control_flags)]
#[bw(ignore)]
#[serde(skip)]
#[derivative(PartialEq="ignore")]
control_flags: ControlFlags,
}
impl Display for Acl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for ace in self.ace_list() {
write!(f, "{SDDL_ACE_BEGIN}{ace}{SDDL_ACE_END}")?;
}
Ok(())
}
}
#[binrw]
#[derive(Eq, PartialEq, Clone, Copy, Default, Debug, Serialize)]
#[allow(non_camel_case_types)]
#[brw(repr=u8)]
pub enum AclRevision {
#[default]
ACL_REVISION = 0x02,
ACL_REVISION_DS = 0x04,
}
impl Acl {
pub fn new(
acl_revision: AclRevision,
acl_type: AclType,
control_flags: ControlFlags,
ace_list: Vec<Ace>,
) -> Self {
let acl_size = ACL_HEADER_SIZE + ace_list.iter().map(|ace| ace.raw_size()).sum::<u16>();
let ace_count = ace_list.len().try_into().unwrap();
Self {
acl_revision,
acl_size,
ace_count,
ace_list,
acl_type,
control_flags,
}
}
pub fn from_sddl(value: &str, domain_rid: Option<&[u32]>) -> Result<Self, crate::Error> {
Ok(crate::parser::AclParser::new().parse(domain_rid, value)?)
}
pub fn sddl_string(&self) -> String {
let ace_list = self
.ace_list()
.iter()
.map(|ace: &Ace| format!("{SDDL_ACE_BEGIN}{ace}{SDDL_ACE_END}"))
.fold(String::new(), |a, b| a + &b);
let acl_type = self.acl_type().sddl_string();
let flags = self.control_flags().sddl_string(*self.acl_type());
format!("{acl_type}{SDDL_DELIMINATOR}{flags}{ace_list}")
}
}