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

SDDL Parsing and Generation

The Security Descriptor Definition Language (SDDL) is the standard text format for Windows security descriptors: O:ownerG:groupD:dacl_flags(ACEs)S:sacl_flags(ACEs).

Parsing

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

let sddl = "O:BAG:SYD:(D;;GA;;;AN)(A;;FA;;;BA)(A;;FR;;;WD)";
let sd = parse::<SddlParser>(sddl).unwrap();

assert_eq!(sd.owner(), Some(&Sid::administrators()));
assert_eq!(sd.group(), Some(&Sid::local_system()));
assert_eq!(sd.dacl().unwrap().ace_count(), 3);
}

Generating

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

let sd = SecurityDescriptorBuilder::new()
    .owner(Sid::administrators())
    .group(Sid::local_system())
    .allow(Sid::everyone(), AccessMask::FILE_GENERIC_READ)
    .build();

let sddl = generate::<SddlGenerator>(&sd).unwrap();
assert_eq!(sddl, "O:BAG:SYD:(A;;FR;;;WD)");
}

SID aliases

Well-known SIDs are represented by two-letter aliases:

AliasSIDName
WDS-1-1-0Everyone
BAS-1-5-32-544BUILTIN\Administrators
BUS-1-5-32-545BUILTIN\Users
SYS-1-5-18LOCAL SYSTEM
ANS-1-5-7ANONYMOUS LOGON
AUS-1-5-11Authenticated Users
COS-1-3-0Creator Owner
LWS-1-16-4096Low Integrity
MES-1-16-8192Medium Integrity
HIS-1-16-12288High Integrity
SIS-1-16-16384System Integrity

BUILTIN and other well-known SIDs

AliasSIDName
PSS-1-5-10Principal Self
EDS-1-5-9Enterprise DCs
OWS-1-3-4Owner Rights
BOS-1-5-32-551Backup Operators
SOS-1-5-32-549Server Operators
POS-1-5-32-550Print Operators
AOS-1-5-32-548Account Operators
PUS-1-5-32-547Power Users
RES-1-5-32-552Replicator
RUS-1-5-32-554Pre-W2K Compatible
ISS-1-5-32-568IIS_IUSRS
CYS-1-5-32-569Crypto Operators
ERS-1-5-32-573Event Log Readers
HAS-1-5-32-578Hyper-V Admins
AAS-1-5-32-579Access Control Assistance
ACS-1-15-2-1All Application Packages

Domain-relative aliases

Domain-relative aliases (DA, DU, DD, etc.) require a DomainContext:

#![allow(unused)]
fn main() {
use win_sd::{parse_with_domain, generate_with_domain, DomainContext, Sid};

let domain = DomainContext::new(
    Sid::from_authority(5, vec![21, 100, 200, 300]),
);

// DA resolves to S-1-5-21-100-200-300-512 (Domain Admins)
let sd = parse_with_domain("O:DAG:DUD:(A;;FA;;;DA)", &domain).unwrap();
let owner = sd.owner().unwrap();
assert_eq!(owner.rid(), Some(512));

// Generate uses aliases when a domain context is provided
let sddl = generate_with_domain(&sd, &domain).unwrap();
assert!(sddl.contains("DA"));
}
AliasRIDName
DA512Domain Admins
DU513Domain Users
DG514Domain Guests
DC515Domain Computers
DD516Domain Controllers
SA518Schema Admins
EA519Enterprise Admins
PA520Policy Admins
RO521Read-Only DCs

Rights aliases

Access mask values use two-letter codes:

CodeValueMeaning
GA0x10000000GENERIC_ALL
GR0x80000000GENERIC_READ
GW0x40000000GENERIC_WRITE
GX0x20000000GENERIC_EXECUTE
FA0x001F01FFFILE_ALL_ACCESS
FR0x00120089FILE_GENERIC_READ
FW0x00120116FILE_GENERIC_WRITE
FX0x001200A0FILE_GENERIC_EXECUTE
KA0x000F003FKEY_ALL_ACCESS
KR0x00020019KEY_READ
KW0x00020006KEY_WRITE
CC0x00000001CREATE_CHILD (AD)
DC0x00000002DELETE_CHILD (AD)
RP0x00000010READ_PROP (AD)
WP0x00000020WRITE_PROP (AD)
CR0x00000100CONTROL_ACCESS (AD)
RC0x00020000READ_CONTROL
SD0x00010000DELETE
WD0x00040000WRITE_DAC
WO0x00080000WRITE_OWNER
NW0x01NO_WRITE_UP (integrity)
NR0x02NO_READ_UP (integrity)
NX0x04NO_EXECUTE_UP (integrity)

ACL flags: P (protected), AR (auto-inherit request), AI (auto-inherited).

Hex literals are also accepted: 0x001F01FF.