use super::Sid;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AccessMask(u32);
impl AccessMask {
pub const NONE: AccessMask = AccessMask(0);
pub const fn from_bits(bits: u32) -> Self {
AccessMask(bits)
}
pub const fn bits(self) -> u32 {
self.0
}
pub const fn contains(self, other: AccessMask) -> bool {
(self.0 & other.0) == other.0
}
}
impl std::ops::BitOr for AccessMask {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
AccessMask(self.0 | rhs.0)
}
}
impl std::ops::BitOrAssign for AccessMask {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
impl std::ops::BitAnd for AccessMask {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
AccessMask(self.0 & rhs.0)
}
}
impl std::ops::BitAndAssign for AccessMask {
fn bitand_assign(&mut self, rhs: Self) {
self.0 &= rhs.0;
}
}
impl std::ops::Not for AccessMask {
type Output = Self;
fn not(self) -> Self::Output {
AccessMask(!self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AceType {
Allow,
Deny,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct InheritanceFlags {
pub object_inherit: bool,
pub container_inherit: bool,
pub inherit_only: bool,
pub no_propagate_inherit: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Ace {
pub trustee: Sid,
pub ace_type: AceType,
pub access_mask: AccessMask,
pub inheritance: InheritanceFlags,
pub inherited: bool,
}
impl Ace {
pub fn new(trustee: Sid, ace_type: AceType, access_mask: AccessMask) -> Self {
Self {
trustee,
ace_type,
access_mask,
inheritance: InheritanceFlags::default(),
inherited: false,
}
}
pub fn inherited(mut self, inherited: bool) -> Self {
self.inherited = inherited;
self
}
pub fn with_inheritance(mut self, inheritance: InheritanceFlags) -> Self {
self.inheritance = inheritance;
self
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Dacl {
entries: Vec<Ace>,
}
impl Dacl {
pub fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub fn from_entries(entries: Vec<Ace>) -> Self {
Self { entries }
}
pub fn entries(&self) -> &[Ace] {
&self.entries
}
pub fn entries_mut(&mut self) -> &mut Vec<Ace> {
&mut self.entries
}
pub fn canonicalize(&mut self) {
self.entries.sort_by_key(|ace| {
let inherited_rank = if ace.inherited { 1u8 } else { 0u8 };
let type_rank = match ace.ace_type {
AceType::Deny => 0u8,
AceType::Allow => 1u8,
};
(inherited_rank, type_rank)
});
}
}
#[cfg(test)]
mod tests {
use super::{AccessMask, Ace, AceType, Dacl};
use crate::security::Sid;
#[test]
fn canonicalize_places_explicit_deny_first() {
let user = Sid::parse("S-1-5-32-545").expect("valid sid");
let mut dacl = Dacl::from_entries(vec![
Ace::new(user.clone(), AceType::Allow, AccessMask::from_bits(0x2)),
Ace::new(user.clone(), AceType::Deny, AccessMask::from_bits(0x1)),
Ace::new(user.clone(), AceType::Allow, AccessMask::from_bits(0x4)).inherited(true),
]);
dacl.canonicalize();
assert_eq!(dacl.entries()[0].ace_type, AceType::Deny);
assert!(!dacl.entries()[0].inherited);
}
}