3.5 Adjust and transform

These change a token or derive a new one from it. Deriving calls return a new fd; in-place adjustments return 0 / -1.

3.5.0.1 Privileges and groups #

int peios_token_adjust_privileges(int fd, const struct kacs_priv_entry *entries,
                                  unsigned count, uint64_t *prev_enabled);
int peios_token_reset_privileges(int fd);
int peios_token_adjust_groups(int fd, const struct kacs_group_entry *entries,
                              unsigned count, uint64_t *prev_state);
int peios_token_reset_groups(int fd);
  • peios_token_adjust_privileges enables/disables the privileges named in entries (each a kacs_priv_entry); if prev_enabled is non-NULL it receives the prior enabled mask, so you can restore it later. peios_token_reset_privileges restores enabled := enabled_by_default. Errors: EACCES (handle lacks ADJUST_PRIVILEGES), EINVAL (empty or oversized batch, duplicate entry, enabling an absent privilege, unknown attribute bits), EFAULT (bad entries pointer).
  • peios_token_adjust_groups is the group analogue. prev_state, if non-NULL, points at a caller array of KACS_TOKEN_GROUP_MASK_WORDS uint64_t words that receives the prior enabled bitmask. peios_token_reset_groups restores the default group state. Errors: EACCES (handle lacks ADJUST_GROUPS), EINVAL (mandatory, deny-only, or logon-SID group targeted; duplicate or out-of-range index; empty batch), EFAULT (bad entries pointer).

3.5.0.2 Duplicate and restrict #

int peios_token_duplicate(int fd, uint32_t access, uint8_t type, uint8_t imp_level);

struct peios_token_restrict {
    uint64_t           privs_to_delete;
    const uint32_t    *deny_group_indices;   /* groups demoted to deny-only */
    unsigned           deny_count;
    const void *const *restrict_sids;        /* added restricting SIDs */
    const size_t      *restrict_sid_lens;
    unsigned           restrict_count;
    uint32_t           flags;                /* KACS_TOKEN_RESTRICT_WRITE_RESTRICTED */
};
int peios_token_restrict(int fd, const struct peios_token_restrict *spec);
  • peios_token_duplicate copies the token, returning a new fd with handle rights access, token type (KACS_TOKEN_TYPE_*), and impersonation level imp_level (KACS_IMLEVEL_*). This is how you turn a primary token into an impersonation token, or narrow a handle's rights. Errors: EACCES (handle lacks DUPLICATE, or the new token's SD denies access), EINVAL (unknown type/imp_level, raising an impersonation token's level, empty or unknown access bits), ENOMEM (allocation failed).
  • peios_token_restrict creates a filtered token — the sandboxing primitive. It can delete privileges (privs_to_delete), demote groups to deny-only (deny_group_indices, by index), add restricting SIDs (restrict_sids/restrict_sid_lens), and set KACS_TOKEN_RESTRICT_WRITE_RESTRICTED. The result is a strictly less-powerful token you can hand to less-trusted code. Errors: EACCES (handle lacks DUPLICATE), EINVAL (duplicate or out-of-range deny index, malformed restricting SID, unknown flags, NULL spec or arrays), ENOMEM (allocation failed).

3.5.0.3 Impersonation and installation #

int peios_token_install(int fd);
int peios_token_impersonate(int fd);
int peios_token_revert(void);
  • peios_token_install makes this primary token the calling process's primary token. Errors: EACCES (handle lacks ASSIGN_PRIMARY, or SeAssignPrimaryTokenPrivilege missing), EINVAL (not a primary token), EAGAIN (thread set changed mid-install — retry), ENOMEM (allocation failed).
  • peios_token_impersonate makes this impersonation token the calling thread's effective identity — subsequent access checks on that thread run as the impersonated identity. Errors: EACCES (handle lacks IMPERSONATE), EINVAL (not an impersonation token), EPERM (restricted→unrestricted same-user — the one hard deny), ENOMEM (allocation failed).
  • peios_token_revert undoes it: it clears the thread's impersonation token so checks run as the thread's real (primary) identity again. It takes no argument and is a no-op (reported as success) if the thread was not impersonating. This is the inverse of peios_token_impersonate — always pair them, ideally with revert in the cleanup path. Errors: none in normal operation.

The archetypal server flow: peios_token_open_peer the caller → peios_token_impersonate it → do the work as them → peios_token_revert.

3.5.0.4 Linked tokens and defaults #

int peios_token_link(int elevated_fd, int filtered_fd, uint64_t session_id);
int peios_token_get_linked(int fd);
int peios_token_adjust_default(int fd, const void *dacl, size_t len,
                               uint16_t owner_index, uint16_t group_index);
int peios_token_set_session_id(int fd, uint32_t session_id);
  • peios_token_link links an elevated + filtered primary-token pair in session_id — the UAC-style split-token model, where a filtered token is the everyday identity and its elevated linked token is available on demand. peios_token_get_linked opens the linked token of fd, returning a new fd. Errors (_link): EACCES (SeTcbPrivilege missing, or either handle lacks DUPLICATE), EINVAL (self-link, role/session/user-SID mismatch, not primary tokens, unknown session_id, or an fd that is not a token fd), EBADF (invalid fd). Errors (_get_linked): EACCES (handle lacks QUERY), ENOENT (not part of a linked pair, or the pair was destroyed), ENOMEM (allocation failed).
  • peios_token_adjust_default replaces the token's default DACL and/or owner/primary-group indices. dacl == NULL leaves the DACL unchanged (and ignores len); dacl != NULL with len == 0 clears it; an index of 0xFFFF leaves that index unchanged. Errors: EACCES (handle lacks ADJUST_DEFAULT), EINVAL (out-of-range index; malformed or oversized DACL), EFAULT (bad DACL pointer).
  • peios_token_set_session_id sets the token's session id (requires SeTcbPrivilege). Errors: EACCES (handle lacks ADJUST_SESSIONID, or SeTcbPrivilege missing).

Edit this page