sddl 0.1.3

a library to parse and analyse SDDL Strings
Documentation
use std::str::FromStr;
use crate::*;
grammar(domain_rid: Option<&[u32]>);

extern {
    type Error = Error;
}

pub SecurityDescriptor: SecurityDescriptor = {
    // only DACL or DACL first and SACL second
    "O:" <owner: SidOrAlias> "G:" <group: SidOrAlias> <dacl: DAcl> <sacl: SAcl?> =>? {
        Ok(SecurityDescriptor::new(Some(owner), Some(group), Some(dacl), sacl))
    },

    // only SACL or SACL first and DACL second
    "O:" <owner: SidOrAlias> "G:" <group: SidOrAlias> <sacl: SAcl> <dacl: DAcl?> =>? {
        Ok(SecurityDescriptor::new(Some(owner), Some(group), dacl, Some(sacl)))
    },
}

// (Type;Flags;Access;[ObjectType];[InheritedObjectType];SID[;ExtraData])

// there is no way to parse SACL and DACL flags separately. So, we set both,
// the DACL and SACL flags, and delete the unwanted flags afterwards
pub Acl: Acl = { <dacl: DAcl> => dacl, <sacl: SAcl> => sacl, }

pub DAcl: Acl = {
    "D:" <flags: AclFlags?> <ace_list: Ace*> => Acl::new(
        acl::Revision::ACL_REVISION,
        acl::Type::DACL,
        flags.unwrap_or(ControlFlags::empty()).remove_sacl_flags(),
        ace_list
    ),
}

pub SAcl: Acl = {
    "S:" <flags: AclFlags?> <ace_list: Ace*> => Acl::new(
        acl::Revision::ACL_REVISION,
        acl::Type::SACL,
        flags.unwrap_or(ControlFlags::empty()).remove_dacl_flags(),
        ace_list
    )
}

// "PAR" and "PAI" conflict with the well-known SID "PA", so we create distinct tokens for these flags
pub AclFlags: ControlFlags = {
    "P" =>      control_flags!(
                    SystemAclProtected |
                    DiscretionaryAclProtected),

    "PAR"   =>  control_flags!(
                    SystemAclProtected |
                    DiscretionaryAclProtected |
                    SystemAclAutoInheritRequired |
                    DiscretionaryAclAutoInheritRequired),

    "PAI"   =>  control_flags!(
                    SystemAclProtected |
                    DiscretionaryAclProtected |
                    SystemAclAutoInherited |
                    DiscretionaryAclAutoInherited),
    
    "PAIAR" =>  control_flags!(
                    SystemAclProtected |
                    DiscretionaryAclProtected |
                    SystemAclAutoInherited |
                    DiscretionaryAclAutoInherited |
                    SystemAclAutoInheritRequired |
                    DiscretionaryAclAutoInheritRequired),
    
    "PARAI" =>  control_flags!(
                    SystemAclProtected |
                    DiscretionaryAclProtected |
                    SystemAclAutoInherited |
                    DiscretionaryAclAutoInherited |
                    SystemAclAutoInheritRequired |
                    DiscretionaryAclAutoInheritRequired),

    "AR" =>     control_flags!(
                    SystemAclAutoInheritRequired |
                    DiscretionaryAclAutoInheritRequired),
    "AI" =>     control_flags!(
                    SystemAclAutoInherited |
                    DiscretionaryAclAutoInherited)
}

SingleAclFlag: ControlFlags = {
    "P" => control_flags!(SystemAclProtected | DiscretionaryAclProtected),
    "AR" => control_flags!(SystemAclAutoInheritRequired | DiscretionaryAclAutoInheritRequired),
    "AI" => control_flags!(SystemAclAutoInherited | DiscretionaryAclAutoInherited),
}

pub Ace: Ace = {
    "(A;"  <a: AceSimpleData> ")" => a.into_ace(ace::Type::ACCESS_ALLOWED_ACE_TYPE),
    "(D;"  <a: AceSimpleData> ")" => a.into_ace(ace::Type::ACCESS_DENIED_ACE_TYPE),
    "(OA;" <a: AceSimpleData> ")" => a.into_ace(ace::Type::ACCESS_ALLOWED_OBJECT_ACE_TYPE),
    "(OD;" <a: AceSimpleData> ")" => a.into_ace(ace::Type::ACCESS_DENIED_OBJECT_ACE_TYPE),
    "(AU;" <a: AceSimpleData> ")" => a.into_ace(ace::Type::SYSTEM_AUDIT_ACE_TYPE),
    "(OU;" <a: AceSimpleData> ")" => a.into_ace(ace::Type::SYSTEM_AUDIT_OBJECT_ACE_TYPE),
    "(ML;" <a: AceSimpleData> ")" => a.into_ace(ace::Type::SYSTEM_MANDATORY_LABEL_ACE_TYPE),
    "(SP;" <a: AceSimpleData> ")" => a.into_ace(ace::Type::SYSTEM_SCOPED_POLICY_ID_ACE_TYPE)
}
/*
pub ConditionalAce: Ace = {
    //"(XA;" <a: AceSidAppdata> ")" => Ace::access_allowed_callback(a.0, a.1, a.2, a.3),
    //"(XD;" <a: AceSidAppdata> ")" => Ace::access_denied_callback(a.0, a.1, a.2, a.3),
    //"(ZA;" <a: AceSidObjectAppdata> ")" => Ace::access_allowed_object_callback(a.0, a.1, a.2, a.3, a.4, a.5),
    //"(ZD;" <a: AceSidObjectAppdata> ")" => Ace::access_denied_object_callback(a.0, a.1, a.2, a.3, a.4, a.5),
    //"(XU;" <a: AceSidAppdata> ")" => Ace::audit_callback(a.0, a.1, a.2, a.3),
    //"(ZU;" <a: AceSidObjectAppdata> ")" => Ace::audit_callback_object(a.0, a.1, a.2, a.3, a.4, a.5),
}
*/
AceSimpleData: ace::ParsedContents = {
    <flags: AceHeaderFlags> ";"
    <mask: AccessMask> ";"
    <object_type: Guid?> ";"
    <inherited_object_type: Guid?> ";"
    <sid: SidOrAlias> =>? {
        Ok(ace::ParsedContents::new(flags, mask, sid, object_type, inherited_object_type))
    }
}

SidOrAlias: Sid = {
    <alias: Alias> =>? Ok(Sid::try_from_alias(alias, domain_rid)?),
    <sid:r#"S-1-\d+(-\d+)*"#> =>? Ok(Sid::try_from(sid)?)
}

AceHeaderFlags: ace::header::Flags = {
    <s:AceHeaderFlagAlias*> =>? Ok(s.into_iter().fold(ace::header::Flags::empty(), |v, s| v|s ))
}

AceHeaderFlagAlias: ace::header::Flags = {
    <alias: Alias> =>? Ok(ace::header::Flags::try_from_alias(alias)?)
}

pub AccessMask: AccessMask = {
    <s:SingleAccessMask*> =>? Ok(s.into_iter().fold(AccessMask::empty(), |v, s| v|s )),
    <n:Number> =>? Ok(AccessMask::from(n)),
};

SingleAccessMask: AccessMask = {
    <alias: Alias> =>? Ok(AccessMask::try_from_alias(alias)?)
}

pub Guid: Guid = {
    <guid: r"[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}"> => guid.try_into().unwrap()
}

Alias: &'input str = {
    <alias: r"[A-Z]{2}"> => alias
}

Number: u32 = {
    <s:r#"0x[0-9a-fA-F]+"#> => {
        u32::from_str_radix(&s[2..], 16).unwrap()
    },
    <s:r#"0[0-7]+"#> => {
        u32::from_str_radix(s, 8).unwrap()
    },
    <s:r#"[1-9][0-9]*"#> => {
        u32::from_str(s).unwrap()
    }
}

/*
ace::Type: &'static str = {
    "A" => sddl_h::SDDL_ACCESS_ALLOWED,
    "D" => sddl_h::SDDL_ACCESS_DENIED,
    "AU" => sddl_h::SDDL_AUDIT,
    "AL" => sddl_h::SDDL_ALARM,
    "OA" => sddl_h::SDDL_OBJECT_ACCESS_ALLOWED,
    "OD" => sddl_h::SDDL_OBJECT_ACCESS_DENIED,
    "OU" => sddl_h::SDDL_OBJECT_AUDIT,
    "OL" => sddl_h::SDDL_OBJECT_ALARM,
    "XA" => sddl_h::SDDL_CALLBACK_ACCESS_ALLOWED,
    "XD" => sddl_h::SDDL_CALLBACK_ACCESS_DENIED,
    "ZA" => sddl_h::SDDL_CALLBACK_OBJECT_ACCESS_ALLOWED,
    "XU" => sddl_h::SDDL_CALLBACK_AUDIT,
    "ML" => sddl_h::SDDL_MANDATORY_LABEL,
    "RA" => sddl_h::SDDL_RESOURCE_ATTRIBUTE,
    "SP" => sddl_h::SDDL_SCOPED_POLICY_ID,
    "TL" => sddl_h::SDDL_PROCESS_TRUST_LABEL,
    "FL" => sddl_h::SDDL_ACCESS_FILTER,
}
*/