3.3 The token-spec builder
Minting a token means assembling a 192-byte-header wire format with many optional sections. The builder is the ergonomic path — typed setters, no hand-packed offsets — and follows the standard sticky-error builder rules: the setters return void, the first error latches, you check peios_token_builder_error at the end, and you _free every builder.
typedef struct peios_token_builder peios_token_builder;
peios_token_builder *;
void ;
void ;
3.3.0.1 The index convention #
Three fields — the owner, the primary group, and the restrict/deny indices — refer to SIDs by index into the token's own SID list rather than by value. The convention is fixed:
Index 0 is the user SID. Indices 1..N are the 1st..Nth group you added with
peios_token_builder_add_group, in order.
So to make the second group the primary group, you set primary_group_index to 2. Do not add the logon SID yourself — the kernel injects it.
3.3.0.2 Core fields #
void ;
void ;
void ;
void ;
void ;
void ;
void ;
void ;
void ;
| Setter | Sets |
|---|---|
_user | The user SID (index 0). |
_add_group | Appends a group SID with its KACS_SE_GROUP_* attribute word (enabled, mandatory, deny-only, …). Call once per group, in the order you want them indexed. |
_privileges | The privilege bitmasks: present (which privileges the token holds) and enabled (which are on). Bits are KACS_SE_*_PRIVILEGE. |
_type | The token type (KACS_TOKEN_TYPE_* — primary or impersonation) and the impersonation level imp_level (KACS_IMLEVEL_*). Choose the level deliberately: it caps every identity derived from the token, including a primary. CreateToken accepts all four levels; Identification permits peers to identify the process without acting as it, and Anonymous hides its identity from peers. The process still acts as its own user. Older kernels reject primary levels below Impersonation. DuplicateToken retains its separate Impersonation floor for primary results. |
_integrity | The integrity level, as the RID of an S-1-16-<rid> label (see peios_integrity_level). |
_session | The logon session id the token references. |
_owner_index / _primary_group_index | Which SID (by index) is the default owner / primary group. |
_default_dacl | The default DACL applied to new objects the token creates (ACL bytes, e.g. from a peios_acl_builder). |
3.3.0.3 Advanced fields #
These cover the rest of the token-spec and can be left unset. They are marked [adv] in the header for a reason — most tokens need none of them.
void ;
void ;
void ;
void ;
void ;
void ;
void ;
void ;
void ;
| Setter | Sets |
|---|---|
_mandatory_policy | The mandatory-integrity policy bits governing how the integrity label is enforced. |
_projected_ids | The POSIX uid/gid this token projects into the Linux-compatibility layer. |
_expiration | An absolute expiry time after which the token is no longer valid. |
_source | The token's source: an 8-byte name and a source_id, recording who issued it (appears in audit). |
_audit_policy | Per-token audit policy bits. |
_add_restricted_sid | Appends a restricting SID (a write-restricted / restricted token intersects these against the normal SIDs). |
_add_device_group | Appends a device group SID (the device/machine side of a claim-aware token). |
_confinement | The confinement/AppContainer package SID that sandboxes the token. |
_supp_gids | Replaces the projected supplementary GIDs (pass NULL, 0 to clear). |
3.3.0.4 Token flags #
The four boolean token-spec flags are set together, so a designated initialiser reads clearly:
;
void ;
write_restricted— the token's restricting SIDs are checked only for write access.user_deny_only— the user SID is usable for deny ACEs but not to grant access.isolation_boundary— marks an isolation boundary for confinement.confinement_exempt— the token is exempt from confinement checks.
3.3.0.5 Claims #
A claim is a named, typed, multi-valued security attribute — the input to conditional (callback) ACEs. Claims come in user and device flavours; both share the same shape.
;
;
void ;
void ;
The value_type selects which member of each value carries the data:
value_type | Value member |
|---|---|
KACS_CLAIM_TYPE_INT64 / _UINT64 / _BOOLEAN | scalar (a boolean is 0 or 1). |
KACS_CLAIM_TYPE_STRING | bytes/len — a UTF-8 string (transcoded to UTF-16LE on the wire). |
KACS_CLAIM_TYPE_SID | bytes/len — a binary SID. |
KACS_CLAIM_TYPE_OCTET | bytes/len — an opaque blob. |
Each claim you add is round-tripped through the kernel's own claim parser before acceptance, so a malformed claim latches EINVAL on the builder immediately — you find out at build time, not at token-create time.
3.3.0.6 LCS registry credentials #
The final optional section grants the token registry-layer powers: which layer scopes it may resolve and which private layers it owns.
;
void ;
Setting it replaces any prior credentials; it is emitted as the last token-spec section. See <peios/registry.h> for what layers and scopes mean.
3.3.0.7 Finishing the builder #
ssize_t ;
int ;
int ;
peios_token_builder_bytesreturns the serialised length and, ifoutis non-NULL, writes a pointer into the builder (valid until the next reset/free) through it. Use this if you want the raw token-spec bytes.peios_token_builder_createdoes it in one step: serialise and mint, returning the new token fd. This is the usual call. It requiresSeCreateTokenPrivilege.peios_token_builder_errorreturns the latched errno, or0.
Errors: _bytes and _create first surface any latched builder error — EINVAL (malformed field, SID, claim, or index) or ENOMEM (allocation failed). A clean _create then adds the peios_token_create_raw set: EPERM (privilege missing), EINVAL (spec failed kernel validation), ENOMEM.
peios_token_builder *tb = ;
;
;
;
;
;
int tok = ; /* -1 on failure */
if
;