windows_erg/security/
acl.rs1use super::Sid;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub struct AccessMask(u32);
8
9impl AccessMask {
10 pub const NONE: AccessMask = AccessMask(0);
12
13 pub const fn from_bits(bits: u32) -> Self {
15 AccessMask(bits)
16 }
17
18 pub const fn bits(self) -> u32 {
20 self.0
21 }
22
23 pub const fn contains(self, other: AccessMask) -> bool {
25 (self.0 & other.0) == other.0
26 }
27}
28
29impl std::ops::BitOr for AccessMask {
30 type Output = Self;
31
32 fn bitor(self, rhs: Self) -> Self::Output {
33 AccessMask(self.0 | rhs.0)
34 }
35}
36
37impl std::ops::BitOrAssign for AccessMask {
38 fn bitor_assign(&mut self, rhs: Self) {
39 self.0 |= rhs.0;
40 }
41}
42
43impl std::ops::BitAnd for AccessMask {
44 type Output = Self;
45
46 fn bitand(self, rhs: Self) -> Self::Output {
47 AccessMask(self.0 & rhs.0)
48 }
49}
50
51impl std::ops::BitAndAssign for AccessMask {
52 fn bitand_assign(&mut self, rhs: Self) {
53 self.0 &= rhs.0;
54 }
55}
56
57impl std::ops::Not for AccessMask {
58 type Output = Self;
59
60 fn not(self) -> Self::Output {
61 AccessMask(!self.0)
62 }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
67pub enum AceType {
68 Allow,
70 Deny,
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
76pub struct InheritanceFlags {
77 pub object_inherit: bool,
79 pub container_inherit: bool,
81 pub inherit_only: bool,
83 pub no_propagate_inherit: bool,
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct Ace {
90 pub trustee: Sid,
92 pub ace_type: AceType,
94 pub access_mask: AccessMask,
96 pub inheritance: InheritanceFlags,
98 pub inherited: bool,
100}
101
102impl Ace {
103 pub fn new(trustee: Sid, ace_type: AceType, access_mask: AccessMask) -> Self {
105 Self {
106 trustee,
107 ace_type,
108 access_mask,
109 inheritance: InheritanceFlags::default(),
110 inherited: false,
111 }
112 }
113
114 pub fn inherited(mut self, inherited: bool) -> Self {
116 self.inherited = inherited;
117 self
118 }
119
120 pub fn with_inheritance(mut self, inheritance: InheritanceFlags) -> Self {
122 self.inheritance = inheritance;
123 self
124 }
125}
126
127#[derive(Debug, Clone, Default, PartialEq, Eq)]
129pub struct Dacl {
130 entries: Vec<Ace>,
131}
132
133impl Dacl {
134 pub fn new() -> Self {
136 Self {
137 entries: Vec::new(),
138 }
139 }
140
141 pub fn from_entries(entries: Vec<Ace>) -> Self {
143 Self { entries }
144 }
145
146 pub fn entries(&self) -> &[Ace] {
148 &self.entries
149 }
150
151 pub fn entries_mut(&mut self) -> &mut Vec<Ace> {
153 &mut self.entries
154 }
155
156 pub fn canonicalize(&mut self) {
160 self.entries.sort_by_key(|ace| {
161 let inherited_rank = if ace.inherited { 1u8 } else { 0u8 };
162 let type_rank = match ace.ace_type {
163 AceType::Deny => 0u8,
164 AceType::Allow => 1u8,
165 };
166 (inherited_rank, type_rank)
167 });
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::{AccessMask, Ace, AceType, Dacl};
174 use crate::security::Sid;
175
176 #[test]
177 fn canonicalize_places_explicit_deny_first() {
178 let user = Sid::parse("S-1-5-32-545").expect("valid sid");
179
180 let mut dacl = Dacl::from_entries(vec![
181 Ace::new(user.clone(), AceType::Allow, AccessMask::from_bits(0x2)),
182 Ace::new(user.clone(), AceType::Deny, AccessMask::from_bits(0x1)),
183 Ace::new(user.clone(), AceType::Allow, AccessMask::from_bits(0x4)).inherited(true),
184 ]);
185
186 dacl.canonicalize();
187
188 assert_eq!(dacl.entries()[0].ace_type, AceType::Deny);
189 assert!(!dacl.entries()[0].inherited);
190 }
191}