3.2.2 Token Structure

Token fields fall into three mutability classes. Fixed fields are set at creation and never change — every security-critical identity field is fixed. Adjustable fields can be modified at runtime through the adjustment operations (§3.2.5). One-way fields can be set or tightened but never cleared or loosened.

3.2.2.1 Identity core (fixed) #

FieldTypeDescription
user_sidSIDThe token's primary identity.
user_deny_onlyboolWhen true, the user SID matches only deny ACEs, never allow ACEs. Set at creation by CreateToken or FilterToken. True whenever write_restricted is true.
groupsSID_AND_ATTRIBUTES[]Group memberships. The set of SIDs is fixed at creation; the per-group attribute flags are adjustable.
restricted_sidsSID_AND_ATTRIBUTES[]?Secondary SID list for restricted tokens, null on unrestricted ones. Set at creation by CreateToken or FilterToken. AccessCheck treats the list as presence-based: a restricting SID participates whenever it is present, and neither SE_GROUP_ENABLED nor SE_GROUP_USE_FOR_DENY_ONLY affects restricted-pass matching.
write_restrictedboolWhen true, the restricted SID check applies only to write access. Set at creation by CreateToken or FilterToken.

The logon SIDS-1-5-5-X-Y, tying the token to its LogonSession — is not stored as a token field at all. It is derived from the session on every read, and materialised once in groups carrying SE_GROUP_LOGON_ID, which is where AccessCheck finds it.

The group SID set is fixed at creation — adjustment never adds or removes a SID. Individual groups can be enabled or disabled by modifying SE_GROUP_ENABLED, within two limits: a mandatory group (SE_GROUP_MANDATORY) cannot be disabled, and a deny-only group (SE_GROUP_USE_FOR_DENY_ONLY) cannot be re-enabled.

A token holds at most 1024 group entries including the kernel-injected logon SID, so CreateToken accepts at most 1023 caller-supplied groups.

3.2.2.2 Token type (fixed) #

FieldTypeDescription
token_typeenumPrimary or Impersonation.
impersonation_levelenumAnonymous, Identification, Impersonation, or Delegation. Primary tokens always carry Anonymous.

3.2.2.3 Integrity (fixed) #

FieldTypeDescription
integrity_leveluintNumeric integrity level. Standard values are 0 (Untrusted), 4096 (Low), 8192 (Medium), 12288 (High), 16384 (System), but any unsigned integer is valid and is compared numerically against object labels.
mandatory_policyflagsNO_WRITE_UP (0x0001) and NEW_PROCESS_MIN (0x0002). Per-token MIC enforcement policy, set at creation.

mandatory_policy is immutable: a process cannot change its own MIC constraints at runtime, neither loosening nor tightening them. This is a deliberate departure from MS-DTYP, where the mandatory policy is runtime-modifiable — which reduces MIC to a constraint that stops only processes not actively trying to bypass it. Immutability is what makes MIC a real boundary here, and it is also what allows the impersonation integrity ceiling (§3.5) to be enforced unconditionally.

3.2.2.4 Privileges (adjustable) #

Each privilege on a token has four independent states.

Present — the privilege exists on the token. A present privilege can be removed permanently, but no privilege can be added after creation. Enabled — the privilege is currently active; only present privileges can be enabled or disabled. Enabled by default — the creation-time enabled state, which adjustment can restore. Used — the privilege has been exercised during this token's lifetime; monotonic, and never cleared once set.

The lifecycle runs: present and disabled, to enabled, to used, then optionally disabled, then optionally removed permanently. Removal clears the privilege from the present, enabled, and enabled-by-default states together.

The four states are encoded as four 64-bit bitmasks, one bit per defined privilege, which makes a privilege check constant-time and a multi-privilege operation atomic.

3.2.2.5 Elevation (one-way) #

FieldTypeDescription
elevation_typeenumDefault (non-elevated), Full (elevated), or Limited (filtered).

A token is created as Default. Only KACS_IOC_LINK_TOKENS sets Full or Limited, when a linked pair is established, and once set neither reverts to Default on that token object. The role is sticky: relinking can replace the partner but never converts Full to Limited or the reverse. DuplicateToken and FilterToken produce new token objects whose elevation_type starts again at Default, because a new token is not part of any linked pair.

Linked pairs are associated at the LogonSession level rather than stored on individual tokens; §3.2.6 describes the pairing mechanism.

3.2.2.6 Default object security (adjustable) #

FieldDescription
owner_sid_indexIndex into [user_sid, groups...] selecting the default owner SID for new objects: 0 is the user SID, 1..N are groups[0..N-1]. The referenced SID is the user SID or a group carrying SE_GROUP_OWNER.
primary_group_indexIndex into [user_sid, groups...] selecting the default primary group. The referenced SID is the user SID or any group SID on the token.
default_daclThe DACL applied to objects this token creates when no explicit descriptor is supplied.

Storing indices rather than SID copies keeps the owner and primary group consistent with the group array they name.

3.2.2.7 Metadata (fixed) #

FieldTypeDescription
token_idLUIDUnique identifier for this token instance.
token_guidUUID128-bit identifier for this token instance, generated by the kernel at creation and immutable. Used by KMES and other kernel-internal consumers for identity stamping and event correlation.
auth_idLUIDThe LogonSession LUID, linking the token to the authentication event that produced it.
sourceTOKEN_SOURCEWho minted the token: an 8-character name plus a LUID.
created_attimestampWhen the original token was minted by CreateToken. Copied unchanged by DuplicateToken, FilterToken, and NEW_PROCESS_MIN, so it tracks original minting rather than duplication.
expirationtimestampWhen the token becomes invalid; zero means no expiry. Not enforced by AccessCheck.
originLUIDThe originating LogonSession for derived tokens, such as S4U or network logon.

3.2.2.8 Mutation tracking (adjustable) #

FieldDescription
modified_idCounter incremented on any token adjustment.

Marking a privilege used is audit and accounting state rather than an access-decision input, so it stays monotonic but does not bump modified_id. Setting the elevation type is the one other mutation that leaves the counter alone.

The counter is intended as a cache invalidation key — a modified_id that has changed since a cached decision was taken means the decision is stale. Nothing currently reads it for that purpose: it is maintained on every adjustment and reported through the statistics query class, and no cache anywhere invalidates on it.

3.2.2.9 Interactivity scope (adjustable) #

FieldDescription
interactivity_scope0 for services, which have no interactive environment; 1 and above for interactive and remote user environments. Changing it requires SeTcbPrivilege.

3.2.2.10 Claims and security attributes (fixed) #

FieldTypeDescription
user_claimsCLAIM_ATTRIBUTES[]Name-value pairs from the user's directory object, fed into conditional ACE evaluation.
device_claimsCLAIM_ATTRIBUTES[]Name-value pairs from the machine's directory object.

3.2.2.11 LCS registry credentials (fixed) #

FieldTypeDescription
lcs_scope_guidsGUID[]Ordered private registry scope GUIDs used by LCS private hive routing. LCS checks the list in order before falling back to global hives.
lcs_private_layersstring[]Registry layer names visible to this token even when disabled globally, using LCS layer-name syntax and matching rules.

These are KACS-owned credential material belonging to LCS. They are fixed at creation and copied by duplication and filtering, and attaching them is authorized by the same trusted-minting gate as the rest of CreateToken — only a caller holding SeCreateTokenPrivilege can create a token carrying them.

3.2.2.12 Device identity (fixed) #

FieldTypeDescription
device_groupsSID_AND_ATTRIBUTES[]?The machine's group memberships, for compound identity.
restricted_device_groupsSID_AND_ATTRIBUTES[]?Filtered device groups for restricted tokens.

3.2.2.13 Confinement (fixed) #

FieldTypeDescription
confinement_sidSID?Places the token in a default-deny sandbox; null means unconfined. When set, AccessCheck switches to default-deny and access requires an explicit grant to this SID or to a SID present in confinement_capabilities.
confinement_capabilitiesSID_AND_ATTRIBUTES[]Declared access capabilities for a confined process, empty if none. The attributes field is carried for wire-format uniformity only: AccessCheck treats capability membership as presence-based and consults neither SE_GROUP_ENABLED nor SE_GROUP_USE_FOR_DENY_ONLY when matching confinement SIDs.
isolation_boundaryboolAdds namespace filtering on top of confinement, making objects outside the boundary invisible rather than merely denied. Requires confinement_sid. Settable at creation but not enforced.
confinement_exemptboolEscape hatch: confinement restrictions are not evaluated at all.

ALL_APPLICATION_PACKAGES participates only when it is present in confinement_capabilities. KACS never synthesises it, and equally never rejects an otherwise valid confined token merely because it is present — strict confinement is expressed by the caller omitting it. Deciding which capabilities a package token receives is authd's job and policy tooling's, not the kernel's.

3.2.2.14 Audit (fixed) #

FieldTypeDescription
audit_policyu32Per-token audit overrides as a bitmask, fixed at creation — no adjustment operation exists.
FlagValueDescription
OBJECT_ACCESS_SUCCESS0x0001Audit successful object access.
OBJECT_ACCESS_FAILURE0x0002Audit failed object access.
PRIVILEGE_USE_SUCCESS0x0004Audit successful privilege exercises: the privilege contributed requested bits that survive into the final granted result.
PRIVILEGE_USE_FAILURE0x0008Audit failed privilege exercises: the privilege contributed requested bits during evaluation, but they do not survive into the final result.

The policy is additive. It forces audit events that system-wide policy would not generate, and cannot suppress events that system-wide policy requires. It follows impersonation: when service A impersonates client B and B's token has a category enabled, operations during impersonation are audited under B's identity. The creation default is 0.

3.2.2.15 Credential projection (fixed) #

FieldDescription
projected_uidLinux UID for the user SID, precomputed by authd when the token is minted (PSPU §2); 65534 for the anonymous identity.
projected_gidLinux primary GID, precomputed the same way; 65534 for the anonymous identity.
projected_supplementary_gidsLinux supplementary GIDs, one per group SID, precomputed the same way.

authd computes these at token creation and they are stored on the token; KACS never resolves a SID-to-UID mapping at runtime. Projection reflects all groups regardless of enabled state, so adjusting groups does not trigger recalculation. §3.10 covers how the projection is used.

3.2.2.16 Token security (adjustable) #

FieldDescription
security_descriptorThe token's own SD, controlling who may query, adjust, duplicate, or impersonate it.

3.2.2.17 Internal #

FieldDescription
refcountReference count; the token is freed when the last reference drops. Not exposed to userspace.

Edit this page