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, for an impersonation token, the impersonation level imp_level (KACS_IMLEVEL_*). |
_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
;