3.5.1 Impersonation Levels

Impersonation lets a server thread temporarily assume a client's identity, so that access control decisions on that thread evaluate the client's token instead of the server's.

The client controls how far its identity can travel by setting an impersonation level on the connection before it is established, and the server cannot escalate beyond the level the client chose. There is no API that bypasses that choice.

Anonymous. The server cannot identify the caller at all. The connection carries no identity information: both token inspection and impersonation yield a token whose user SID is Anonymous (S-1-5-7), which carries Everyone as an enabled group and does not carry Authenticated Users.

Identification. The server can identify the caller — read SIDs, query groups, inspect privileges — but cannot act as them. An Identification-level token is barred from AccessCheck against resources: a server thread impersonating one and attempting to open a file simply fails the check, with EACCES — the same refusal the kacs_access_check syscall reports for that token.

Impersonation. The server can act as the caller for all local operations, including ones that cross local IPC boundaries. If service A impersonates client B at this level and connects to local service C, C sees B's identity — identity cascades freely across local services. This is the default.

Delegation. Locally identical to Impersonation. The distinction activates at the network boundary, where a Delegation-level token carries authorization for the server to forward the client's identity to services on other machines through Kerberos. KACS enforces the level; authd is what acts on it.

The level is set by the client through a KACS syscall on the socket before connect(), and defaults to Impersonation.

3.5.1.1 The level is a ratchet #

Every token carries an impersonation level, and on every token it means the same thing: identity derived from this token may act at no more than this level. An impersonation token acts at its level. A primary token's level is the ceiling on everything the process carrying it can convey — what a peer captures at connect, what KACS_SO_PASS_TOKEN attaches, what KACS_IOC_DUPLICATE produces in either direction.

The level only ever goes down:

  • Socket capture and KACS_SCM_TOKEN attach store the lower of the socket's level and the source token's own;
  • DuplicateToken refuses a result above its source, whatever the types involved;
  • fork, exec, NEW_PROCESS_MIN, FilterToken and primary installation copy it unchanged.

The one way to a higher level is a fresh token from CreateToken, which takes SeCreateTokenPrivilege. authd mints logon tokens at Delegation and the bootstrap SYSTEM token is Delegation, so an identity starts at the top and each hop can only lower it.

This is what makes the client's choice hold across any number of hops and process boundaries. A client that connects at Impersonation is captured at Impersonation; a server that converts that token to a primary and launches a process with it (§3.2.4) produces a process capped at Impersonation; and nothing that process captures, conveys or duplicates can ever be Delegation — so authd, which reads the level to decide whether to forward the client's credentials, is never shown a Delegation flag the client did not grant.

Edit this page