Geoff Chappell, Software Analyst
The SID structure is the fixed-size header that begins a variable-size Security Identifier (SID). Each SID is a path in a security namespace of authorities and subauthorities which together identify a trustee in the security model. A trustee can be a single user, a group of users, a computer, a program, or something much more abstract.
What a program can get from Windows depends on who runs the program or on whose behalf it asks. The who is most generally a trustee in the security model. Any resource to which access is selective must be associated somehow with SIDs for trustees who do or don’t have this or that access. Any request for access must come with a SID for the trustee that is to be granted the access—and with some means for testing that such a SID is in some sense genuine. SIDs, as the identifiers of trustees, are therefore abundant both in memory at run-time and in persistent storage. Moreover, they exist both in a compact binary form and in a more human-readable expression.
SIDS are directly or indirectly among the inputs to many API functions, especially those of the Security Reference Monitor. A large family of Run Time Library (RTL) functions exists for managing SIDs, with implementations both in kernel and user modes.
The SID structure and its continuation as a SID are documented but more than usually in the abstract. The SID is defined in NTIFS.H from the Windows Driver Kit (WDK) and in WINNT.H from the Software Development Kit (SDK), but this layout of its binary form seems intended to be treated as opaque by almost all Windows software. See in particular that although a PSID type is defined for use whenever software has the address of a SID, it evaluates not as a pointer to a SID but as a pointer to void.
SIDs must have equal meaning to all operating systems that might use them. The SID is therefore the same for both 32-bit and 64-bit Windows. It is formally 0x0C bytes but only because it ends with a variable-size array that has one element as a placeholder. The SID is as well regarded as an 8-byte header that introduces the variable-size SubAuthority array. The true element count for this array is SubAuthorityCount.
ULONG SubAuthority [ANYSIZE_ARRAY];
Through a quarter century of use, the only Revision known for any SID is 1, for which Microsoft defines SID_REVISION. Despite its definition as a whole byte, RTL functions that check validity require 1 only in the low four bits.
The six-byte SID_IDENTIFIER_AUTHORITY has just the one member:
UCHAR Value ;
RTL functions for converting between binary and string forms treat the IdentifierAuthority as a 48-bit integer whose bytes are ordered from most significant to least.
Interpretation of the SubAuthority array varies with the authority. Each element of the array is known as a Relative Identifier (RID). An authority or subauthority defines some number of subsequent RIDs for the next subauthority. RTL functions that check validity impose a maximum of 15 elements in the array. Microsoft defines this limit symbolically as SID_MAX_SUB_AUTHORITIES.
Though the use of SIDs in an access check is ultimately the work of the Security Reference Monitor in the kernel, the work of creating and managing SIDs is needed throughout Windows, both in kernel and user modes. The substantial interface is in the Run Time Library. Its functions are exported from either or both of the kernel and NTDLL, typically in implementations that are close enough that they plausibly are compiled from the same source code. In user mode, these low-level functions are the basis of higher-level functions that are exported by ADVAPI32.DLL.
TO BE CONTINUED