1use binrw::io::TakeSeekExt;
4use binrw::prelude::*;
5use modular_bitfield::prelude::*;
6use smb_dtyp_derive::mbitfield;
7
8use crate::{binrw_util::prelude::*, guid::Guid};
9
10use super::SID;
11
12#[macro_export]
20macro_rules! access_mask {
21 (
22 $(#[$meta:meta])*
23 $vis:vis struct $name:ident {
24 $(
25 $(#[$field_meta:meta])*
26 $field_name:ident : $field_ty:ty,
27 )*
28 }) => {
29
30 #[::modular_bitfield::bitfield]
31 #[derive(::binrw::BinWrite, ::binrw::BinRead, Debug, Default, Clone, Copy, PartialEq, Eq)]
32 #[bw(map = |&x| Self::into_bytes(x))]
33 #[br(map = Self::from_bytes)]
34 $(#[$meta])*
35 $vis struct $name {
40 $(
42 $(#[$field_meta])*
43 pub $field_name : $field_ty,
44 )*
45
46 pub delete: bool,
48 pub read_control: bool,
50 pub write_dacl: bool,
52 pub write_owner: bool,
54 pub synchronize: bool,
57 #[skip]
58 __: ::modular_bitfield::prelude::B3,
59
60 pub access_system_security: bool,
64
65 pub maximum_allowed: bool,
69 #[skip]
70 __: ::modular_bitfield::prelude::B2,
71
72 pub generic_all: bool,
74 pub generic_execute: bool,
76 pub generic_write: bool,
78 pub generic_read: bool,
80 }
81 };
82
83}
84
85#[binrw::binrw]
86#[derive(Debug, PartialEq, Eq, Clone)]
87pub struct ACE {
88 #[bw(calc = value.get_type())]
89 #[br(temp)]
90 pub ace_type: AceType,
91 pub ace_flags: AceFlags,
92 #[bw(calc = PosMarker::default())]
93 #[br(temp)]
94 _ace_size: PosMarker<u16>,
95 #[br(args(ace_type))]
96 #[br(map_stream = |s| s.take_seek(_ace_size.value as u64 - Self::HEADER_SIZE))]
97 #[bw(write_with = PosMarker::write_size_plus, args(&_ace_size, Self::HEADER_SIZE))]
98 pub value: AceValue,
99}
100
101impl ACE {
102 const HEADER_SIZE: u64 = 4;
103
104 #[inline]
108 pub fn ace_type(&self) -> AceType {
109 self.value.get_type()
110 }
111}
112
113macro_rules! make_ace_value {
114 (
115 $($type:ident($val:ident),)+
116 ) => {
117 pastey::paste! {
118
119#[binrw::binrw]
120#[derive(Debug, PartialEq, Eq, Clone)]
121#[br(import(ace_type: AceType))]
122pub enum AceValue {
123 $(
124 #[br(pre_assert(matches!(ace_type, AceType::$type)))]
125 $type($val),
126 )+
127}
128
129impl AceValue {
130 pub fn get_type(&self) -> AceType {
131 match self {
132 $(
133 AceValue::$type(_) => AceType::$type,
134 )+
135 }
136 }
137
138 $(
139 pub fn [<unwrap_ $type:snake>](&self) -> &$val {
140 match self {
141 AceValue::$type(v) => v,
142 _ => panic!("Called unwrap_{} on a different AceValue variant", stringify!($type).to_lowercase()),
143 }
144 }
145
146 pub fn [<as_ $type:snake>](&self) -> Option<&$val> {
147 match self {
148 AceValue::$type(v) => Some(v),
149 _ => None,
150 }
151 }
152
153 pub fn [<as_mut_ $type:snake>](&mut self) -> Option<&mut $val> {
154 match self {
155 AceValue::$type(v) => Some(v),
156 _ => None,
157 }
158 }
159 )+
160}
161
162 }
163 };
164}
165
166make_ace_value! {
167 AccessAllowed(AccessAce),
168 AccessDenied(AccessAce),
169 SystemAudit(AccessAce),
170 AccessAllowedObject(AccessObjectAce),
171 AccessDeniedObject(AccessObjectAce),
172 SystemAuditObject(AccessObjectAce),
173 AccessAllowedCallback(AccessCallbackAce),
174 AccessDeniedCallback(AccessCallbackAce),
175 AccessAllowedCallbackObject(AccessObjectCallbackAce),
176 AccessDeniedCallbackObject(AccessObjectCallbackAce),
177 SystemAuditCallback(AccessCallbackAce),
178 SystemAuditCallbackObject(AccessObjectCallbackAce),
179 SystemMandatoryLabel(SystemMandatoryLabelAce),
180 SystemResourceAttribute(SystemResourceAttributeAce),
181 SystemScopedPolicyId(AccessAce),
182}
183
184impl AceValue {
185 pub fn is_access_allowed(&self) -> bool {
187 matches!(
188 self.get_type(),
189 AceType::AccessAllowed
190 | AceType::AccessAllowedObject
191 | AceType::AccessAllowedCallback
192 | AceType::AccessAllowedCallbackObject
193 )
194 }
195
196 pub fn is_access_denied(&self) -> bool {
198 matches!(
199 self.get_type(),
200 AceType::AccessDenied
201 | AceType::AccessDeniedObject
202 | AceType::AccessDeniedCallback
203 | AceType::AccessDeniedCallbackObject
204 )
205 }
206}
207
208#[binrw::binrw]
209#[derive(Debug, PartialEq, Eq, Clone)]
210pub struct AccessAce {
211 pub access_mask: AccessMask,
212 pub sid: SID,
213}
214
215access_mask! {
216pub struct AccessMask {
217 common: B16,
218}}
219
220access_mask! {
221pub struct ObjectAccessMask {
222 crate_child: bool,
223 delete_child: bool,
224 #[skip]
225 __: bool,
226 ds_self: bool,
227
228 read_prop: bool,
229 write_prop: bool,
230 #[skip]
231 __: B2,
232
233 control_access: bool,
234 #[skip]
235 __: B7,
236}}
237
238access_mask! {
239pub struct MandatoryLabelAccessMask {
240 no_write_up: bool,
241 no_read_up: bool,
242 no_execute_up: bool,
243 #[skip]
244 __: B13,
245}}
246
247#[binrw::binrw]
248#[derive(Debug, PartialEq, Eq, Clone)]
249pub struct AccessObjectAce {
250 pub access_mask: ObjectAccessMask,
251 #[bw(calc = ObjectAceFlags::new().with_object_type_present(object_type.is_some()).with_inherited_object_type_present(inherited_object_type.is_some()))]
252 #[br(temp)]
253 pub flags: ObjectAceFlags,
254 #[br(if(flags.object_type_present()))]
255 pub object_type: Option<Guid>,
256 #[br(if(flags.inherited_object_type_present()))]
257 pub inherited_object_type: Option<Guid>,
258 pub sid: SID,
259}
260
261#[mbitfield]
262pub struct ObjectAceFlags {
263 pub object_type_present: bool,
264 pub inherited_object_type_present: bool,
265 #[skip]
266 __: B30,
267}
268
269#[binrw::binrw]
270#[derive(Debug, PartialEq, Eq, Clone)]
271pub struct AccessCallbackAce {
272 pub access_mask: AccessMask,
273 pub sid: SID,
274 #[br(parse_with = binrw::helpers::until_eof)]
275 pub application_data: Vec<u8>,
276}
277
278#[binrw::binrw]
279#[derive(Debug, PartialEq, Eq, Clone)]
280pub struct AccessObjectCallbackAce {
281 pub access_mask: ObjectAccessMask,
282 #[bw(calc = ObjectAceFlags::new().with_object_type_present(object_type.is_some()).with_inherited_object_type_present(inherited_object_type.is_some()))]
283 #[br(temp)]
284 pub flags: ObjectAceFlags,
285 #[br(if(flags.object_type_present()))]
286 pub object_type: Option<Guid>,
287 #[br(if(flags.inherited_object_type_present()))]
288 pub inherited_object_type: Option<Guid>,
289 pub sid: SID,
290 #[br(parse_with = binrw::helpers::until_eof)]
291 pub application_data: Vec<u8>,
292}
293
294#[binrw::binrw]
295#[derive(Debug, PartialEq, Eq, Clone)]
296pub struct SystemMandatoryLabelAce {
297 pub mask: MandatoryLabelAccessMask,
298 pub sid: SID,
299}
300#[binrw::binrw]
301#[derive(Debug, PartialEq, Eq, Clone)]
302pub struct SystemResourceAttributeAce {
303 pub mask: AccessMask,
304 pub sid: SID,
305 pub attribute_data: ClaimSecurityAttributeRelativeV1,
306}
307
308#[binrw::binrw]
309#[derive(Debug, PartialEq, Eq, Clone)]
310pub struct ClaimSecurityAttributeRelativeV1 {
311 #[bw(calc = PosMarker::default())]
312 #[br(temp)]
313 _name: PosMarker<u32>, pub value_type: ClaimSecurityAttributeType,
315 #[bw(calc = 0)]
316 #[br(temp)]
317 _reserved: u16,
318 pub flags: FciClaimSecurityAttributes,
319 value_count: u32,
320 #[br(parse_with = binrw::helpers::until_eof)]
321 pub value: Vec<u8>, }
323
324#[binrw::binrw]
325#[derive(Debug, PartialEq, Eq, Clone, Copy)]
326#[brw(repr(u16))]
327pub enum ClaimSecurityAttributeType {
328 None = 0,
329 Int64 = 1,
330 Uint64 = 2,
331 String = 3,
332 SID = 4,
333 Boolean = 5,
334 OctetString = 6,
335}
336
337#[mbitfield]
338pub struct FciClaimSecurityAttributes {
339 pub non_inheritable: bool,
340 pub value_case_sensitive: bool,
341 pub use_for_deny_only: bool,
342 pub disabled_by_default: bool,
343
344 pub disabled: bool,
345 pub mandatory: bool,
346 #[skip]
347 __: B2,
348
349 pub manual: bool,
350 pub policy_derived: bool,
351 #[skip]
352 __: B6,
353}
354
355#[binrw::binrw]
356#[derive(Debug, PartialEq, Eq, Clone, Copy)]
357#[brw(repr(u8))]
358pub enum AceType {
359 AccessAllowed = 0,
360 AccessDenied = 1,
361 SystemAudit = 2,
362 SystemAlarm = 3,
363 AccessAllowedCompound = 4,
364 AccessAllowedObject = 5,
365 AccessDeniedObject = 6,
366 SystemAuditObject = 7,
367 SystemAlarmObject = 8,
368 AccessAllowedCallback = 9,
369 AccessDeniedCallback = 10,
370 AccessAllowedCallbackObject = 11,
371 AccessDeniedCallbackObject = 12,
372 SystemAuditCallback = 13,
373 SystemAlarmCallback = 14,
374 SystemAuditCallbackObject = 15,
375 SystemAlarmCallbackObject = 16,
376 SystemMandatoryLabel = 17,
377 SystemResourceAttribute = 18,
378 SystemScopedPolicyId = 19,
379}
380
381#[mbitfield]
382pub struct AceFlags {
383 pub object_inherit: bool,
384 pub container_inherit: bool,
385 pub no_propagate_inherit: bool,
386 pub inherit_only: bool,
387
388 pub inherited: bool,
389 #[skip]
390 __: bool,
391 pub successful_access: bool,
392 pub failed_access: bool,
393}