Security Identifiers

SID's are documented in nt/public/sdk/inc/ntseapi.h.

A SID is a 2 byte header giving Revision Number and subauthority count, followed by a 6 byte top-level authority, followed by a variable number of 4 byte subauthorities. In practice a subauthority often claims more than 4 bytes. Hence the subauthority count does not always agree with what logically might be the number of subauthorities. The subauthority count is always simply the number of DWORD's following the top level authority. When a SID is stored in the registry, the DWORD's making up a subauthority are stored little-endian, whereas the top level authority is stored as a byte array, that is, big-endian.

SID's have a canonical external representation formated as

	strcpy( s, "S-%d-%d" ) ;
	for ( i=0; i<number_sub_auth; i++ ) strcat( s, "-%d" ) ;
	printf(	s, revision_level, top_level_authority, 
			subauthority, subauthority, ... ) ;

A typical user SID is 28 bytes:

Field Bytes Value Notes
Revision 1 0x01
Count 1 5 3 subauthorities in 5 DWORD's.
Top Level Auth. 6 0x05 SECURITY_NT_AUTHORITY
Subauth. 4 0x15 SECURITY_NT_NON_UNIQUE
Subauth. 12 - Machine identifier
Subauth. 4 - User identifier
Machine and domain SID simply omit the User identifier subauthority. Perhaps there is no such thing as a domain SiD. Group SiD's are identical to user SiD's, there is no distinction.

SID's for local groups, also known as builtin, are 12 bytes:

Field Bytes Value Notes
Revision 1 0x01
Count 1 2 2 subauthorities in 2 DWORD's.
Top Level Auth. 6 0x05 SECURITY_NT_AUTHORITY
Subauth. 4 0x20 SECURITY_BUILTIN_DOMAIN_RID
Subauth. 4 - Relative identifier

Guess The subauthories are also called RID's. Hence we can speak of a machine RID, the 6 byte unique identifier of a machine, or a domain RID. A domain takes as it's RID the RID of a machine. However, it must be that even if this domain moves to another PDC, user's continue to use the orignal RID. This way, it is easy to decide if two users are from the same or different domains.

Likewise, it is easy to test if a user can be part of a global group. A global group is a domain member, and all its consitutents must be members of the same domain. The members of a group as well as the group itself must share a common RID as the second subauthority. However, since it is not obvious if a RID is a user or a group, the DC must check this before giving out the token, or perhaps, the administration tools prevent entering such a combination into the SAM.

Question: Another question: what stops SID from getting ambiguous with their subauthorities? From the generic structure, we know only the number of DWORD's following, not how to parse those for subauthority consumption.

For instance, the end-marker is the only distinguishing feature of the machine SID from a user SID. That is, user zero isn't reserved for the name. So the end-marker is part of a SID.

Example

See HKLM/SECURITY/Policy/Domains for a subkey identifying the machine's domain. The key name is the canonical external representation of the domain SID. In my case
	S-1-5-21-1179599015-1994013950-622671684. 
Convering to hex,
	S-1-0000 0000 0005-0000 0015-464F 40A7-76DA 3CFE-251D 3744.
The "Sid" subkey contains the actual SID,
01 04 00 00 00 00 00 05
15 00 00 00 A7 40 4F 46
FE 3C DA 76 44 37 1D 25
Note that subauthorities are stored as little-endian DWORDS but the top level authority is stored big-endian.

The builtin Administrator's group is

	S-1-5-32-544
The "Sid" subkey of HKLM/SECURITY/Policy/Accounts/S-1-5-32-544 gives the hex form:
01 02 00 00 00 00 00 05
20 00 00 00 20 02 00 00

The world SID is represented in the "Sid" subkey of Acoutns/S-1-1-0:

01 01 00 00 00 00 00 01
00 00 00 00