1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
use binrw::{binrw, BinRead, BinReaderExt, BinWrite, BinWriterExt};
use bitflags::bitflags;
use getset::Getters;
use strum::Display;
use crate::{sddl_h::*, AccessMask};
#[binrw]
#[derive(Eq, PartialEq, Getters, Clone, Copy)]
#[getset(get = "pub")]
pub struct AceHeader {
/// An unsigned 8-bit integer that specifies a set of ACE type-specific
/// control flags.
ace_flags: AceFlags,
/// An unsigned 16-bit integer that specifies the size, in bytes, of the
/// ACE. The AceSize field can be greater than the sum of the individual
/// fields, but MUST be a multiple of 4 to ensure alignment on a DWORD
/// boundary. In cases where the AceSize field encompasses additional data
/// for the callback ACEs types, that data is implementation-specific.
/// Otherwise, this additional data is not interpreted and MUST be ignored.
#[brw(assert(ace_size%4 == 0))]
ace_size: u16,
mask: AccessMask,
}
/// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/628ebb1d-c509-4ea0-a10f-77ef97ca4586
#[repr(u8)]
#[binrw]
#[brw(repr=u8)]
#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Display, Clone, Copy, Debug)]
pub enum AceType {
/// Access-allowed ACE that uses the ACCESS_ALLOWED_ACE (section 2.4.4.2)
/// structure.
ACCESS_ALLOWED_ACE_TYPE = 0x00,
/// Access-denied ACE that uses the ACCESS_DENIED_ACE (section 2.4.4.4)
/// structure.
ACCESS_DENIED_ACE_TYPE = 0x01,
/// System-audit ACE that uses the SYSTEM_AUDIT_ACE (section 2.4.4.10)
/// structure.
SYSTEM_AUDIT_ACE_TYPE = 0x02,
/// Reserved for future use.
SYSTEM_ALARM_ACE_TYPE = 0x03,
/// Reserved for future use.
ACCESS_ALLOWED_COMPOUND_ACE_TYPE = 0x04,
/// Object-specific access-allowed ACE that uses the
/// ACCESS_ALLOWED_OBJECT_ACE (section 2.4.4.3) structure.
ACCESS_ALLOWED_OBJECT_ACE_TYPE = 0x05,
/// Object-specific access-denied ACE that uses the ACCESS_DENIED_OBJECT_ACE
/// (section 2.4.4.5) structure.
ACCESS_DENIED_OBJECT_ACE_TYPE = 0x06,
/// Object-specific system-audit ACE that uses the SYSTEM_AUDIT_OBJECT_ACE
/// (section 2.4.4.11) structure.
SYSTEM_AUDIT_OBJECT_ACE_TYPE = 0x07,
/// Reserved for future use.
SYSTEM_ALARM_OBJECT_ACE_TYPE = 0x08,
/// Access-allowed callback ACE that uses the ACCESS_ALLOWED_CALLBACK_ACE
/// (section 2.4.4.6) structure.
ACCESS_ALLOWED_CALLBACK_ACE_TYPE = 0x09,
/// Access-denied callback ACE that uses the ACCESS_DENIED_CALLBACK_ACE
/// (section 2.4.4.7) structure.
ACCESS_DENIED_CALLBACK_ACE_TYPE = 0x0a,
/// Object-specific access-allowed callback ACE that uses the
/// ACCESS_ALLOWED_CALLBACK_OBJECT_ACE (section 2.4.4.8) structure.
ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE = 0x0b,
/// Object-specific access-denied callback ACE that uses the
/// ACCESS_DENIED_CALLBACK_OBJECT_ACE (section 2.4.4.9) structure.
ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE = 0x0c,
/// System-audit callback ACE that uses the SYSTEM_AUDIT_CALLBACK_ACE
/// (section 2.4.4.12) structure.
SYSTEM_AUDIT_CALLBACK_ACE_TYPE = 0x0d,
/// Reserved for future use.
SYSTEM_ALARM_CALLBACK_ACE_TYPE = 0x0e,
/// System-audit callback ACE that uses the SYSTEM_AUDIT_CALLBACK_ACE
/// (section 2.4.4.12) structure.
SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE = 0x0f,
/// Reserved for future use.
SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE = 0x10,
/// Object-specific system-audit callback ACE that uses the
/// SYSTEM_AUDIT_CALLBACK_OBJECT_ACE (section 2.4.4.14) structure.
SYSTEM_MANDATORY_LABEL_ACE_TYPE = 0x11,
/// Reserved for future use.
SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE = 0x12,
/// Mandatory label ACE that uses the SYSTEM_MANDATORY_LABEL_ACE
/// (section 2.4.4.13) structure.
SYSTEM_SCOPED_POLICY_ID_ACE_TYPE = 0x13,
}
bitflags! {
///
/// <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/628ebb1d-c509-4ea0-a10f-77ef97ca4586>
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub struct AceFlags: u8 {
/// Child objects that are containers, such as directories, inherit the
/// ACE as an effective ACE. The inherited ACE is inheritable unless the
/// NO_PROPAGATE_INHERIT_ACE bit flag is also set.
const CONTAINER_INHERIT_ACE = 0x02;
/// Used with system-audit ACEs in a system access control list (SACL)
/// to generate audit messages for failed access attempts.
const FAILED_ACCESS_ACE_FLAG = 0x80;
/// Indicates an inherit-only ACE, which does not control access to the
/// object to which it is attached. If this flag is not set, the ACE is
/// an effective ACE that controls access to the object to which it is
/// attached.
///
/// Both effective and inherit-only ACEs can be inherited depending on
/// the state of the other inheritance flags.
const INHERIT_ONLY_ACE = 0x08;
/// Used to indicate that the ACE was inherited.<54> See section 2.5.3.5
/// for processing rules for setting this flag.
const INHERITED_ACE = 0x10;
/// If the ACE is inherited by a child object, the system clears the
/// OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags in the inherited
/// ACE. This prevents the ACE from being inherited by subsequent
/// generations of objects.
const NO_PROPAGATE_INHERIT_ACE = 0x04;
/// Noncontainer child objects inherit the ACE as an effective ACE.
///
/// For child objects that are containers, the ACE is inherited as an
/// inherit-only ACE unless the NO_PROPAGATE_INHERIT_ACE bit flag is
/// also set.
const OBJECT_INHERIT_ACE = 0x01;
/// Used with system-audit ACEs in a SACL to generate audit messages for
/// successful access attempts.
const SUCCESSFUL_ACCESS_ACE_FLAG = 0x40;
}
}
impl AceFlags {
pub fn sddl_string(&self) -> String {
let mut sddl = String::with_capacity(16);
if self.contains(Self::OBJECT_INHERIT_ACE) {
sddl.push_str(SDDL_OBJECT_INHERIT);
}
if self.contains(Self::CONTAINER_INHERIT_ACE) {
sddl.push_str(SDDL_CONTAINER_INHERIT);
}
if self.contains(Self::NO_PROPAGATE_INHERIT_ACE) {
sddl.push_str(SDDL_NO_PROPAGATE);
}
if self.contains(Self::INHERIT_ONLY_ACE) {
sddl.push_str(SDDL_INHERIT_ONLY);
}
if self.contains(Self::INHERITED_ACE) {
sddl.push_str(SDDL_INHERITED);
}
if self.contains(Self::SUCCESSFUL_ACCESS_ACE_FLAG) {
sddl.push_str(SDDL_AUDIT_SUCCESS);
}
if self.contains(Self::FAILED_ACCESS_ACE_FLAG) {
sddl.push_str(SDDL_AUDIT_FAILURE);
}
sddl
}
}
impl BinRead for AceFlags {
type Args<'a> = ();
fn read_options<R: std::io::Read + std::io::Seek>(
reader: &mut R,
endian: binrw::Endian,
args: Self::Args<'_>,
) -> binrw::BinResult<Self> {
let raw_value: u8 = reader.read_type_args(endian, args)?;
Ok(AceFlags::from_bits(raw_value).unwrap())
}
}
impl BinWrite for AceFlags {
type Args<'a> = ();
fn write_options<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
endian: binrw::Endian,
args: Self::Args<'_>,
) -> binrw::BinResult<()> {
let raw_value = self.bits();
writer.write_type_args(&raw_value, endian, args)
}
}