Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ACEs and Security Descriptors

ACE types

The AceType enum covers all 21 MS-DTYP ACE type variants:

CategoryTypesSDDLNumeric
BasicAccessAllowed, AccessDeniedA, D0x00, 0x01
AuditSystemAudit, SystemAlarmAU, AL0x02, 0x03
ObjectAccessAllowedObject, AccessDeniedObject, SystemAuditObject, SystemAlarmObjectOA, OD, OU, OL0x05–0x08
CallbackAccessAllowedCallback, AccessDeniedCallback, + Object variantsXA, XD, ZA, ZD, XU, XL, ZU, ZL0x09–0x10
SpecialSystemMandatoryLabel, SystemResourceAttribute, SystemScopedPolicyIdML, RA, SP0x11–0x13

Classification methods: is_allow(), is_deny(), is_audit(), is_object_type(), is_callback(), is_mandatory_label(), is_dacl_type(), is_sacl_type().

ACE flags

Inheritance and audit flags on each ACE:

#![allow(unused)]
fn main() {
use win_sd::AceFlags;

let flags = AceFlags::CONTAINER_INHERIT | AceFlags::OBJECT_INHERIT;
assert!(flags.contains(AceFlags::CONTAINER_INHERIT));
assert!(!flags.is_inherited());
}
FlagValueMeaning
OBJECT_INHERIT0x01Non-container children inherit
CONTAINER_INHERIT0x02Container children inherit
NO_PROPAGATE_INHERIT0x04Stop propagation to grandchildren
INHERIT_ONLY0x08Does not apply to this object
INHERITED_ACE0x10Was inherited from parent
SUCCESSFUL_ACCESS0x40Audit on success (SACL)
FAILED_ACCESS0x80Audit on failure (SACL)

ACE entries

An Ace carries type, flags, mask, SID, and optional GUID/application data:

#![allow(unused)]
fn main() {
use win_sd::{Ace, AccessMask, Sid};

// Convenience constructors
let allow = Ace::allow(Sid::everyone(), AccessMask::FILE_GENERIC_READ);
let deny = Ace::deny(Sid::anonymous(), AccessMask::FILE_ALL_ACCESS);
let audit = Ace::audit(Sid::everyone(), AccessMask::FILE_WRITE_DATA);

// Object ACE with GUID
let guid = "bf967aba-0de6-11d0-a285-00aa003049e2".parse().unwrap();
let obj_ace = Ace::allow_object(
    Sid::administrators(),
    AccessMask::new(0x0010),  // ADS_RIGHT_DS_READ_PROP
    Some(guid),
    None,
);
assert!(obj_ace.ace_type().is_object_type());
assert!(obj_ace.object_type().is_some());
}

WinAcl

An ordered collection of ACEs, used for both DACLs and SACLs:

#![allow(unused)]
fn main() {
use win_sd::{WinAcl, Ace, AccessMask, Sid};

let mut acl = WinAcl::new();
acl.add_ace(Ace::deny(Sid::anonymous(), AccessMask::FILE_ALL_ACCESS));
acl.add_ace(Ace::allow(Sid::everyone(), AccessMask::FILE_GENERIC_READ));

assert!(acl.is_canonical());  // deny before allow
assert_eq!(acl.ace_count(), 2);

// Canonicalize sorts into MS-recommended order:
// explicit deny → explicit allow → inherited deny → inherited allow
acl.canonicalize();
}

SecurityDescriptor

The top-level container:

#![allow(unused)]
fn main() {
use win_sd::{SecurityDescriptor, SecurityDescriptorBuilder, AccessMask, Sid};
use win_sd::{IntegrityLevel, IntegrityPolicy};

let sd = SecurityDescriptorBuilder::new()
    .owner(Sid::local_system())
    .group(Sid::administrators())
    .deny(Sid::anonymous(), AccessMask::FILE_ALL_ACCESS)
    .allow(Sid::administrators(), AccessMask::FILE_ALL_ACCESS)
    .allow(Sid::everyone(), AccessMask::FILE_GENERIC_READ)
    .mandatory_label(IntegrityLevel::High, IntegrityPolicy::NO_WRITE_UP)
    .protected_dacl(true)
    .build();

assert!(sd.is_valid().is_ok());
assert!(sd.control().dacl_present());
assert!(sd.control().dacl_protected());
assert!(sd.dacl().unwrap().is_canonical());
assert!(sd.sacl().is_some());  // mandatory label is in the SACL
}

The builder automatically sets DACL_PRESENT/SACL_PRESENT flags and canonicalizes ACE ordering.