sddl 0.1.6

a library to parse and analyse SDDL Strings
Documentation
use binrw::BinRead;
use binrw::BinReaderExt;
use binrw::BinWrite;
use binrw::BinWriterExt;
use enumflags2::{bitflags, BitFlags};
use serde::Serialize;

use crate::*;
/// <https://github.com/microsoft/referencesource/blob/master/mscorlib/system/security/accesscontrol/securitydescriptor.cs>
#[derive(Eq, PartialEq, Debug, Copy, Clone, Serialize)]
#[repr(u16)]
#[allow(non_camel_case_types)]
#[bitflags]
pub enum ControlFlag {
    OwnerDefaulted = 0x0001,                      // set by RM only
    GroupDefaulted = 0x0002,                      // set by RM only
    DiscretionaryAclPresent = 0x0004,             // set by RM or user, 'off' means DACL is null
    DiscretionaryAclDefaulted = 0x0008,           // set by RM only
    SystemAclPresent = 0x0010,                    // same as DiscretionaryAclPresent
    SystemAclDefaulted = 0x0020,                  // sams as DiscretionaryAclDefaulted
    DiscretionaryAclUntrusted = 0x0040,           // ignore this one
    ServerSecurity = 0x0080,                      // ignore this one
    DiscretionaryAclAutoInheritRequired = 0x0100, // ignore this one
    SystemAclAutoInheritRequired = 0x0200,        // ignore this one
    DiscretionaryAclAutoInherited = 0x0400,       // set by RM only
    SystemAclAutoInherited = 0x0800,              // set by RM only
    DiscretionaryAclProtected = 0x1000,           // when set, RM will stop inheriting
    SystemAclProtected = 0x2000,                  // when set, RM will stop inheriting
    RMControlValid = 0x4000,                      // the reserved 8 bits have some meaning
    SelfRelative = 0x8000,                        // must always be on
}

flag_wrapper!(ControlFlags, ControlFlag, u16);

#[macro_export]
macro_rules! control_flags {
    ( $($variant:ident)|* ) => {
        {
            use $crate::ControlFlag;
            $crate::ControlFlags::from_bitflags(enumflags2::make_bitflags!(ControlFlag::{$($variant)|*}))
        }
    };
    ($flag:ident) => {
        {
            use $crate::ControlFlag;
            $crate::ControlFlags::from_bitflags(enumflags2::make_bitflags!(ControlFlag::{$flag}))
        }
    };
}

impl ControlFlags {
    pub fn remove_sacl_flags(self) -> Self {
        Self::from(
            self.flags
                & !(crate::ControlFlag::SystemAclProtected
                    | crate::ControlFlag::SystemAclAutoInheritRequired
                    | crate::ControlFlag::SystemAclAutoInherited),
        )
    }

    pub fn remove_dacl_flags(self) -> Self {
        Self::from(
            self.flags
                & !(crate::ControlFlag::DiscretionaryAclProtected
                    | crate::ControlFlag::DiscretionaryAclAutoInheritRequired
                    | crate::ControlFlag::DiscretionaryAclAutoInherited),
        )
    }

    pub fn sddl_string(&self, acl_type: acl::Type) -> String {
        if self.flags == BitFlags::<ControlFlag, u16>::EMPTY {
            SDDL_NULL_ACL.into()
        } else {
            let mut sddl = String::with_capacity(32);
            let mut flag = |flag: ControlFlag, s: &str| {
                if self.flags.contains(flag) {
                    sddl.push_str(s);
                }
            };

            match acl_type {
                acl::Type::SACL => {
                    flag(ControlFlag::SystemAclProtected, SDDL_PROTECTED);
                    flag(
                        ControlFlag::SystemAclAutoInheritRequired,
                        SDDL_AUTO_INHERIT_REQ,
                    );
                    flag(ControlFlag::SystemAclAutoInherited, SDDL_AUTO_INHERITED);
                }
                acl::Type::DACL => {
                    flag(ControlFlag::DiscretionaryAclProtected, SDDL_PROTECTED);
                    flag(
                        ControlFlag::DiscretionaryAclAutoInheritRequired,
                        SDDL_AUTO_INHERIT_REQ,
                    );
                    flag(
                        ControlFlag::DiscretionaryAclAutoInherited,
                        SDDL_AUTO_INHERITED,
                    );
                }
            }
            sddl
        }
    }
}