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

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:

  1. Foundation typesSid (Security Identifier with string parsing and well-known constants), AccessMask (32-bit permission bitmask with lattice algebra), Guid (128-bit UUID for Object ACEs).

  2. ACE modelAceType (21 MS-DTYP ACE type variants), AceFlags (inheritance and audit flags), Ace (entry with optional GUIDs for Object ACEs, optional application_data for Callback ACEs, integrity level accessors, and structural validation).

  3. Security descriptorWinAcl (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).

  4. 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.

  5. 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.

  6. 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.

  • 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 PermissionMapping for file/AD/registry semantics, _with variants, 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.