win-sd: Windows Security Descriptor Modeling
Your organisation runs both Windows and Linux. Files live on Samba shares,
Active Directory defines who can access what, and the security descriptors
that Windows puts on every object carry fine-grained permissions — read
extended attributes, write the DACL, take ownership — that go far beyond the
three-bit rwx of POSIX. win-sd provides Rust types that model the full
MS-DTYP security descriptor system, from individual access mask bits up
through complete DACLs, SACLs, SDDL parsing, the access-check algorithm,
conditional ACE expressions, mandatory integrity labels, and ACL inheritance.
Architecture
The crate is organised into layers, each building on the previous:
-
Foundation types —
Sid(Security Identifier with string parsing and well-known constants),AccessMask(32-bit permission bitmask with lattice algebra),Guid(128-bit UUID for Object ACEs). -
ACE model —
AceType(21 MS-DTYP ACE type variants),AceFlags(inheritance and audit flags),Ace(entry with optional GUIDs for Object ACEs, optionalapplication_datafor Callback ACEs, integrity level accessors, and structural validation). -
Security descriptor —
WinAcl(ordered ACE collection with canonical ordering),ControlFlags(16-bit SD control field),SecurityDescriptor(top-level container with owner/group/DACL/SACL),SecurityDescriptorBuilder(fluent construction with auto-canonicalization). -
SDDL — full parser and generator for the Security Descriptor Definition Language text format, with SID alias tables (well-known and domain-relative), rights alias tables, and domain context support.
-
Access check — the Windows access-check algorithm per MS-DTYP §2.5.3.2, with mandatory integrity enforcement, privilege handling, MAXIMUM_ALLOWED mode, callback ACE conditional evaluation, Object ACE GUID filtering, and restricted token support.
-
Advanced features — conditional ACE expression engine (AST, binary format parser/writer, evaluator with depth limit), mandatory integrity labels, generic rights mapping, binary self-relative format serialization, ACL inheritance propagation, resource attribute claims, and an access token model.
An acls-rs bridge connects everything to the algebraic permission system
via configurable PermissionMapping tables. Pre-defined mappings cover
file ("win" namespace), Active Directory ("ad"), and registry ("reg")
semantics. Unlike POSIX ACLs (which have no explicit denials), the bridge
populates both the grants and denials fields of GrantDenialPair.
Quick start
Add win-sd to your Cargo.toml:
[dependencies]
win-sd = "0.1"
With serde support:
[dependencies]
win-sd = { version = "0.1", features = ["serde"] }
Build a security descriptor, generate SDDL, and check access:
#![allow(unused)]
fn main() {
use win_sd::prelude::*;
// Build a security descriptor with a DACL
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)
.build();
// Generate SDDL
let sddl = generate::<SddlGenerator>(&sd).unwrap();
assert!(sddl.contains("(D;")); // deny ACE
assert!(sddl.contains("(A;")); // allow ACEs
// Parse it back
let recovered = parse::<SddlParser>(&sddl).unwrap();
assert_eq!(recovered.owner(), sd.owner());
// Check access — administrators can read
let result = sd.check_access(
&[Sid::administrators(), Sid::everyone()],
AccessMask::FILE_GENERIC_READ,
);
assert!(result.granted);
// Anonymous is denied
let result = sd.check_access(
&[Sid::anonymous(), Sid::everyone()],
AccessMask::FILE_GENERIC_READ,
);
assert!(!result.granted);
}
Full access check with token
The check_access_full method supports the complete Windows access-check
algorithm, including mandatory integrity, privileges, generic rights mapping,
conditional ACE evaluation, and restricted tokens:
#![allow(unused)]
fn main() {
use win_sd::prelude::*;
use win_sd::token::{AccessToken, Privilege};
let sd = SecurityDescriptorBuilder::new()
.owner(Sid::local_system())
.allow(Sid::administrators(), AccessMask::FILE_ALL_ACCESS)
.allow(Sid::everyone(), AccessMask::FILE_GENERIC_READ)
.mandatory_label(IntegrityLevel::High, IntegrityPolicy::NO_WRITE_UP)
.build();
// A medium-integrity token trying to write to a high-integrity object
let token = AccessToken::new(Sid::administrators())
.with_integrity(IntegrityLevel::Medium);
let result = sd.check_access_full(
&token,
AccessMask::FILE_WRITE_DATA,
None, // no object type GUID
Some(&GenericMapping::file()),
None, // no attribute context
);
assert!(!result.granted); // denied by mandatory integrity check
}
NT ↔ POSIX translation
The nt_posix_translate example demonstrates bidirectional translation
between Windows Security Descriptors and POSIX ACLs, including two lossless
round-trip paths:
cargo run -p bac-examples --example nt_posix_translate
See NT-POSIX Translation for details.
AD schema access control
The ad_schema_access example parses the real Windows Server v1903 AD DS
schema (LDIF), evaluates SDDL security descriptors with win-sd,
translates them into LDAP ACIs with ldap-acis, and compares both models
through the acls-rs PermissionSet bridge:
cargo run -p bac-examples --example ad_schema_access
See AD Schema Access Control for details.
What to read next
- SIDs and Access Masks — Security Identifiers, the 32-bit permission bitmask, lattice algebra, and well-known constants.
- ACEs and Security Descriptors — ACE types, flags, entries, the WinAcl container, canonical ordering, and the SecurityDescriptor type with fluent construction.
- SDDL Parsing — the Security Descriptor Definition Language text format, alias tables, domain context, and round-trip guarantees.
- Access Checks — the Windows access-check algorithm, mandatory integrity, privileges, MAXIMUM_ALLOWED, callback ACE evaluation, Object ACE GUID filtering, and restricted tokens.
- Advanced Features — conditional expressions, binary serialization, ACL inheritance, generic rights mapping, resource attribute claims, and the access token model.
- acls-rs Bridge — configurable
PermissionMappingfor file/AD/registry semantics,_withvariants, GrantDenialPair with explicit denials, and cross-system permission comparison. - NT-POSIX Translation — bidirectional translation between Windows SDs and POSIX ACLs, lossy and lossless round-trip paths, and the fundamental impedance mismatch.