sddl/
control_flags.rs

1use binrw::BinRead;
2use binrw::BinReaderExt;
3use binrw::BinWrite;
4use binrw::BinWriterExt;
5use enumflags2::{bitflags, BitFlags};
6use serde::Serialize;
7
8use crate::*;
9/// <https://github.com/microsoft/referencesource/blob/master/mscorlib/system/security/accesscontrol/securitydescriptor.cs>
10#[derive(Eq, PartialEq, Debug, Copy, Clone, Serialize)]
11#[repr(u16)]
12#[allow(non_camel_case_types)]
13#[bitflags]
14pub enum ControlFlag {
15    OwnerDefaulted = 0x0001,                      // set by RM only
16    GroupDefaulted = 0x0002,                      // set by RM only
17    DiscretionaryAclPresent = 0x0004,             // set by RM or user, 'off' means DACL is null
18    DiscretionaryAclDefaulted = 0x0008,           // set by RM only
19    SystemAclPresent = 0x0010,                    // same as DiscretionaryAclPresent
20    SystemAclDefaulted = 0x0020,                  // sams as DiscretionaryAclDefaulted
21    DiscretionaryAclUntrusted = 0x0040,           // ignore this one
22    ServerSecurity = 0x0080,                      // ignore this one
23    DiscretionaryAclAutoInheritRequired = 0x0100, // ignore this one
24    SystemAclAutoInheritRequired = 0x0200,        // ignore this one
25    DiscretionaryAclAutoInherited = 0x0400,       // set by RM only
26    SystemAclAutoInherited = 0x0800,              // set by RM only
27    DiscretionaryAclProtected = 0x1000,           // when set, RM will stop inheriting
28    SystemAclProtected = 0x2000,                  // when set, RM will stop inheriting
29    RMControlValid = 0x4000,                      // the reserved 8 bits have some meaning
30    SelfRelative = 0x8000,                        // must always be on
31}
32
33flag_wrapper!(ControlFlags, ControlFlag, u16);
34
35#[macro_export]
36macro_rules! control_flags {
37    ( $($variant:ident)|* ) => {
38        {
39            use $crate::ControlFlag;
40            $crate::ControlFlags::from_bitflags(enumflags2::make_bitflags!(ControlFlag::{$($variant)|*}))
41        }
42    };
43    ($flag:ident) => {
44        {
45            use $crate::ControlFlag;
46            $crate::ControlFlags::from_bitflags(enumflags2::make_bitflags!(ControlFlag::{$flag}))
47        }
48    };
49}
50
51impl ControlFlags {
52    pub fn remove_sacl_flags(self) -> Self {
53        Self::from(
54            self.flags
55                & !(crate::ControlFlag::SystemAclProtected
56                    | crate::ControlFlag::SystemAclAutoInheritRequired
57                    | crate::ControlFlag::SystemAclAutoInherited),
58        )
59    }
60
61    pub fn remove_dacl_flags(self) -> Self {
62        Self::from(
63            self.flags
64                & !(crate::ControlFlag::DiscretionaryAclProtected
65                    | crate::ControlFlag::DiscretionaryAclAutoInheritRequired
66                    | crate::ControlFlag::DiscretionaryAclAutoInherited),
67        )
68    }
69
70    pub fn sddl_string(&self, acl_type: acl::Type) -> String {
71        if self.flags == BitFlags::<ControlFlag, u16>::EMPTY {
72            SDDL_NULL_ACL.into()
73        } else {
74            let mut sddl = String::with_capacity(32);
75            let mut flag = |flag: ControlFlag, s: &str| {
76                if self.flags.contains(flag) {
77                    sddl.push_str(s);
78                }
79            };
80
81            match acl_type {
82                acl::Type::SACL => {
83                    flag(ControlFlag::SystemAclProtected, SDDL_PROTECTED);
84                    flag(
85                        ControlFlag::SystemAclAutoInheritRequired,
86                        SDDL_AUTO_INHERIT_REQ,
87                    );
88                    flag(ControlFlag::SystemAclAutoInherited, SDDL_AUTO_INHERITED);
89                }
90                acl::Type::DACL => {
91                    flag(ControlFlag::DiscretionaryAclProtected, SDDL_PROTECTED);
92                    flag(
93                        ControlFlag::DiscretionaryAclAutoInheritRequired,
94                        SDDL_AUTO_INHERIT_REQ,
95                    );
96                    flag(
97                        ControlFlag::DiscretionaryAclAutoInherited,
98                        SDDL_AUTO_INHERITED,
99                    );
100                }
101            }
102            sddl
103        }
104    }
105}