1use binrw::prelude::*;
4
5use crate::binrw_util::prelude::*;
6
7use super::ACE;
8
9#[binrw::binrw]
10#[derive(Debug, PartialEq, Eq, Clone)]
11pub struct ACL {
12 pub acl_revision: AclRevision,
13 #[bw(calc = 0)]
14 #[br(assert(sbz1 == 0))]
15 sbz1: u8,
16 #[bw(calc = PosMarker::default())]
17 _acl_size: PosMarker<u16>,
18 #[bw(calc = ace.len() as u16)]
19 ace_count: u16,
20 #[bw(calc = 0)]
21 #[br(assert(sbz2 == 0))]
22 sbz2: u16,
23
24 #[br(count = ace_count)]
25 #[bw(write_with = PosMarker::write_size_plus, args(&_acl_size, Self::HEADER_SIZE))]
26 pub ace: Vec<ACE>,
27}
28
29impl ACL {
30 const HEADER_SIZE: u64 = 8;
31
32 pub fn order_aces(&mut self) {
45 self.ace.sort_by(Self::sort_aces_by);
46 }
47
48 pub fn is_ace_sorted(&self) -> bool {
52 self.ace
53 .is_sorted_by(|a, b| Self::sort_aces_by(a, b).is_le())
54 }
55
56 fn sort_aces_by(a: &ACE, b: &ACE) -> std::cmp::Ordering {
60 let a_inherited = a.ace_flags.inherited();
61 let b_inherited = b.ace_flags.inherited();
62 if a_inherited != b_inherited {
63 return a_inherited.cmp(&b_inherited); }
65 if a_inherited {
66 return std::cmp::Ordering::Equal; }
68 let a_denied = a.value.is_access_allowed();
69 let b_denied = b.value.is_access_allowed();
70 a_denied.cmp(&b_denied) }
73
74 pub fn insert_ace(&mut self, ace: ACE) {
77 self.ace.push(ace);
78 self.order_aces();
79 }
80}
81
82#[binrw::binrw]
83#[derive(Debug, PartialEq, Eq, Copy, Clone)]
84#[brw(repr(u8))]
85pub enum AclRevision {
86 Nt4 = 2,
88 DS = 4,
90}
91
92#[cfg(test)]
93mod tests {
94 use crate::security::{AccessAce, AccessMask, AceFlags, AceValue, SID};
95 use std::str::FromStr;
96
97 use super::*;
98 #[test]
99 fn test_sort_acls() {
100 let fake_access_ace = AccessAce {
101 access_mask: AccessMask::new(),
102 sid: SID::from_str(SID::S_EVERYONE).unwrap(),
103 };
104 let explicit_deny_first = ACE {
105 ace_flags: AceFlags::new().with_inherited(false),
106 value: AceValue::AccessDenied(fake_access_ace.clone()),
107 };
108 let explicit_allow_second = ACE {
109 ace_flags: AceFlags::new().with_inherited(false),
110 value: AceValue::AccessAllowed(fake_access_ace.clone()),
111 };
112 let inherited_last_1 = ACE {
114 ace_flags: AceFlags::new().with_inherited(true),
115 value: AceValue::AccessAllowed(fake_access_ace.clone()),
116 };
117 let inherited_last_2 = ACE {
118 ace_flags: AceFlags::new().with_inherited(true),
119 value: AceValue::AccessDenied(fake_access_ace.clone()),
120 };
121 let dacl = ACL {
122 acl_revision: AclRevision::Nt4,
123 ace: vec![
124 inherited_last_1.clone(), explicit_allow_second.clone(), explicit_deny_first.clone(), inherited_last_2.clone(), ],
129 };
130
131 assert!(!dacl.is_ace_sorted());
132
133 let mut new_dacl = dacl.clone();
134 new_dacl.order_aces();
135
136 assert!(new_dacl.is_ace_sorted());
137
138 assert_eq!(
139 new_dacl,
140 ACL {
141 acl_revision: AclRevision::Nt4,
142 ace: vec![
143 explicit_deny_first,
144 explicit_allow_second,
145 inherited_last_1,
146 inherited_last_2,
147 ]
148 }
149 );
150 }
151}