SIDs and Access Masks
Security Identifiers (SIDs)
A SID uniquely identifies a security principal — a user, group, computer, or service. It consists of a revision (always 1), a 6-byte identifier authority, and up to 15 sub-authority values.
#![allow(unused)]
fn main() {
use win_sd::Sid;
// Parse from standard string format
let sid: Sid = "S-1-5-32-544".parse().unwrap();
assert_eq!(sid, Sid::administrators());
assert_eq!(sid.to_string(), "S-1-5-32-544");
// Well-known SID constructors
let _ = Sid::everyone(); // S-1-1-0
let _ = Sid::local_system(); // S-1-5-18
let _ = Sid::authenticated_users();// S-1-5-11
let _ = Sid::anonymous(); // S-1-5-7
let _ = Sid::creator_owner(); // S-1-3-0
// Domain SIDs
let domain = Sid::from_authority(5, vec![21, 100, 200, 300]);
let alice = Sid::from_authority(5, vec![21, 100, 200, 300, 1001]);
assert_eq!(alice.rid(), Some(1001));
assert_eq!(alice.domain(), domain);
}
SIDs implement Hash, Eq, Ord, and optional Serialize/Deserialize,
making them suitable as HashMap keys.
ACCESS_MASK
The AccessMask is a 32-bit bitmask encoding the permissions requested or
granted. Bits are divided into regions:
| Bits | Category | Examples |
|---|---|---|
| 0–15 | Object-specific | FILE_READ_DATA, FILE_WRITE_DATA, KEY_QUERY_VALUE |
| 16–20 | Standard rights | DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER, SYNCHRONIZE |
| 24–25 | Special | ACCESS_SYSTEM_SECURITY, MAXIMUM_ALLOWED |
| 28–31 | Generic | GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE, GENERIC_ALL |
#![allow(unused)]
fn main() {
use win_sd::AccessMask;
use acls_rs::algebra::JoinSemilattice;
// Named constants
let read = AccessMask::FILE_GENERIC_READ;
let write = AccessMask::FILE_GENERIC_WRITE;
// Lattice algebra: join (OR) is the least upper bound
let combined = read.join(write);
assert!(combined.contains(read));
assert!(combined.contains(write));
// Subset partial order
assert!(read < AccessMask::FILE_ALL_ACCESS);
// Bitwise operators
let rw = AccessMask::FILE_READ_DATA | AccessMask::FILE_WRITE_DATA;
assert_eq!(rw & AccessMask::FILE_READ_DATA, AccessMask::FILE_READ_DATA);
}
File-specific composites
| Constant | Bits |
|---|---|
FILE_GENERIC_READ | FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES | READ_CONTROL | SYNCHRONIZE |
FILE_GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES | READ_CONTROL | SYNCHRONIZE |
FILE_GENERIC_EXECUTE | FILE_EXECUTE | FILE_READ_ATTRIBUTES | READ_CONTROL | SYNCHRONIZE |
FILE_ALL_ACCESS | All standard + file-specific rights (0x001F01FF) |
Registry key rights
The crate also defines registry key constants (KEY_QUERY_VALUE,
KEY_SET_VALUE, KEY_READ, KEY_WRITE, KEY_ALL_ACCESS) and Active
Directory rights (ADS_RIGHT_DS_READ_PROP, ADS_RIGHT_DS_WRITE_PROP, etc.)
for use with Object ACEs.
Generic rights mapping
Generic rights (bits 28–31) are abstract — they must be mapped to
object-specific bits before use in access checks. GenericMapping provides
this:
#![allow(unused)]
fn main() {
use win_sd::{AccessMask, GenericMapping};
let mapping = GenericMapping::file();
let expanded = mapping.map_mask(AccessMask::GENERIC_READ);
assert_eq!(expanded, AccessMask::FILE_GENERIC_READ);
}
Pre-defined mappings: file(), directory(), registry_key().