Skip to main content

dolang_winterop/security/
access_mask.rs

1bitflags::bitflags! {
2/// Generic `ACCESS_MASK` flags.
3///
4/// These apply to any securable object type (registry keys, services, files, ...), as opposed to
5/// bits whose meaning is specific to one object type (e.g. `KEY_QUERY_VALUE`, `SERVICE_START`).
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
7pub struct AccessMask: u32 {
8    /// All object-specific rights in the low 16 bits.
9    const SPECIFIC_RIGHTS_ALL = 0x0000_FFFF;
10    /// Grants the right to delete the object.
11    const DELETE = 0x0001_0000;
12    /// Grants the right to read the object's security descriptor.
13    const READ_CONTROL = 0x0002_0000;
14    /// Grants the right to modify the discretionary ACL.
15    const WRITE_DAC = 0x0004_0000;
16    /// Grants the right to change the owner or primary group.
17    const WRITE_OWNER = 0x0008_0000;
18    /// Grants the synchronization right.
19    const SYNCHRONIZE = 0x0010_0000;
20    /// Combines the standard rights required by an object type.
21    const STANDARD_RIGHTS_REQUIRED = 0x000F_0000;
22    /// Combines all standard rights.
23    const STANDARD_RIGHTS_ALL = 0x001F_0000;
24    /// Requests access to the system ACL; enabling `SeSecurityPrivilege` may be required.
25    const ACCESS_SYSTEM_SECURITY = 0x0100_0000;
26    /// Asks the system to grant the maximum permitted access.
27    const MAXIMUM_ALLOWED = 0x0200_0000;
28    /// Generic all-access mapping bit.
29    const GENERIC_ALL = 0x1000_0000;
30    /// Generic execute-access mapping bit.
31    const GENERIC_EXECUTE = 0x2000_0000;
32    /// Generic write-access mapping bit.
33    const GENERIC_WRITE = 0x4000_0000;
34    /// Generic read-access mapping bit.
35    const GENERIC_READ = 0x8000_0000;
36}
37}
38
39impl AccessMask {
40    /// Returns the object-specific low 16 bits.
41    pub const fn specific_rights(self) -> u16 {
42        self.bits() as u16
43    }
44
45    /// Creates a mask from object-specific low 16 bits.
46    pub const fn from_specific_rights(rights: u16) -> Self {
47        Self::from_bits_retain(rights as u32)
48    }
49
50    /// Returns the standard and system-access rights.
51    pub const fn standard_rights(self) -> Self {
52        self.intersection(Self::from_bits_retain(0x0FFF_0000))
53    }
54
55    /// Returns the generic mapping rights.
56    pub const fn generic_rights(self) -> Self {
57        self.intersection(Self::from_bits_retain(0xF000_0000))
58    }
59}
60
61bitflags::bitflags! {
62    /// Native `SE_GROUP_*` attributes attached to token groups.
63    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
64    pub struct TokenGroupAttributes: u32 {
65        const MANDATORY = 0x0000_0001;
66        const ENABLED_BY_DEFAULT = 0x0000_0002;
67        const ENABLED = 0x0000_0004;
68        const OWNER = 0x0000_0008;
69        const USE_FOR_DENY_ONLY = 0x0000_0010;
70        const INTEGRITY = 0x0000_0020;
71        const INTEGRITY_ENABLED = 0x0000_0040;
72        const RESOURCE = 0x2000_0000;
73        const LOGON_ID = 0xC000_0000;
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn serde_preserves_bits() {
83        let mask = AccessMask::from_specific_rights(0x8123)
84            | AccessMask::READ_CONTROL
85            | AccessMask::GENERIC_READ
86            | AccessMask::from_bits_retain(0x0080_0000);
87        let encoded = postcard::to_stdvec(&mask).unwrap();
88        assert_eq!(encoded, postcard::to_stdvec(&mask.bits()).unwrap());
89        assert_eq!(postcard::from_bytes::<AccessMask>(&encoded).unwrap(), mask);
90        assert_eq!(mask.specific_rights(), 0x8123);
91        assert_eq!(
92            mask.standard_rights(),
93            AccessMask::READ_CONTROL | AccessMask::from_bits_retain(0x0080_0000)
94        );
95        assert_eq!(mask.generic_rights(), AccessMask::GENERIC_READ);
96    }
97
98    #[test]
99    fn token_group_attributes_preserve_unknown_bits() {
100        let attributes = TokenGroupAttributes::LOGON_ID
101            | TokenGroupAttributes::ENABLED
102            | TokenGroupAttributes::from_bits_retain(0x1000_0000);
103        let encoded = postcard::to_stdvec(&attributes).unwrap();
104        assert_eq!(encoded, postcard::to_stdvec(&attributes.bits()).unwrap());
105        assert_eq!(
106            postcard::from_bytes::<TokenGroupAttributes>(&encoded).unwrap(),
107            attributes
108        );
109    }
110}