ReactOS  0.4.15-dev-3748-g6a496c3
token.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <ntlsa.h>
Include dependency graph for token.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static NTSTATUS SepCreateTokenLock (_Inout_ PTOKEN Token)
 Creates a lock for the token. More...
 
static VOID SepDeleteTokenLock (_Inout_ PTOKEN Token)
 Deletes a lock of a token. More...
 
static BOOLEAN SepCompareSidAndAttributesFromTokens (_In_ PSID_AND_ATTRIBUTES SidArrayToken1, _In_ ULONG CountSidArray1, _In_ PSID_AND_ATTRIBUTES SidArrayToken2, _In_ ULONG CountSidArray2)
 Compares the elements of SID arrays provided by tokens. The elements that are being compared for equality are the SIDs and their attributes. More...
 
static BOOLEAN SepComparePrivilegeAndAttributesFromTokens (_In_ PLUID_AND_ATTRIBUTES PrivArrayToken1, _In_ ULONG CountPrivArray1, _In_ PLUID_AND_ATTRIBUTES PrivArrayToken2, _In_ ULONG CountPrivArray2)
 Compares the elements of privilege arrays provided by tokens. The elements that are being compared for equality are the privileges and their attributes. More...
 
static NTSTATUS SepCompareTokens (_In_ PTOKEN FirstToken, _In_ PTOKEN SecondToken, _Out_ PBOOLEAN Equal)
 Compares tokens if they're equal based on all the following properties. If all of the said conditions are met then the tokens are deemed as equal. More...
 
static NTSTATUS SepImpersonateAnonymousToken (_In_ PETHREAD Thread, _In_ KPROCESSOR_MODE PreviousMode)
 Private function that impersonates the system's anonymous logon token. The major bulk of the impersonation procedure is done here. More...
 
static VOID SepUpdateSinglePrivilegeFlagToken (_Inout_ PTOKEN Token, _In_ ULONG Index)
 Updates the token's flags based upon the privilege that the token has been granted. The flag can either be taken out or given to the token if the attributes of the specified privilege is enabled or not. More...
 
static VOID SepUpdatePrivilegeFlagsToken (_Inout_ PTOKEN Token)
 Updates the token's flags based upon the privilege that the token has been granted. The function uses the private helper, SepUpdateSinglePrivilegeFlagToken, in order to update the flags of a token. More...
 
static VOID SepRemovePrivilegeToken (_Inout_ PTOKEN Token, _In_ ULONG Index)
 Removes a privilege from the token. More...
 
static VOID SepRemoveUserGroupToken (_Inout_ PTOKEN Token, _In_ ULONG Index)
 Removes a group from the token. More...
 
VOID NTAPI SepFreeProxyData (_Inout_ PVOID ProxyData)
 Frees (de-allocates) the proxy data memory block of a token. More...
 
NTSTATUS NTAPI SepCopyProxyData (_Out_ PVOID *Dest, _In_ PVOID Src)
 Copies the proxy data from the source into the destination of a token. More...
 
NTSTATUS NTAPI SeExchangePrimaryToken (_In_ PEPROCESS Process, _In_ PACCESS_TOKEN NewAccessToken, _Out_ PACCESS_TOKEN *OldAccessToken)
 Replaces the old access token of a process (pointed by the EPROCESS kernel structure) with a new access token. The new access token must be a primary token for use. More...
 
VOID NTAPI SeDeassignPrimaryToken (_Inout_ PEPROCESS Process)
 Removes the primary token of a process. More...
 
static ULONG RtlLengthSidAndAttributes (_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src)
 Computes the length size of a SID. More...
 
static NTSTATUS SepFindPrimaryGroupAndDefaultOwner (_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
 Finds the primary group and default owner entity based on the submitted primary group instance and an access token. More...
 
NTSTATUS NTAPI SepDuplicateToken (_In_ PTOKEN Token, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL Level, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *NewAccessToken)
 Duplicates an access token, from an existing valid token. More...
 
NTSTATUS NTAPI SeSubProcessToken (_In_ PTOKEN ParentToken, _Out_ PTOKEN *Token, _In_ BOOLEAN InUse, _In_ ULONG SessionId)
 Subtracts a token in exchange of duplicating a new one. More...
 
NTSTATUS NTAPI SeIsTokenChild (_In_ PTOKEN Token, _Out_ PBOOLEAN IsChild)
 Checks if the token is a child of the other token of the current process that the calling thread is invoking this function. More...
 
NTSTATUS NTAPI SeIsTokenSibling (_In_ PTOKEN Token, _Out_ PBOOLEAN IsSibling)
 Checks if the token is a sibling of the other token of the current process that the calling thread is invoking this function. More...
 
NTSTATUS NTAPI SeCopyClientToken (_In_ PACCESS_TOKEN Token, _In_ SECURITY_IMPERSONATION_LEVEL Level, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PACCESS_TOKEN *NewToken)
 Copies an existing access token (technically duplicating a new one). More...
 
VOID NTAPI SepDeleteToken (_In_ PVOID ObjectBody)
 Internal function that deals with access token object destruction and deletion. The function is used solely by the object manager mechanism that handles the life management of a token object. More...
 
VOID NTAPI SepInitializeTokenImplementation (VOID)
 Internal function that initializes critical kernel data for access token implementation in SRM. More...
 
VOID NTAPI SeAssignPrimaryToken (_In_ PEPROCESS Process, _In_ PTOKEN Token)
 Assigns a primary access token to a given process. More...
 
NTSTATUS NTAPI SepCreateToken (_Out_ PHANDLE TokenHandle, _In_ KPROCESSOR_MODE PreviousMode, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PSID_AND_ATTRIBUTES User, _In_ ULONG GroupCount, _In_ PSID_AND_ATTRIBUTES Groups, _In_ ULONG GroupsLength, _In_ ULONG PrivilegeCount, _In_ PLUID_AND_ATTRIBUTES Privileges, _In_opt_ PSID Owner, _In_ PSID PrimaryGroup, _In_opt_ PACL DefaultDacl, _In_ PTOKEN_SOURCE TokenSource, _In_ BOOLEAN SystemToken)
 Internal function responsible for access token object creation in the kernel. A fully created token objected is inserted into the token handle, thus the handle becoming a valid handle to an access token object and ready for use. More...
 
static NTSTATUS SepPerformTokenFiltering (_In_ PTOKEN Token, _In_opt_ PLUID_AND_ATTRIBUTES PrivilegesToBeDeleted, _In_opt_ PSID_AND_ATTRIBUTES SidsToBeDisabled, _In_opt_ PSID_AND_ATTRIBUTES RestrictedSidsIntoToken, _When_(PrivilegesToBeDeleted !=NULL, _In_) ULONG PrivilegesCount, _When_(SidsToBeDisabled !=NULL, _In_) ULONG RegularGroupsSidCount, _When_(RestrictedSidsIntoToken !=NULL, _In_) ULONG RestrictedSidsCount, _In_ ULONG PrivilegeFlags, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *FilteredToken)
 Private helper function responsible for creating a restricted access token, that is, a filtered token from privileges and groups and with restricted SIDs added into the token on demand by the caller. More...
 
PTOKEN NTAPI SepCreateSystemProcessToken (VOID)
 Creates the system process token. More...
 
PTOKEN SepCreateSystemAnonymousLogonToken (VOID)
 Creates the anonymous logon token for the system. The difference between this token and the other one is the inclusion of everyone SID group (being SeWorldSid). The other token lacks such group. More...
 
PTOKEN SepCreateSystemAnonymousLogonTokenNoEveryone (VOID)
 Creates the anonymous logon token for the system. This kind of token doesn't include the everyone SID group (being SeWorldSid). More...
 
NTSTATUS NTAPI SeFilterToken (_In_ PACCESS_TOKEN ExistingToken, _In_ ULONG Flags, _In_opt_ PTOKEN_GROUPS SidsToDisable, _In_opt_ PTOKEN_PRIVILEGES PrivilegesToDelete, _In_opt_ PTOKEN_GROUPS RestrictedSids, _Out_ PACCESS_TOKEN *FilteredToken)
 Filters an access token from an existing token, making it more restricted than the previous one. More...
 
NTSTATUS NTAPI SeQueryInformationToken (_In_ PACCESS_TOKEN AccessToken, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Outptr_result_buffer_(_Inexpressible_(token-dependent)) PVOID *TokenInformation)
 Queries information details about the given token to the call. The difference between NtQueryInformationToken and this routine is that the system call has user mode buffer data probing and additional protection checks whereas this routine doesn't have any of these. The routine is used exclusively in kernel mode. More...
 
NTSTATUS NTAPI SeQuerySessionIdToken (_In_ PACCESS_TOKEN Token, _Out_ PULONG pSessionId)
 Queries the session ID of an access token. More...
 
NTSTATUS NTAPI SeQueryAuthenticationIdToken (_In_ PACCESS_TOKEN Token, _Out_ PLUID LogonId)
 Queries the authentication ID of an access token. More...
 
SECURITY_IMPERSONATION_LEVEL NTAPI SeTokenImpersonationLevel (_In_ PACCESS_TOKEN Token)
 Gathers the security impersonation level of an access token. More...
 
TOKEN_TYPE NTAPI SeTokenType (_In_ PACCESS_TOKEN Token)
 Gathers the token type of an access token. A token ca be either a primary token or impersonation token. More...
 
BOOLEAN NTAPI SeTokenIsAdmin (_In_ PACCESS_TOKEN Token)
 Determines if a token is either an admin token or not. Such condition is checked based upon TOKEN_HAS_ADMIN_GROUP flag, which means if the respective access token belongs to an administrator group or not. More...
 
BOOLEAN NTAPI SeTokenIsRestricted (_In_ PACCESS_TOKEN Token)
 Determines if a token is restricted or not, based upon the token flags. More...
 
BOOLEAN NTAPI SeTokenIsWriteRestricted (_In_ PACCESS_TOKEN Token)
 Determines if a token is write restricted, that is, nobody can write anything to it. More...
 
BOOLEAN NTAPI SeTokenCanImpersonate (_In_ PTOKEN ProcessToken, _In_ PTOKEN TokenToImpersonate, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
 Ensures that client impersonation can occur by checking if the token we're going to assign as the impersonation token can be actually impersonated in the first place. The routine is used primarily by PsImpersonateClient. More...
 
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken (_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength, _Out_ PULONG ReturnLength)
 Queries a specific type of information in regard of an access token based upon the information class. The calling thread must have specific access rights in order to obtain specific information about the token. More...
 
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtSetInformationToken (_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _In_reads_bytes_(TokenInformationLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength)
 Sets (modifies) some specific information in regard of an access token. The calling thread must have specific access rights in order to modify token's information data. More...
 
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtDuplicateToken (_In_ HANDLE ExistingTokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _Out_ PHANDLE NewTokenHandle)
 Duplicates a token. More...
 
static NTSTATUS SepAdjustGroups (_In_ PTOKEN Token, _In_opt_ PSID_AND_ATTRIBUTES NewState, _In_ ULONG NewStateCount, _In_ BOOLEAN ApplyChanges, _In_ BOOLEAN ResetToDefaultStates, _Out_ PBOOLEAN ChangesMade, _Out_opt_ PTOKEN_GROUPS PreviousGroupsState, _Out_ PULONG ChangedGroups)
 Private routine that iterates over the groups of an access token to be adjusted as per on request by the caller, where a group can be enabled or disabled. More...
 
NTSTATUS NTAPI NtAdjustGroupsToken (_In_ HANDLE TokenHandle, _In_ BOOLEAN ResetToDefault, _In_ PTOKEN_GROUPS NewState, _In_ ULONG BufferLength, _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_GROUPS PreviousState, _When_(PreviousState !=NULL, _Out_) PULONG ReturnLength)
 Changes the list of groups by enabling or disabling them in an access token. Unlike NtAdjustPrivilegesToken, this API routine does not remove groups. More...
 
static NTSTATUS SepAdjustPrivileges (_Inout_ PTOKEN Token, _In_ BOOLEAN DisableAllPrivileges, _In_opt_ PLUID_AND_ATTRIBUTES NewState, _In_ ULONG NewStateCount, _Out_opt_ PTOKEN_PRIVILEGES PreviousState, _In_ BOOLEAN ApplyChanges, _Out_ PULONG ChangedPrivileges, _Out_ PBOOLEAN ChangesMade)
 Removes a certain amount of privileges of a token based upon the request by the caller. More...
 
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtAdjustPrivilegesToken (_In_ HANDLE TokenHandle, _In_ BOOLEAN DisableAllPrivileges, _In_opt_ PTOKEN_PRIVILEGES NewState, _In_ ULONG BufferLength, _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_PRIVILEGES PreviousState, _When_(PreviousState!=NULL, _Out_) PULONG ReturnLength)
 Removes a certain amount of privileges of a token based upon the request by the caller. More...
 
__kernel_entry NTSTATUS NTAPI NtCreateToken (_Out_ PHANDLE TokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PTOKEN_USER TokenUser, _In_ PTOKEN_GROUPS TokenGroups, _In_ PTOKEN_PRIVILEGES TokenPrivileges, _In_opt_ PTOKEN_OWNER TokenOwner, _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl, _In_ PTOKEN_SOURCE TokenSource)
 Creates an access token. More...
 
NTSTATUS NTAPI NtOpenThreadTokenEx (_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _In_ ULONG HandleAttributes, _Out_ PHANDLE TokenHandle)
 Opens a token that is tied to a thread handle. More...
 
NTSTATUS NTAPI NtOpenThreadToken (_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _Out_ PHANDLE TokenHandle)
 Opens a token that is tied to a thread handle. More...
 
NTSTATUS NTAPI NtCompareTokens (_In_ HANDLE FirstTokenHandle, _In_ HANDLE SecondTokenHandle, _Out_ PBOOLEAN Equal)
 Compares tokens if they're equal or not. More...
 
NTSTATUS NTAPI NtFilterToken (_In_ HANDLE ExistingTokenHandle, _In_ ULONG Flags, _In_opt_ PTOKEN_GROUPS SidsToDisable, _In_opt_ PTOKEN_PRIVILEGES PrivilegesToDelete, _In_opt_ PTOKEN_GROUPS RestrictedSids, _Out_ PHANDLE NewTokenHandle)
 Creates an access token in a restricted form from the original existing token, that is, such action is called filtering. More...
 
NTSTATUS NTAPI NtImpersonateAnonymousToken (_In_ HANDLE ThreadHandle)
 Allows the calling thread to impersonate the system's anonymous logon token. More...
 

Variables

POBJECT_TYPE SeTokenObjectType = NULL
 
TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}}
 
LUID SeSystemAuthenticationId = SYSTEM_LUID
 
LUID SeAnonymousAuthenticationId = ANONYMOUS_LOGON_LUID
 
static GENERIC_MAPPING SepTokenMapping
 
static const INFORMATION_CLASS_INFO SeTokenInformationClass []
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file token.c.

Function Documentation

◆ NtAdjustGroupsToken()

NTSTATUS NTAPI NtAdjustGroupsToken ( _In_ HANDLE  TokenHandle,
_In_ BOOLEAN  ResetToDefault,
_In_ PTOKEN_GROUPS  NewState,
_In_ ULONG  BufferLength,
_Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_GROUPS  PreviousState,
_When_(PreviousState !=NULL, _Out_) PULONG  ReturnLength 
)

Changes the list of groups by enabling or disabling them in an access token. Unlike NtAdjustPrivilegesToken, this API routine does not remove groups.

Parameters
[in]TokenHandleToken handle where the list of groups SID are to be adjusted. The access token must have TOKEN_ADJUST_GROUPS access right in order to change the groups in a token. The token must also have TOKEN_QUERY access right if the caller requests the previous states of groups list, that is, PreviousState is not NULL.
[in]ResetToDefaultIf set to TRUE, the function resets the list of groups to default enabled and disabled states. NewState is ignored in this case. Otherwise if the parameter is set to FALSE, the function expects a new list of groups from NewState to be adjusted within the token.
[in]NewStateA new list of groups SID that the function will use it accordingly to modify the current list of groups SID of a token.
[in]BufferLengthThe length size of the buffer that is pointed by the NewState parameter argument, in bytes.
[out]PreviousStateIf specified, the function will return to the caller the old list of groups SID. If this parameter is NULL, ReturnLength must also be NULL.
[out]ReturnLengthIf specified, the function will return the total size length of the old list of groups SIDs, in bytes.
Returns
STATUS_SUCCESS is returned if the function has successfully adjusted the token's groups. STATUS_INVALID_PARAMETER is returned if the caller has submitted one or more invalid parameters, that is, the caller didn't want to reset the groups to default state but no NewState argument list has been provided. STATUS_BUFFER_TOO_SMALL is returned if the buffer length given by the caller is smaller than the required length size. A failure NTSTATUS code is returned otherwise.

Definition at line 5276 of file token.c.

5284 {
5285  PTOKEN Token;
5286  NTSTATUS Status;
5288  ULONG ChangeCount, RequiredLength;
5289  ULONG CapturedCount = 0;
5290  ULONG CapturedLength = 0;
5291  ULONG NewStateSize = 0;
5292  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
5293  BOOLEAN ChangesMade = FALSE;
5294  BOOLEAN LockAndReferenceAcquired = FALSE;
5295 
5296  PAGED_CODE();
5297 
5298  /*
5299  * If the caller doesn't want to reset the groups of an
5300  * access token to default states then at least we must
5301  * expect a list of groups to be adjusted based on NewState
5302  * parameter. Otherwise bail out because the caller has
5303  * no idea what they're doing.
5304  */
5305  if (!ResetToDefault && !NewState)
5306  {
5307  DPRINT1("NtAdjustGroupsToken(): The caller hasn't provided any list of groups to adjust!\n");
5308  return STATUS_INVALID_PARAMETER;
5309  }
5310 
5312 
5313  if (PreviousMode != KernelMode)
5314  {
5315  _SEH2_TRY
5316  {
5317  /* Probe NewState */
5318  if (!ResetToDefault)
5319  {
5320  /* Probe the header */
5321  ProbeForRead(NewState, sizeof(*NewState), sizeof(ULONG));
5322 
5323  CapturedCount = NewState->GroupCount;
5324  NewStateSize = FIELD_OFFSET(TOKEN_GROUPS, Groups[CapturedCount]);
5325 
5326  ProbeForRead(NewState, NewStateSize, sizeof(ULONG));
5327  }
5328 
5329  if (PreviousState != NULL)
5330  {
5332  ProbeForWrite(ReturnLength, sizeof(*ReturnLength), sizeof(ULONG));
5333  }
5334  }
5336  {
5337  /* Return the exception code */
5339  }
5340  _SEH2_END;
5341  }
5342  else
5343  {
5344  /*
5345  * We're calling directly from the kernel, just retrieve
5346  * the number count of captured groups outright.
5347  */
5348  if (!ResetToDefault)
5349  {
5350  CapturedCount = NewState->GroupCount;
5351  }
5352  }
5353 
5354  /* Time to capture the NewState list */
5355  if (!ResetToDefault)
5356  {
5357  _SEH2_TRY
5358  {
5359  Status = SeCaptureSidAndAttributesArray(NewState->Groups,
5360  CapturedCount,
5361  PreviousMode,
5362  NULL,
5363  0,
5364  PagedPool,
5365  TRUE,
5366  &CapturedGroups,
5367  &CapturedLength);
5368  }
5370  {
5372  }
5373  _SEH2_END;
5374 
5375  if (!NT_SUCCESS(Status))
5376  {
5377  DPRINT1("NtAdjustGroupsToken(): Failed to capture the NewState list of groups (Status 0x%lx)\n", Status);
5378  return Status;
5379  }
5380  }
5381 
5382  /* Time to reference the token */
5386  PreviousMode,
5387  (PVOID*)&Token,
5388  NULL);
5389  if (!NT_SUCCESS(Status))
5390  {
5391  /* We couldn't reference the access token, bail out */
5392  DPRINT1("NtAdjustGroupsToken(): Failed to reference the token (Status 0x%lx)\n", Status);
5393 
5394  if (CapturedGroups != NULL)
5395  {
5396  SeReleaseSidAndAttributesArray(CapturedGroups,
5397  PreviousMode,
5398  TRUE);
5399  }
5400 
5401  goto Quit;
5402  }
5403 
5404  /* Lock the token */
5406  LockAndReferenceAcquired = TRUE;
5407 
5408  /* Count the number of groups to be changed */
5410  CapturedGroups,
5411  CapturedCount,
5412  FALSE,
5413  ResetToDefault,
5414  &ChangesMade,
5415  NULL,
5416  &ChangeCount);
5417 
5418  /* Does the caller want the previous state of groups? */
5419  if (PreviousState != NULL)
5420  {
5421  /* Calculate the required length */
5423 
5424  /* Return the required length to the caller */
5425  _SEH2_TRY
5426  {
5428  }
5430  {
5431  /* Bail out and return the exception code */
5433  _SEH2_YIELD(goto Quit);
5434  }
5435  _SEH2_END;
5436 
5437  /* The buffer length provided is smaller than the required length, bail out */
5439  {
5441  goto Quit;
5442  }
5443  }
5444 
5445  /*
5446  * Now it's time to apply changes. Wrap the code
5447  * in SEH as we are returning the old groups state
5448  * list to the caller since PreviousState is a
5449  * UM pointer.
5450  */
5451  _SEH2_TRY
5452  {
5454  CapturedGroups,
5455  CapturedCount,
5456  TRUE,
5457  ResetToDefault,
5458  &ChangesMade,
5459  PreviousState,
5460  &ChangeCount);
5461  }
5463  {
5464  /* Bail out and return the exception code */
5466 
5467  /* Force the write as we touched the token still */
5468  ChangesMade = TRUE;
5469  _SEH2_YIELD(goto Quit);
5470  }
5471  _SEH2_END;
5472 
5473 Quit:
5474  /* Allocate a new ID for the token as we made changes */
5475  if (ChangesMade)
5476  {
5477  ExAllocateLocallyUniqueId(&Token->ModifiedId);
5478  }
5479 
5480  /* Have we successfully acquired the lock and referenced the token before? */
5481  if (LockAndReferenceAcquired)
5482  {
5483  /* Unlock and dereference the token */
5486  }
5487 
5488  /* Release the captured groups */
5489  if (CapturedGroups != NULL)
5490  {
5491  SeReleaseSidAndAttributesArray(CapturedGroups,
5492  PreviousMode,
5493  TRUE);
5494  }
5495 
5496  return Status;
5497 }
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:220
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3767
VOID NTAPI SeReleaseSidAndAttributesArray(_In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID with attributes.
Definition: sid.c:768
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
TOpcodeData Groups[17][8]
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define TOKEN_ADJUST_GROUPS
Definition: setypes.h:909
#define TOKEN_QUERY
Definition: setypes.h:906
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define SepReleaseTokenLock(Token)
Definition: se.h:231
NTSTATUS NTAPI SeCaptureSidAndAttributesArray(_In_ PSID_AND_ATTRIBUTES SrcSidAndAttributes, _In_ ULONG AttributeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_opt_ PVOID AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID_AND_ATTRIBUTES *CapturedSidAndAttributes, _Out_ PULONG ResultLength)
Captures a SID with attributes.
Definition: sid.c:485
_SEH2_END
Definition: create.c:4400
VOID NTAPI ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
Definition: uuid.c:335
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:29
static NTSTATUS SepAdjustGroups(_In_ PTOKEN Token, _In_opt_ PSID_AND_ATTRIBUTES NewState, _In_ ULONG NewStateCount, _In_ BOOLEAN ApplyChanges, _In_ BOOLEAN ResetToDefaultStates, _Out_ PBOOLEAN ChangesMade, _Out_opt_ PTOKEN_GROUPS PreviousGroupsState, _Out_ PULONG ChangedGroups)
Private routine that iterates over the groups of an access token to be adjusted as per on request by ...
Definition: token.c:5068
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829
#define PAGED_CODE()

Referenced by AdjustTokenGroups(), and START_TEST().

◆ NtAdjustPrivilegesToken()

_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtAdjustPrivilegesToken ( _In_ HANDLE  TokenHandle,
_In_ BOOLEAN  DisableAllPrivileges,
_In_opt_ PTOKEN_PRIVILEGES  NewState,
_In_ ULONG  BufferLength,
_Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_PRIVILEGES  PreviousState,
_When_(PreviousState!=NULL, _Out_) PULONG  ReturnLength 
)

Removes a certain amount of privileges of a token based upon the request by the caller.

Parameters
[in,out]TokenToken handle where the privileges are about to be modified.
[in]DisableAllPrivilegesIf set to TRUE, the function disables all the privileges.
[in]NewStateA new list of privileges that the function will use it accordingly to either disable or enable the said privileges and change them.
[in]NewStateCountThe new total number count of privileges.
[out]PreviousStateIf specified, the function will return the previous state list of privileges.
[in]ApplyChangesIf set to TRUE, the function will immediatelly apply the changes onto the token's privileges.
[out]ChangedPrivilegesThe returned count number of changed privileges.
[out]ChangesMadeIf TRUE, the function has made changes to the token's privileges. FALSE otherwise.
Returns
Returns STATUS_SUCCESS if the function has successfully changed the list of privileges. STATUS_NOT_ALL_ASSIGNED is returned if not every privilege has been changed.

Definition at line 5695 of file token.c.

5703 {
5704  NTSTATUS Status;
5706  PTOKEN Token;
5707  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
5708  ULONG CapturedCount = 0;
5709  ULONG CapturedLength = 0;
5710  ULONG NewStateSize = 0;
5711  ULONG ChangeCount;
5713  BOOLEAN ChangesMade = FALSE;
5714 
5715  PAGED_CODE();
5716 
5717  DPRINT("NtAdjustPrivilegesToken() called\n");
5718 
5719  /* Fail, if we do not disable all privileges but NewState is NULL */
5720  if (DisableAllPrivileges == FALSE && NewState == NULL)
5721  return STATUS_INVALID_PARAMETER;
5722 
5724  if (PreviousMode != KernelMode)
5725  {
5726  _SEH2_TRY
5727  {
5728  /* Probe NewState */
5729  if (DisableAllPrivileges == FALSE)
5730  {
5731  /* First probe the header */
5732  ProbeForRead(NewState, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG));
5733 
5734  CapturedCount = NewState->PrivilegeCount;
5735  NewStateSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedCount]);
5736 
5737  ProbeForRead(NewState, NewStateSize, sizeof(ULONG));
5738  }
5739 
5740  /* Probe PreviousState and ReturnLength */
5741  if (PreviousState != NULL)
5742  {
5744  ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
5745  }
5746  }
5748  {
5749  /* Return the exception code */
5751  }
5752  _SEH2_END;
5753  }
5754  else
5755  {
5756  /* This is kernel mode, we trust the caller */
5757  if (DisableAllPrivileges == FALSE)
5758  CapturedCount = NewState->PrivilegeCount;
5759  }
5760 
5761  /* Do we need to capture the new state? */
5762  if (DisableAllPrivileges == FALSE)
5763  {
5764  _SEH2_TRY
5765  {
5766  /* Capture the new state array of privileges */
5767  Status = SeCaptureLuidAndAttributesArray(NewState->Privileges,
5768  CapturedCount,
5769  PreviousMode,
5770  NULL,
5771  0,
5772  PagedPool,
5773  TRUE,
5774  &CapturedPrivileges,
5775  &CapturedLength);
5776  }
5778  {
5779  /* Return the exception code */
5781  }
5782  _SEH2_END;
5783 
5784  if (!NT_SUCCESS(Status))
5785  return Status;
5786  }
5787 
5788  /* Reference the token */
5792  PreviousMode,
5793  (PVOID*)&Token,
5794  NULL);
5795  if (!NT_SUCCESS(Status))
5796  {
5797  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
5798 
5799  /* Release the captured privileges */
5800  if (CapturedPrivileges != NULL)
5801  {
5802  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
5803  PreviousMode,
5804  TRUE);
5805  }
5806 
5807  return Status;
5808  }
5809 
5810  /* Lock the token */
5812 
5813  /* Count the privileges that need to be changed, do not apply them yet */
5815  DisableAllPrivileges,
5816  CapturedPrivileges,
5817  CapturedCount,
5818  NULL,
5819  FALSE,
5820  &ChangeCount,
5821  &ChangesMade);
5822 
5823  /* Check if the caller asked for the previous state */
5824  if (PreviousState != NULL)
5825  {
5826  /* Calculate the required length */
5828 
5829  /* Try to return the required buffer length */
5830  _SEH2_TRY
5831  {
5833  }
5835  {
5836  /* Do cleanup and return the exception code */
5838  _SEH2_YIELD(goto Cleanup);
5839  }
5840  _SEH2_END;
5841 
5842  /* Fail, if the buffer length is smaller than the required length */
5844  {
5846  goto Cleanup;
5847  }
5848  }
5849 
5850  /* Now enter SEH, since we might return the old privileges */
5851  _SEH2_TRY
5852  {
5853  /* This time apply the changes */
5855  DisableAllPrivileges,
5856  CapturedPrivileges,
5857  CapturedCount,
5858  PreviousState,
5859  TRUE,
5860  &ChangeCount,
5861  &ChangesMade);
5862  }
5864  {
5865  /* Do cleanup and return the exception code */
5867  ChangesMade = TRUE; // Force write.
5868  _SEH2_YIELD(goto Cleanup);
5869  }
5870  _SEH2_END;
5871 
5872 Cleanup:
5873  /* Touch the token if we made changes */
5874  if (ChangesMade)
5875  ExAllocateLocallyUniqueId(&Token->ModifiedId);
5876 
5877  /* Unlock and dereference the token */
5880 
5881  /* Release the captured privileges */
5882  if (CapturedPrivileges != NULL)
5883  {
5884  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
5885  PreviousMode,
5886  TRUE);
5887  }
5888 
5889  DPRINT ("NtAdjustPrivilegesToken() done\n");
5890  return Status;
5891 }
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:220
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3767
NTSTATUS NTAPI SeCaptureLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Src, _In_ ULONG PrivilegeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_ PLUID_AND_ATTRIBUTES AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PLUID_AND_ATTRIBUTES *Dest, _Inout_ PULONG Length)
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define KeGetPreviousMode()
Definition: ketypes.h:1107
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
static NTSTATUS SepAdjustPrivileges(_Inout_ PTOKEN Token, _In_ BOOLEAN DisableAllPrivileges, _In_opt_ PLUID_AND_ATTRIBUTES NewState, _In_ ULONG NewStateCount, _Out_opt_ PTOKEN_PRIVILEGES PreviousState, _In_ BOOLEAN ApplyChanges, _Out_ PULONG ChangedPrivileges, _Out_ PBOOLEAN ChangesMade)
Removes a certain amount of privileges of a token based upon the request by the caller.
Definition: token.c:5538
#define TOKEN_QUERY
Definition: setypes.h:906
VOID NTAPI SeReleaseLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Privilege, _In_ KPROCESSOR_MODE PreviousMode, _In_ BOOLEAN CaptureIfKernel)
Releases a LUID with attributes structure.
Definition: priv.c:554
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET * Privileges
Definition: sefuncs.h:13
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define SepReleaseTokenLock(Token)
Definition: se.h:231
static const WCHAR Cleanup[]
Definition: register.c:80
_SEH2_END
Definition: create.c:4400
VOID NTAPI ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
Definition: uuid.c:335
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:29
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define DPRINT
Definition: sndvol32.h:71
#define TOKEN_ADJUST_PRIVILEGES
Definition: setypes.h:908
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829
#define PAGED_CODE()

Referenced by AdjustEnableDefaultPriv(), AdjustTokenPrivileges(), SmpAcquirePrivilege(), and SmpReleasePrivilege().

◆ NtCompareTokens()

NTSTATUS NTAPI NtCompareTokens ( _In_ HANDLE  FirstTokenHandle,
_In_ HANDLE  SecondTokenHandle,
_Out_ PBOOLEAN  Equal 
)

Compares tokens if they're equal or not.

Parameters
[in]FirstTokenThe first token.
[in]SecondTokenThe second token.
[out]EqualThe retrieved value which determines if the tokens are equal or not.
Returns
Returns STATUS_SUCCESS, otherwise it returns a failure NTSTATUS code.

Definition at line 6474 of file token.c.

6478 {
6480  PTOKEN FirstToken, SecondToken;
6481  BOOLEAN IsEqual;
6482  NTSTATUS Status;
6483 
6484  PAGED_CODE();
6485 
6487 
6488  if (PreviousMode != KernelMode)
6489  {
6490  _SEH2_TRY
6491  {
6492  ProbeForWriteBoolean(Equal);
6493  }
6495  {
6496  /* Return the exception code */
6498  }
6499  _SEH2_END;
6500  }
6501 
6502  Status = ObReferenceObjectByHandle(FirstTokenHandle,
6503  TOKEN_QUERY,
6505  PreviousMode,
6506  (PVOID*)&FirstToken,
6507  NULL);
6508  if (!NT_SUCCESS(Status))
6509  {
6510  DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
6511  return Status;
6512  }
6513 
6514  Status = ObReferenceObjectByHandle(SecondTokenHandle,
6515  TOKEN_QUERY,
6517  PreviousMode,
6518  (PVOID*)&SecondToken,
6519  NULL);
6520  if (!NT_SUCCESS(Status))
6521  {
6522  DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
6523  ObDereferenceObject(FirstToken);
6524  return Status;
6525  }
6526 
6527  if (FirstToken != SecondToken)
6528  {
6529  Status = SepCompareTokens(FirstToken,
6530  SecondToken,
6531  &IsEqual);
6532  }
6533  else
6534  {
6535  IsEqual = TRUE;
6536  }
6537 
6538  ObDereferenceObject(SecondToken);
6539  ObDereferenceObject(FirstToken);
6540 
6541  if (NT_SUCCESS(Status))
6542  {
6543  _SEH2_TRY
6544  {
6545  *Equal = IsEqual;
6546  }
6548  {
6550  }
6551  _SEH2_END;
6552  }
6553 
6554  return Status;
6555 }
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
unsigned char BOOLEAN
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define TOKEN_QUERY
Definition: setypes.h:906
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
static NTSTATUS SepCompareTokens(_In_ PTOKEN FirstToken, _In_ PTOKEN SecondToken, _Out_ PBOOLEAN Equal)
Compares tokens if they're equal based on all the following properties. If all of the said conditions...
Definition: token.c:288
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ProbeForWriteBoolean(Ptr)
Definition: probe.h:31
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_SEH2_END
Definition: create.c:4400
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:349
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define PAGED_CODE()

Referenced by START_TEST().

◆ NtCreateToken()

__kernel_entry NTSTATUS NTAPI NtCreateToken ( _Out_ PHANDLE  TokenHandle,
_In_ ACCESS_MASK  DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES  ObjectAttributes,
_In_ TOKEN_TYPE  TokenType,
_In_ PLUID  AuthenticationId,
_In_ PLARGE_INTEGER  ExpirationTime,
_In_ PTOKEN_USER  TokenUser,
_In_ PTOKEN_GROUPS  TokenGroups,
_In_ PTOKEN_PRIVILEGES  TokenPrivileges,
_In_opt_ PTOKEN_OWNER  TokenOwner,
_In_ PTOKEN_PRIMARY_GROUP  TokenPrimaryGroup,
_In_opt_ PTOKEN_DEFAULT_DACL  TokenDefaultDacl,
_In_ PTOKEN_SOURCE  TokenSource 
)

Creates an access token.

Parameters
[out]TokenHandleThe returned created token handle to the caller.
[in]DesiredAccessThe desired access rights for the token that we're creating.
[in]ObjectAttributesThe object attributes for the token object that we're creating.
[in]TokenTypeThe type of token to assign for the newly created token.
[in]AuthenticationIdAuthentication ID that represents the token's identity.
[in]ExpirationTimeExpiration time for the token. If set to -1, the token never expires.
[in]TokenUserThe main user entity for the token to assign.
[in]TokenGroupsGroup list of SIDs for the token to assign.
[in]TokenPrivilegesPrivileges for the token.
[in]TokenOwnerThe main user that owns the newly created token.
[in]TokenPrimaryGroupThe primary group that represents as the main group of the token.
[in]TokenDefaultDaclDiscretionary access control list for the token. This limits on how the token can be used, accessed and used by whom.
[in]TokenSourceThe source origin of the token who creates it.
Returns
Returns STATUS_SUCCESS if the function has successfully created the token. A failure NTSTATUS code is returned otherwise.

Definition at line 5944 of file token.c.

5958 {
5959  HANDLE hToken;
5961  ULONG PrivilegeCount, GroupCount;
5962  PSID OwnerSid, PrimaryGroupSid;
5963  PACL DefaultDacl;
5964  LARGE_INTEGER LocalExpirationTime = {{0, 0}};
5965  LUID LocalAuthenticationId;
5966  TOKEN_SOURCE LocalTokenSource;
5967  SECURITY_QUALITY_OF_SERVICE LocalSecurityQos;
5968  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
5969  PSID_AND_ATTRIBUTES CapturedUser = NULL;
5970  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
5971  PSID CapturedOwnerSid = NULL;
5972  PSID CapturedPrimaryGroupSid = NULL;
5973  PACL CapturedDefaultDacl = NULL;
5974  ULONG PrivilegesLength, UserLength, GroupsLength;
5975  NTSTATUS Status;
5976 
5977  PAGED_CODE();
5978 
5980 
5981  if (PreviousMode != KernelMode)
5982  {
5983  _SEH2_TRY
5984  {
5986 
5987  if (ObjectAttributes != NULL)
5988  {
5990  sizeof(OBJECT_ATTRIBUTES),
5991  sizeof(ULONG));
5992  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
5993  }
5994 
5995  ProbeForRead(AuthenticationId,
5996  sizeof(LUID),
5997  sizeof(ULONG));
5998  LocalAuthenticationId = *AuthenticationId;
5999 
6000  LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
6001 
6003  sizeof(TOKEN_USER),
6004  sizeof(ULONG));
6005 
6007  sizeof(TOKEN_GROUPS),
6008  sizeof(ULONG));
6009  GroupCount = TokenGroups->GroupCount;
6010 
6012  sizeof(TOKEN_PRIVILEGES),
6013  sizeof(ULONG));
6014  PrivilegeCount = TokenPrivileges->PrivilegeCount;
6015 
6016  if (TokenOwner != NULL)
6017  {
6019  sizeof(TOKEN_OWNER),
6020  sizeof(ULONG));
6021  OwnerSid = TokenOwner->Owner;
6022  }
6023  else
6024  {
6025  OwnerSid = NULL;
6026  }
6027 
6029  sizeof(TOKEN_PRIMARY_GROUP),
6030  sizeof(ULONG));
6031  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
6032 
6033  if (TokenDefaultDacl != NULL)
6034  {
6036  sizeof(TOKEN_DEFAULT_DACL),
6037  sizeof(ULONG));
6038  DefaultDacl = TokenDefaultDacl->DefaultDacl;
6039  }
6040  else
6041  {
6042  DefaultDacl = NULL;
6043  }
6044 
6046  sizeof(TOKEN_SOURCE),
6047  sizeof(ULONG));
6048  LocalTokenSource = *TokenSource;
6049  }
6051  {
6052  /* Return the exception code */
6054  }
6055  _SEH2_END;
6056  }
6057  else
6058  {
6059  if (ObjectAttributes != NULL)
6060  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
6061  LocalAuthenticationId = *AuthenticationId;
6062  LocalExpirationTime = *ExpirationTime;
6063  GroupCount = TokenGroups->GroupCount;
6064  PrivilegeCount = TokenPrivileges->PrivilegeCount;
6065  OwnerSid = TokenOwner ? TokenOwner->Owner : NULL;
6066  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
6067  DefaultDacl = TokenDefaultDacl ? TokenDefaultDacl->DefaultDacl : NULL;
6068  LocalTokenSource = *TokenSource;
6069  }
6070 
6071  /* Check token type */
6072  if ((TokenType < TokenPrimary) ||
6074  {
6075  return STATUS_BAD_TOKEN_TYPE;
6076  }
6077 
6078  /* Check for token creation privilege */
6080  {
6082  }
6083 
6084  /* Capture the user SID and attributes */
6086  1,
6087  PreviousMode,
6088  NULL,
6089  0,
6090  PagedPool,
6091  FALSE,
6092  &CapturedUser,
6093  &UserLength);
6094  if (!NT_SUCCESS(Status))
6095  {
6096  goto Cleanup;
6097  }
6098 
6099  /* Capture the groups SID and attributes array */
6101  GroupCount,
6102  PreviousMode,
6103  NULL,
6104  0,
6105  PagedPool,
6106  FALSE,
6107  &CapturedGroups,
6108  &GroupsLength);
6109  if (!NT_SUCCESS(Status))
6110  {
6111  goto Cleanup;
6112  }
6113 
6114  /* Capture privileges */
6116  PrivilegeCount,
6117  PreviousMode,
6118  NULL,
6119  0,
6120  PagedPool,
6121  FALSE,
6122  &CapturedPrivileges,
6123  &PrivilegesLength);
6124  if (!NT_SUCCESS(Status))
6125  {
6126  goto Cleanup;
6127  }
6128 
6129  /* Capture the token owner SID */
6130  if (TokenOwner != NULL)
6131  {
6132  Status = SepCaptureSid(OwnerSid,
6133  PreviousMode,
6134  PagedPool,
6135  FALSE,
6136  &CapturedOwnerSid);
6137  if (!NT_SUCCESS(Status))
6138  {
6139  goto Cleanup;
6140  }
6141  }
6142 
6143  /* Capture the token primary group SID */
6144  Status = SepCaptureSid(PrimaryGroupSid,
6145  PreviousMode,
6146  PagedPool,
6147  FALSE,
6148  &CapturedPrimaryGroupSid);
6149  if (!NT_SUCCESS(Status))
6150  {
6151  goto Cleanup;
6152  }
6153 
6154  /* Capture DefaultDacl */
6155  if (DefaultDacl != NULL)
6156  {
6157  Status = SepCaptureAcl(DefaultDacl,
6158  PreviousMode,
6159  NonPagedPool,
6160  FALSE,
6161  &CapturedDefaultDacl);
6162  if (!NT_SUCCESS(Status))
6163  {
6164  goto Cleanup;
6165  }
6166  }
6167 
6168  /* Call the internal function */
6169  Status = SepCreateToken(&hToken,
6170  PreviousMode,
6171  DesiredAccess,
6173  TokenType,
6174  LocalSecurityQos.ImpersonationLevel,
6175  &LocalAuthenticationId,
6176  &LocalExpirationTime,
6177  CapturedUser,
6178  GroupCount,
6179  CapturedGroups,
6180  GroupsLength,
6181  PrivilegeCount,
6182  CapturedPrivileges,
6183  CapturedOwnerSid,
6184  CapturedPrimaryGroupSid,
6185  CapturedDefaultDacl,
6186  &LocalTokenSource,
6187  FALSE);
6188  if (NT_SUCCESS(Status))
6189  {
6190  _SEH2_TRY
6191  {
6192  *TokenHandle = hToken;
6193  }
6195  {
6197  }
6198  _SEH2_END;
6199  }
6200 
6201 Cleanup:
6202 
6203  /* Release what we captured */
6206  SeReleaseLuidAndAttributesArray(CapturedPrivileges, PreviousMode, FALSE);
6207  SepReleaseSid(CapturedOwnerSid, PreviousMode, FALSE);
6208  SepReleaseSid(CapturedPrimaryGroupSid, PreviousMode, FALSE);
6209  SepReleaseAcl(CapturedDefaultDacl, PreviousMode, FALSE);
6210 
6211  return Status;
6212 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
VOID NTAPI SepReleaseAcl(_In_ PACL CapturedAcl, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases (frees) a captured ACL from the memory pool.
Definition: acl.c:459
const LUID SeCreateTokenPrivilege
Definition: priv.c:21
VOID NTAPI SeReleaseSidAndAttributesArray(_In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID with attributes.
Definition: sid.c:768
NTSTATUS NTAPI SeCaptureLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Src, _In_ ULONG PrivilegeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_ PLUID_AND_ATTRIBUTES AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PLUID_AND_ATTRIBUTES *Dest, _Inout_ PULONG Length)
NTSTATUS NTAPI SepCaptureSid(_In_ PSID InputSid, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID *CapturedSid)
Captures a SID.
Definition: sid.c:314
LONG NTSTATUS
Definition: precomp.h:26
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
VOID NTAPI SepReleaseSid(_In_ PSID CapturedSid, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID.
Definition: sid.c:400
_SEH2_TRY
Definition: create.c:4226
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI SepCaptureAcl(_In_ PACL InputAcl, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PACL *CapturedAcl)
Captures an access control list from an already valid input ACL.
Definition: acl.c:352
#define STATUS_BAD_TOKEN_TYPE
Definition: ntstatus.h:404
NTSTATUS NTAPI SepCreateToken(_Out_ PHANDLE TokenHandle, _In_ KPROCESSOR_MODE PreviousMode, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PSID_AND_ATTRIBUTES User, _In_ ULONG GroupCount, _In_ PSID_AND_ATTRIBUTES Groups, _In_ ULONG GroupsLength, _In_ ULONG PrivilegeCount, _In_ PLUID_AND_ATTRIBUTES Privileges, _In_opt_ PSID Owner, _In_ PSID PrimaryGroup, _In_opt_ PACL DefaultDacl, _In_ PTOKEN_SOURCE TokenSource, _In_ BOOLEAN SystemToken)
Internal function responsible for access token object creation in the kernel. A fully created token o...
Definition: token.c:1708
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
VOID NTAPI SeReleaseLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Privilege, _In_ KPROCESSOR_MODE PreviousMode, _In_ BOOLEAN CaptureIfKernel)
Releases a LUID with attributes structure.
Definition: priv.c:554
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
NTSTATUS NTAPI SeCaptureSidAndAttributesArray(_In_ PSID_AND_ATTRIBUTES SrcSidAndAttributes, _In_ ULONG AttributeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_opt_ PVOID AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID_AND_ATTRIBUTES *CapturedSidAndAttributes, _Out_ PULONG ResultLength)
Captures a SID with attributes.
Definition: sid.c:485
static const WCHAR Cleanup[]
Definition: register.c:80
_SEH2_END
Definition: create.c:4400
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
#define NULL
Definition: types.h:112
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:401
#define PAGED_CODE()

Referenced by LsapLogonUser().

◆ NtDuplicateToken()

_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtDuplicateToken ( _In_ HANDLE  ExistingTokenHandle,
_In_ ACCESS_MASK  DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES  ObjectAttributes,
_In_ BOOLEAN  EffectiveOnly,
_In_ TOKEN_TYPE  TokenType,
_Out_ PHANDLE  NewTokenHandle 
)

Duplicates a token.

Parameters
[in]ExistingTokenHandleAn existing token to duplicate.
[in]DesiredAccessThe desired access rights for the new duplicated token.
[in]ObjectAttributesObject attributes for the new duplicated token.
[in]EffectiveOnlyIf set to TRUE, the function removes all the disabled privileges and groups of the token to duplicate.
[in]TokenTypeType of token to assign to the duplicated token.
[out]NewTokenHandleThe returned duplicated token handle.
Returns
STATUS_SUCCESS is returned if token duplication has completed successfully. STATUS_BAD_IMPERSONATION_LEVEL is returned if the caller erroneously wants to raise the impersonation level even though the conditions do not permit it. A failure NTSTATUS code is returned otherwise.
Remarks
Some sources claim 4th param is ImpersonationLevel, but on W2K this is certainly NOT true, although I can't say for sure that EffectiveOnly is correct either. -Gunnar This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore wrong in that regard, while MSDN documentation is correct.

Definition at line 4853 of file token.c.

4860 {
4862  HANDLE hToken;
4863  PTOKEN Token;
4864  PTOKEN NewToken;
4865  PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
4866  BOOLEAN QoSPresent;
4868  NTSTATUS Status;
4869 
4870  PAGED_CODE();
4871 
4872  if (TokenType != TokenImpersonation &&
4874  {
4875  return STATUS_INVALID_PARAMETER;
4876  }
4877 
4879 
4880  if (PreviousMode != KernelMode)
4881  {
4882  _SEH2_TRY
4883  {
4885  }
4887  {
4888  /* Return the exception code */
4890  }
4891  _SEH2_END;
4892  }
4893 
4895  PreviousMode,
4896  PagedPool,
4897  FALSE,
4898  &CapturedSecurityQualityOfService,
4899  &QoSPresent);
4900  if (!NT_SUCCESS(Status))
4901  {
4902  DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
4903  return Status;
4904  }
4905 
4906  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
4909  PreviousMode,
4910  (PVOID*)&Token,
4912  if (!NT_SUCCESS(Status))
4913  {
4914  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
4915  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
4916  PreviousMode,
4917  FALSE);
4918  return Status;
4919  }
4920 
4921  /*
4922  * Fail, if the original token is an impersonation token and the caller
4923  * tries to raise the impersonation level of the new token above the
4924  * impersonation level of the original token.
4925  */
4926  if (Token->TokenType == TokenImpersonation)
4927  {
4928  if (QoSPresent &&
4929  CapturedSecurityQualityOfService->ImpersonationLevel >Token->ImpersonationLevel)
4930  {
4932  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
4933  PreviousMode,
4934  FALSE);
4936  }
4937  }
4938 
4939  /*
4940  * Fail, if a primary token is to be created from an impersonation token
4941  * and and the impersonation level of the impersonation token is below SecurityImpersonation.
4942  */
4943  if (Token->TokenType == TokenImpersonation &&
4944  TokenType == TokenPrimary &&
4945  Token->ImpersonationLevel < SecurityImpersonation)
4946  {
4948  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
4949  PreviousMode,
4950  FALSE);
4952  }
4953 
4956  EffectiveOnly,
4957  TokenType,
4958  (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
4959  PreviousMode,
4960  &NewToken);
4961 
4963 
4964  if (NT_SUCCESS(Status))
4965  {
4966  Status = ObInsertObject(NewToken,
4967  NULL,
4968  (DesiredAccess ? DesiredAccess : HandleInformation.GrantedAccess),
4969  0,
4970  NULL,
4971  &hToken);
4972  if (NT_SUCCESS(Status))
4973  {
4974  _SEH2_TRY
4975  {
4976  *NewTokenHandle = hToken;
4977  }
4979  {
4981  }
4982  _SEH2_END;
4983  }
4984  }
4985 
4986  /* Free the captured structure */
4987  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
4988  PreviousMode,
4989  FALSE);
4990 
4991  return Status;
4992 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define STATUS_BAD_IMPERSONATION_LEVEL
Definition: ntstatus.h:401
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define KeGetPreviousMode()
Definition: ketypes.h:1107
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI SepDuplicateToken(_In_ PTOKEN Token, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL Level, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *NewAccessToken)
Duplicates an access token, from an existing valid token.
Definition: token.c:995
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE _Out_ PHANDLE NewTokenHandle
Definition: sefuncs.h:401
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
_In_ ACCESS_MASK _In_opt_ POBJECT_TYPE _In_ KPROCESSOR_MODE _Out_ PVOID _Out_opt_ POBJECT_HANDLE_INFORMATION HandleInformation
Definition: obfuncs.h:40
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define TOKEN_DUPLICATE
Definition: setypes.h:904
VOID NTAPI SepReleaseSecurityQualityOfService(_In_opt_ PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases (frees) the captured SQOS data from an object in the memory pool.
Definition: sqos.c:225
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2934
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
NTSTATUS NTAPI SepCaptureSecurityQualityOfService(_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, _Out_ PBOOLEAN Present)
Captures the security quality of service data given the object attributes from an object.
Definition: sqos.c:52
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN EffectiveOnly
Definition: sefuncs.h:401
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:401
#define PAGED_CODE()

Referenced by CreateProcessAsUserCommon(), DuplicateTokenAsEffective(), DuplicateTokenEx(), and ImpersonateLoggedOnUser().

◆ NtFilterToken()

NTSTATUS NTAPI NtFilterToken ( _In_ HANDLE  ExistingTokenHandle,
_In_ ULONG  Flags,
_In_opt_ PTOKEN_GROUPS  SidsToDisable,
_In_opt_ PTOKEN_PRIVILEGES  PrivilegesToDelete,
_In_opt_ PTOKEN_GROUPS  RestrictedSids,
_Out_ PHANDLE  NewTokenHandle 
)

Creates an access token in a restricted form from the original existing token, that is, such action is called filtering.

Parameters
[in]ExistingTokenHandleA handle to an access token which is to be filtered.
[in]FlagsPrivilege flag options. This parameter argument influences how the token's privileges are filtered. For further details see remarks.
[in]SidsToDisableArray of SIDs to disable. The action of doing so assigns the SE_GROUP_USE_FOR_DENY_ONLY attribute to the respective group SID and takes away SE_GROUP_ENABLED and SE_GROUP_ENABLED_BY_DEFAULT. This parameter can be NULL. This can be a UM pointer.
[in]PrivilegesToDeleteArray of privileges to delete. The function will walk within this array to determine if the specified privileges do exist in the access token. Any missing privileges gets ignored. This parameter can be NULL. This can be a UM pointer.
[in]RestrictedSidsAn array list of restricted groups SID to be added in the access token. A token that is already restricted the newly added restricted SIDs are redundant information in addition to the existing restricted SIDs in the token. This parameter can be NULL. This can be a UM pointer.
[out]NewTokenHandleA new handle to the restricted (filtered) access token. This can be a UM pointer.
Returns
Returns STATUS_SUCCESS if the routine has successfully filtered the access token. STATUS_INVALID_PARAMETER is returned if one or more parameters are not valid (see SepPerformTokenFiltering routine call for more information). A failure NTSTATUS code is returned otherwise.
Remarks
The Flags parameter determines the final outcome of how the privileges in an access token are filtered. This parameter can take these supported values (these can be combined):

0 – Filter the token's privileges in the usual way. The function expects that the caller MUST PROVIDE a valid array list of privileges to be deleted (that is, PrivilegesToDelete MUSTN'T BE NULL).

DISABLE_MAX_PRIVILEGE – Disables (deletes) all the privileges except SeChangeNotifyPrivilege in the new access token. Bear in mind if this flag is specified the routine ignores PrivilegesToDelete.

SANDBOX_INERT – Stores the TOKEN_SANDBOX_INERT token flag within the access token.

LUA_TOKEN – The newly filtered access token is a LUA token. This flag is not supported in Windows Server 2003.

WRITE_RESTRICTED – The newly filtered token has the restricted SIDs that are considered only when evaluating write access onto the token. This value is not supported in Windows Server 2003.

Definition at line 6622 of file token.c.

6629 {
6630  PTOKEN Token, FilteredToken;
6631  HANDLE FilteredTokenHandle;
6632  NTSTATUS Status;
6634  OBJECT_HANDLE_INFORMATION HandleInfo;
6636  ULONG CapturedSidsCount = 0;
6637  ULONG CapturedPrivilegesCount = 0;
6638  ULONG CapturedRestrictedSidsCount = 0;
6639  ULONG ProbeSize = 0;
6640  PSID_AND_ATTRIBUTES CapturedSids = NULL;
6641  PSID_AND_ATTRIBUTES CapturedRestrictedSids = NULL;
6642  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
6643 
6644  PAGED_CODE();
6645 
6647 
6648  _SEH2_TRY
6649  {
6650  /* Probe SidsToDisable */
6651  if (SidsToDisable != NULL)
6652  {
6653  /* Probe the header */
6654  ProbeForRead(SidsToDisable, sizeof(*SidsToDisable), sizeof(ULONG));
6655 
6656  CapturedSidsCount = SidsToDisable->GroupCount;
6657  ProbeSize = FIELD_OFFSET(TOKEN_GROUPS, Groups[CapturedSidsCount]);
6658 
6659  ProbeForRead(SidsToDisable, ProbeSize, sizeof(ULONG));
6660  }
6661 
6662  /* Probe PrivilegesToDelete */
6663  if (PrivilegesToDelete != NULL)
6664  {
6665  /* Probe the header */
6666  ProbeForRead(PrivilegesToDelete, sizeof(*PrivilegesToDelete), sizeof(ULONG));
6667 
6668  CapturedPrivilegesCount = PrivilegesToDelete->PrivilegeCount;
6669  ProbeSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedPrivilegesCount]);
6670 
6671  ProbeForRead(PrivilegesToDelete, ProbeSize, sizeof(ULONG));
6672  }
6673 
6674  /* Probe RestrictedSids */
6675  if (RestrictedSids != NULL)
6676  {
6677  /* Probe the header */
6678  ProbeForRead(RestrictedSids, sizeof(*RestrictedSids), sizeof(ULONG));
6679 
6680  CapturedRestrictedSidsCount = RestrictedSids->GroupCount;
6681  ProbeSize = FIELD_OFFSET(TOKEN_GROUPS, Groups[CapturedRestrictedSidsCount]);
6682 
6683  ProbeForRead(RestrictedSids, ProbeSize, sizeof(ULONG));
6684  }
6685 
6686  /* Probe the handle */
6688  }
6690  {
6691  /* Return the exception code */
6693  }
6694  _SEH2_END;
6695 
6696  /* Reference the token and do the job */
6697  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
6700  PreviousMode,
6701  (PVOID*)&Token,
6702  &HandleInfo);
6703  if (!NT_SUCCESS(Status))
6704  {
6705  DPRINT1("NtFilterToken(): Failed to reference the token (Status 0x%lx)\n", Status);
6706  return Status;
6707  }
6708 
6709  /* Lock the token */
6711 
6712  /* Capture the group SIDs */
6713  if (SidsToDisable != NULL)
6714  {
6715  Status = SeCaptureSidAndAttributesArray(SidsToDisable->Groups,
6716  CapturedSidsCount,
6717  PreviousMode,
6718  NULL,
6719  0,
6720  PagedPool,
6721  TRUE,
6722  &CapturedSids,
6723  &ResultLength);
6724  if (!NT_SUCCESS(Status))
6725  {
6726  DPRINT1("NtFilterToken(): Failed to capture the SIDs (Status 0x%lx)\n", Status);
6727  goto Quit;
6728  }
6729  }
6730 
6731  /* Capture the privileges */
6732  if (PrivilegesToDelete != NULL)
6733  {
6734  Status = SeCaptureLuidAndAttributesArray(PrivilegesToDelete->Privileges,
6735  CapturedPrivilegesCount,
6736  PreviousMode,
6737  NULL,
6738  0,
6739  PagedPool,
6740  TRUE,
6741  &CapturedPrivileges,
6742  &ResultLength);
6743  if (!NT_SUCCESS(Status))
6744  {
6745  DPRINT1("NtFilterToken(): Failed to capture the privileges (Status 0x%lx)\n", Status);
6746  goto Quit;
6747  }
6748  }
6749 
6750  /* Capture the restricted SIDs */
6751  if (RestrictedSids != NULL)
6752  {
6753  Status = SeCaptureSidAndAttributesArray(RestrictedSids->Groups,
6754  CapturedRestrictedSidsCount,
6755  PreviousMode,
6756  NULL,
6757  0,
6758  PagedPool,
6759  TRUE,
6760  &CapturedRestrictedSids,
6761  &ResultLength);
6762  if (!NT_SUCCESS(Status))
6763  {
6764  DPRINT1("NtFilterToken(): Failed to capture the restricted SIDs (Status 0x%lx)\n", Status);
6765  goto Quit;
6766  }
6767  }
6768 
6769  /* Call the internal API so that it can filter the token for us */
6771  CapturedPrivileges,
6772  CapturedSids,
6773  CapturedRestrictedSids,
6774  CapturedPrivilegesCount,
6775  CapturedSidsCount,
6776  CapturedRestrictedSidsCount,
6777  Flags,
6778  PreviousMode,
6779  &FilteredToken);
6780  if (!NT_SUCCESS(Status))
6781  {
6782  DPRINT1("NtFilterToken(): Failed to filter the token (Status 0x%lx)\n", Status);
6783  goto Quit;
6784  }
6785 
6786  /* We got our filtered token, insert it to the handle */
6787  Status = ObInsertObject(FilteredToken,
6788  NULL,
6789  HandleInfo.GrantedAccess,
6790  0,
6791  NULL,
6792  &FilteredTokenHandle);
6793  if (!NT_SUCCESS(Status))
6794  {
6795  DPRINT1("NtFilterToken(): Failed to insert the filtered token object into the handle (Status 0x%lx)\n", Status);
6796  goto Quit;
6797  }
6798 
6799  /* And give it to the caller once we're done */
6800  _SEH2_TRY
6801  {
6802  *NewTokenHandle = FilteredTokenHandle;
6803  }
6805  {
6807  _SEH2_YIELD(goto Quit);
6808  }
6809  _SEH2_END;
6810 
6811 Quit:
6812  /* Unlock and dereference the token */
6815 
6816  /* Release all the stuff we've captured */
6817  if (CapturedSids != NULL)
6818  {
6819  SeReleaseSidAndAttributesArray(CapturedSids,
6820  PreviousMode,
6821  TRUE);
6822 
6823  CapturedSids = NULL;
6824  }
6825 
6826  if (CapturedPrivileges != NULL)
6827  {
6828  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
6829  PreviousMode,
6830  TRUE);
6831 
6832  CapturedPrivileges = NULL;
6833  }
6834 
6835  if (CapturedRestrictedSids != NULL)
6836  {
6837  SeReleaseSidAndAttributesArray(CapturedRestrictedSids,
6838  PreviousMode,
6839  TRUE);
6840 
6841  CapturedRestrictedSids = NULL;
6842  }
6843 
6844  return Status;
6845 }
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:220
VOID NTAPI SeReleaseSidAndAttributesArray(_In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID with attributes.
Definition: sid.c:768
NTSTATUS NTAPI SeCaptureLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Src, _In_ ULONG PrivilegeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_ PLUID_AND_ATTRIBUTES AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PLUID_AND_ATTRIBUTES *Dest, _Inout_ PULONG Length)
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
TOpcodeData Groups[17][8]
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE _Out_ PHANDLE NewTokenHandle
Definition: sefuncs.h:401
ACCESS_MASK GrantedAccess
Definition: iotypes.h:181
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
static NTSTATUS SepPerformTokenFiltering(_In_ PTOKEN Token, _In_opt_ PLUID_AND_ATTRIBUTES PrivilegesToBeDeleted, _In_opt_ PSID_AND_ATTRIBUTES SidsToBeDisabled, _In_opt_ PSID_AND_ATTRIBUTES RestrictedSidsIntoToken, _When_(PrivilegesToBeDeleted !=NULL, _In_) ULONG PrivilegesCount, _When_(SidsToBeDisabled !=NULL, _In_) ULONG RegularGroupsSidCount, _When_(RestrictedSidsIntoToken !=NULL, _In_) ULONG RestrictedSidsCount, _In_ ULONG PrivilegeFlags, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *FilteredToken)
Private helper function responsible for creating a restricted access token, that is,...
Definition: token.c:2040
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
VOID NTAPI SeReleaseLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Privilege, _In_ KPROCESSOR_MODE PreviousMode, _In_ BOOLEAN CaptureIfKernel)
Releases a LUID with attributes structure.
Definition: priv.c:554
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET * Privileges
Definition: sefuncs.h:13
#define TOKEN_DUPLICATE
Definition: setypes.h:904
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define SepReleaseTokenLock(Token)
Definition: se.h:231
NTSTATUS NTAPI SeCaptureSidAndAttributesArray(_In_ PSID_AND_ATTRIBUTES SrcSidAndAttributes, _In_ ULONG AttributeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_opt_ PVOID AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID_AND_ATTRIBUTES *CapturedSidAndAttributes, _Out_ PULONG ResultLength)
Captures a SID with attributes.
Definition: sid.c:485
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2934
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define PAGED_CODE()

Referenced by CreateRestrictedToken(), and START_TEST().

◆ NtImpersonateAnonymousToken()

NTSTATUS NTAPI NtImpersonateAnonymousToken ( _In_ HANDLE  ThreadHandle)

Allows the calling thread to impersonate the system's anonymous logon token.

Parameters
[in]ThreadHandleA handle to the thread to start the procedure of logon token impersonation. The thread must have the THREAD_IMPERSONATE access right.
Returns
Returns STATUS_SUCCESS if the thread has successfully impersonated the anonymous logon token, otherwise a failure NTSTATUS code is returned.
Remarks
By default the system gives the opportunity to the caller to impersonate the anonymous logon token without including the Everyone Group SID. In cases where the caller wants to impersonate the token including such group, the EveryoneIncludesAnonymous registry value setting has to be set to 1, from HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa registry path. The calling thread must invoke PsRevertToSelf when impersonation is no longer needed or RevertToSelf if the calling execution is done in user mode.

Definition at line 6873 of file token.c.

6875 {
6876  PETHREAD Thread;
6878  NTSTATUS Status;
6879  PAGED_CODE();
6880 
6882 
6883  /* Obtain the thread object from the handle */
6884  Status = ObReferenceObjectByHandle(ThreadHandle,
6886  PsThreadType,
6887  PreviousMode,
6888  (PVOID*)&Thread,
6889  NULL);
6890  if (!NT_SUCCESS(Status))
6891  {
6892  DPRINT1("NtImpersonateAnonymousToken(): Failed to reference the object (Status 0x%lx)\n", Status);
6893  return Status;
6894  }
6895 
6896  /* Call the private routine to impersonate the token */
6898  if (!NT_SUCCESS(Status))
6899  {
6900  DPRINT1("NtImpersonateAnonymousToken(): Failed to impersonate the token (Status 0x%lx)\n", Status);
6901  }
6902 
6904  return Status;
6905 }
#define THREAD_IMPERSONATE
Definition: pstypes.h:151
LONG NTSTATUS
Definition: precomp.h:26
static NTSTATUS SepImpersonateAnonymousToken(_In_ PETHREAD Thread, _In_ KPROCESSOR_MODE PreviousMode)
Private function that impersonates the system's anonymous logon token. The major bulk of the imperson...
Definition: token.c:379
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
POBJECT_TYPE PsThreadType
Definition: thread.c:20
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
#define PAGED_CODE()

Referenced by ImpersonateAnonymousToken(), and START_TEST().

◆ NtOpenThreadToken()

NTSTATUS NTAPI NtOpenThreadToken ( _In_ HANDLE  ThreadHandle,
_In_ ACCESS_MASK  DesiredAccess,
_In_ BOOLEAN  OpenAsSelf,
_Out_ PHANDLE  TokenHandle 
)

Opens a token that is tied to a thread handle.

Parameters
[out]ThreadHandleThread handle where the token is about to be opened.
[in]DesiredAccessThe request access right for the token.
[in]OpenAsSelfIf set to TRUE, the access check will be made with the security context of the process of the calling thread (opening as self). Otherwise the access check will be made with the security context of the calling thread instead.
[out]TokenHandleThe opened token handle returned to the caller for use.
Returns
See NtOpenThreadTokenEx.

Definition at line 6445 of file token.c.

6450 {
6451  return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
6452  TokenHandle);
6453 }
NTSTATUS NTAPI NtOpenThreadTokenEx(_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _In_ ULONG HandleAttributes, _Out_ PHANDLE TokenHandle)
Opens a token that is tied to a thread handle.
Definition: token.c:6243
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
_In_ ACCESS_MASK _In_ BOOLEAN OpenAsSelf
Definition: zwfuncs.h:699

Referenced by BaseGetNamedObjectDirectory(), CheckTokenMembership(), CsrGetProcessLuid(), GetCallerLuid(), LsarSetSecurityObject(), NpGetUserNamep(), OpenThreadToken(), RSetServiceObjectSecurity(), RtlDefaultNpAcl(), RtlNewSecurityGrantedAccess(), RtlpGetImpersonationToken(), and START_TEST().

◆ NtOpenThreadTokenEx()

NTSTATUS NTAPI NtOpenThreadTokenEx ( _In_ HANDLE  ThreadHandle,
_In_ ACCESS_MASK  DesiredAccess,
_In_ BOOLEAN  OpenAsSelf,
_In_ ULONG  HandleAttributes,
_Out_ PHANDLE  TokenHandle 
)

Opens a token that is tied to a thread handle.

Parameters
[out]ThreadHandleThread handle where the token is about to be opened.
[in]DesiredAccessThe request access right for the token.
[in]OpenAsSelfIf set to TRUE, the access check will be made with the security context of the process of the calling thread (opening as self). Otherwise the access check will be made with the security context of the calling thread instead.
[in]HandleAttributesHandle attributes for the opened thread token handle.
[out]TokenHandleThe opened token handle returned to the caller for use.
Returns
Returns STATUS_SUCCESS if the function has successfully opened the thread token. STATUS_CANT_OPEN_ANONYMOUS is returned if a token has SecurityAnonymous as impersonation level and we cannot open it. A failure NTSTATUS code is returned otherwise.

Definition at line 6243 of file token.c.

6249 {
6250  PETHREAD Thread;
6251  HANDLE hToken;
6252  PTOKEN Token, NewToken = NULL, PrimaryToken;
6258  PACL Dacl = NULL;
6260  NTSTATUS Status;
6261  BOOLEAN RestoreImpersonation = FALSE;
6262 
6263  PAGED_CODE();
6264 
6266 
6267  if (PreviousMode != KernelMode)
6268  {
6269  _SEH2_TRY
6270  {
6272  }
6274  {
6275  /* Return the exception code */
6277  }
6278  _SEH2_END;
6279  }
6280 
6281  /* Validate object attributes */
6283 
6284  /*
6285  * At first open the thread token for information access and verify
6286  * that the token associated with thread is valid.
6287  */
6288 
6291  NULL);
6292  if (!NT_SUCCESS(Status))
6293  {
6294  return Status;
6295  }
6296 
6299  if (Token == NULL)
6300  {
6302  return STATUS_NO_TOKEN;
6303  }
6304 
6306  {
6310  }
6311 
6312  /*
6313  * Revert to self if OpenAsSelf is specified.
6314  */
6315 
6316  if (OpenAsSelf)
6317  {
6318  RestoreImpersonation = PsDisableImpersonation(PsGetCurrentThread(),
6320  }
6321 
6322  if (CopyOnOpen)
6323  {
6324  PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
6325 
6326  Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
6327 
6328  ObFastDereferenceObject(&Thread->ThreadsProcess->Token, PrimaryToken);
6329 
6330  if (NT_SUCCESS(Status))
6331  {
6332  if (Dacl)
6333  {
6336  if (!NT_SUCCESS(Status))
6337  {
6338  DPRINT1("NtOpenThreadTokenEx(): Failed to create a security descriptor (Status 0x%lx)\n", Status);
6339  }
6340 
6342  FALSE);
6343  if (!NT_SUCCESS(Status))
6344  {
6345  DPRINT1("NtOpenThreadTokenEx(): Failed to set a DACL to the security descriptor (Status 0x%lx)\n", Status);
6346  }
6347  }
6348 
6351 
6354  KernelMode, &NewToken);
6355  if (!NT_SUCCESS(Status))
6356  {
6357  DPRINT1("NtOpenThreadTokenEx(): Failed to duplicate the token (Status 0x%lx)\n", Status);
6358  }
6359 
6360  ObReferenceObject(NewToken);
6361  Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
6362  &hToken);
6363  if (!NT_SUCCESS(Status))
6364  {
6365  DPRINT1("NtOpenThreadTokenEx(): Failed to insert the token object (Status 0x%lx)\n", Status);
6366  }
6367  }
6368  else
6369  {
6370  DPRINT1("NtOpenThreadTokenEx(): Failed to impersonate token from DACL (Status 0x%lx)\n", Status);
6371  }
6372  }
6373  else
6374  {
6377  PreviousMode, &hToken);
6378  if (!NT_SUCCESS(Status))
6379  {
6380  DPRINT1("NtOpenThreadTokenEx(): Failed to open the object (Status 0x%lx)\n", Status);
6381  }
6382  }
6383 
6385 
6386  if (RestoreImpersonation)
6387  {
6389  }
6390 
6392 
6393  if (NT_SUCCESS(Status) && CopyOnOpen)
6394  {
6396  if (!NT_SUCCESS(Status))
6397  {
6398  DPRINT1("NtOpenThreadTokenEx(): Failed to impersonate the client (Status 0x%lx)\n", Status);
6399  }
6400  }
6401 
6402  if (NewToken) ObDereferenceObject(NewToken);
6403 
6405 
6406  if (NT_SUCCESS(Status))
6407  {
6408  _SEH2_TRY
6409  {
6410  *TokenHandle = hToken;
6411  }
6413  {
6415  }
6416  _SEH2_END;
6417  }
6418 
6419  return Status;
6420 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSTATUS NTAPI PsImpersonateClient(IN PETHREAD Thread, IN PACCESS_TOKEN Token, IN BOOLEAN CopyOnOpen, IN BOOLEAN EffectiveOnly, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Definition: security.c:610
_In_ HANDLE _In_opt_ HANDLE _Out_opt_ PHANDLE _In_ ACCESS_MASK _In_ ULONG HandleAttributes
Definition: obfuncs.h:429
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
_Inout_ PSE_IMPERSONATION_STATE ImpersonationState
Definition: psfuncs.h:189
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define TRUE
Definition: types.h:120
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:182
#define STATUS_CANT_OPEN_ANONYMOUS
Definition: ntstatus.h:402
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
_Out_ PBOOLEAN CopyOnOpen
Definition: psfuncs.h:154
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
NTSTATUS NTAPI ObOpenObjectByPointer(IN PVOID Object, IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PHANDLE Handle)
Definition: obhandle.c:2741
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
_SEH2_TRY
Definition: create.c:4226
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
NTSTATUS NTAPI SepDuplicateToken(_In_ PTOKEN Token, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL Level, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *NewAccessToken)
Duplicates an access token, from an existing valid token.
Definition: token.c:995
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define FALSE
Definition: types.h:117
enum _SECURITY_IMPERSONATION_LEVEL SECURITY_IMPERSONATION_LEVEL
VOID NTAPI PsRestoreImpersonation(IN PETHREAD Thread, IN PSE_IMPERSONATION_STATE ImpersonationState)
Definition: security.c:965
unsigned char BOOLEAN
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
BOOLEAN NTAPI PsDisableImpersonation(IN PETHREAD Thread, OUT PSE_IMPERSONATION_STATE ImpersonationState)
Definition: security.c:915
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_Out_ PBOOLEAN _Out_ PBOOLEAN _Out_ PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: psfuncs.h:154
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
#define STATUS_NO_TOKEN
Definition: ntstatus.h:360
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1552
POBJECT_TYPE PsThreadType
Definition: thread.c:20
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
PACCESS_TOKEN NTAPI PsReferenceImpersonationToken(IN PETHREAD Thread, OUT PBOOLEAN CopyOnOpen, OUT PBOOLEAN EffectiveOnly, OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Definition: security.c:849
FORCEINLINE ULONG ObpValidateAttributes(IN ULONG Attributes, IN KPROCESSOR_MODE PreviousMode)
Definition: ob_x.h:22
#define TAG_ACL
Definition: tag.h:146
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2934
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
VOID FASTCALL ObFastDereferenceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:167
#define ObReferenceObject
Definition: obfuncs.h:204
#define THREAD_QUERY_INFORMATION
Definition: pstypes.h:149
_In_ ACCESS_MASK _In_ BOOLEAN OpenAsSelf
Definition: zwfuncs.h:699
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN EffectiveOnly
Definition: sefuncs.h:401
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
NTSTATUS NTAPI SepCreateImpersonationTokenDacl(_In_ PTOKEN Token, _In_ PTOKEN PrimaryToken, _Out_ PACL *Dacl)
Allocates a discretionary access control list based on certain properties of a regular and primary ac...
Definition: acl.c:277
#define PAGED_CODE()
VOID NTAPI PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken)
Definition: security.c:888

Referenced by NtOpenThreadToken(), and START_TEST().

◆ NtQueryInformationToken()

_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken ( _In_ HANDLE  TokenHandle,
_In_ TOKEN_INFORMATION_CLASS  TokenInformationClass,
_Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID  TokenInformation,
_In_ ULONG  TokenInformationLength,
_Out_ PULONG  ReturnLength 
)

Queries a specific type of information in regard of an access token based upon the information class. The calling thread must have specific access rights in order to obtain specific information about the token.

Parameters
[in]TokenHandleA handle of a token where information is to be gathered.
[in]TokenInformationClassToken information class.
[out]TokenInformationA returned output buffer with token information, which information is arbitrarily upon the information class chosen.
[in]TokenInformationLengthLength of the token information buffer, in bytes.
[out]ReturnLengthIf specified in the call, the function returns the total length size of the token information buffer..
Returns
Returns STATUS_SUCCESS if information querying has completed successfully. STATUS_BUFFER_TOO_SMALL is returned if the information length that represents the token information buffer is not greater than the required length. STATUS_INVALID_HANDLE is returned if the token handle is not a valid one. STATUS_INVALID_INFO_CLASS is returned if the information class is not a valid one (that is, the class doesn't belong to TOKEN_INFORMATION_CLASS). A failure NTSTATUS code is returned otherwise.

Definition at line 3692 of file token.c.

3699 {
3700  NTSTATUS Status;
3702  PTOKEN Token;
3704  union
3705  {
3706  PSID PSid;
3707  ULONG Ulong;
3708  } Unused;
3709 
3710  PAGED_CODE();
3711 
3713 
3714  /* Check buffers and class validity */
3718  TokenInformation,
3720  ReturnLength,
3721  NULL,
3722  PreviousMode,
3723  TRUE);
3724  if (!NT_SUCCESS(Status))
3725  {
3726  DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
3727  return Status;
3728  }
3729 
3733  PreviousMode,
3734  (PVOID*)&Token,
3735  NULL);
3736  if (NT_SUCCESS(Status))
3737  {
3738  /* Lock the token */
3740 
3741  switch (TokenInformationClass)
3742  {
3743  case TokenUser:
3744  {
3745  PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
3746 
3747  DPRINT("NtQueryInformationToken(TokenUser)\n");
3748  RequiredLength = sizeof(TOKEN_USER) +
3749  RtlLengthSid(Token->UserAndGroups[0].Sid);
3750 
3751  _SEH2_TRY
3752  {
3754  {
3756  &Token->UserAndGroups[0],
3757  RequiredLength - sizeof(TOKEN_USER),
3758  &tu->User,
3759  (PSID)(tu + 1),
3760  &Unused.PSid,
3761  &Unused.Ulong);
3762  }
3763  else
3764  {
3766  }
3767 
3768  if (ReturnLength != NULL)
3769  {
3771  }
3772  }
3774  {
3776  }
3777  _SEH2_END;
3778 
3779  break;
3780  }
3781 
3782  case TokenGroups:
3783  {
3784  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
3785 
3786  DPRINT("NtQueryInformationToken(TokenGroups)\n");
3787  RequiredLength = sizeof(tg->GroupCount) +
3788  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
3789 
3790  _SEH2_TRY
3791  {
3793  {
3794  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
3795  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
3796  PSID Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
3797  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
3798 
3799  tg->GroupCount = Token->UserAndGroupCount - 1;
3800  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
3801  &Token->UserAndGroups[1],
3802  SidLen,
3803  &tg->Groups[0],
3804  Sid,
3805  &Unused.PSid,
3806  &Unused.Ulong);
3807  }
3808  else
3809  {
3811  }
3812 
3813  if (ReturnLength != NULL)
3814  {
3816  }
3817  }
3819  {
3821  }
3822  _SEH2_END;
3823 
3824  break;
3825  }
3826 
3827  case TokenPrivileges:
3828  {
3829  PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
3830 
3831  DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
3832  RequiredLength = sizeof(tp->PrivilegeCount) +
3833  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
3834 
3835  _SEH2_TRY
3836  {
3838  {
3839  tp->PrivilegeCount = Token->PrivilegeCount;
3840  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
3841  Token->Privileges,
3842  &tp->Privileges[0]);
3843  }
3844  else
3845  {
3847  }
3848 
3849  if (ReturnLength != NULL)
3850  {
3852  }
3853  }
3855  {
3857  }
3858  _SEH2_END;
3859 
3860  break;
3861  }
3862 
3863  case TokenOwner:
3864  {
3865  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
3866  ULONG SidLen;
3867 
3868  DPRINT("NtQueryInformationToken(TokenOwner)\n");
3869  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
3870  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
3871 
3872  _SEH2_TRY
3873  {
3875  {
3876  to->Owner = (PSID)(to + 1);
3877  Status = RtlCopySid(SidLen,
3878  to->Owner,
3879  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
3880  }
3881  else
3882  {
3884  }
3885 
3886  if (ReturnLength != NULL)
3887  {
3889  }
3890  }
3892  {
3894  }
3895  _SEH2_END;
3896 
3897  break;
3898  }
3899 
3900  case TokenPrimaryGroup:
3901  {
3902  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
3903  ULONG SidLen;
3904 
3905  DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
3906  SidLen = RtlLengthSid(Token->PrimaryGroup);
3907  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
3908 
3909  _SEH2_TRY
3910  {
3912  {
3913  tpg->PrimaryGroup = (PSID)(tpg + 1);
3914  Status = RtlCopySid(SidLen,
3915  tpg->PrimaryGroup,
3916  Token->PrimaryGroup);
3917  }
3918  else
3919  {
3921  }
3922 
3923  if (ReturnLength != NULL)
3924  {
3926  }
3927  }
3929  {
3931  }
3932  _SEH2_END;
3933 
3934  break;
3935  }
3936 
3937  case TokenDefaultDacl:
3938  {
3939  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
3940 
3941  DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
3943 
3944  if (Token->DefaultDacl != NULL)
3945  RequiredLength += Token->DefaultDacl->AclSize;
3946 
3947  _SEH2_TRY
3948  {
3950  {
3951  if (Token->DefaultDacl != NULL)
3952  {
3953  tdd->DefaultDacl = (PACL)(tdd + 1);
3955  Token->DefaultDacl,
3956  Token->DefaultDacl->AclSize);
3957  }
3958  else
3959  {
3960  tdd->DefaultDacl = NULL;
3961  }
3962  }
3963  else
3964  {
3966  }
3967 
3968  if (ReturnLength != NULL)
3969  {
3971  }
3972  }
3974  {
3976  }
3977  _SEH2_END;
3978 
3979  break;
3980  }
3981 
3982  case TokenSource:
3983  {
3984  PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
3985 
3986  DPRINT("NtQueryInformationToken(TokenSource)\n");
3987  RequiredLength = sizeof(TOKEN_SOURCE);
3988 
3989  _SEH2_TRY
3990  {
3992  {
3993  *ts = Token->TokenSource;
3994  }
3995  else
3996  {
3998  }
3999 
4000  if (ReturnLength != NULL)
4001  {
4003  }
4004  }
4006  {
4008  }
4009  _SEH2_END;
4010 
4011  break;
4012  }
4013 
4014  case TokenType:
4015  {
4016  PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
4017 
4018  DPRINT("NtQueryInformationToken(TokenType)\n");
4019  RequiredLength = sizeof(TOKEN_TYPE);
4020 
4021  _SEH2_TRY
4022  {
4024  {
4025  *tt = Token->TokenType;
4026  }
4027  else
4028  {
4030  }
4031 
4032  if (ReturnLength != NULL)
4033  {
4035  }
4036  }
4038  {
4040  }
4041  _SEH2_END;
4042 
4043  break;
4044  }
4045 
4047  {
4049 
4050  DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
4051 
4052  /* Fail if the token is not an impersonation token */
4053  if (Token->TokenType != TokenImpersonation)
4054  {
4056  break;
4057  }
4058 
4060 
4061  _SEH2_TRY
4062  {
4064  {
4065  *sil = Token->ImpersonationLevel;
4066  }
4067  else
4068  {
4070  }
4071 
4072  if (ReturnLength != NULL)
4073  {
4075  }
4076  }
4078  {
4080  }
4081  _SEH2_END;
4082 
4083  break;
4084  }
4085 
4086  case TokenStatistics:
4087  {
4088  PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
4089 
4090  DPRINT("NtQueryInformationToken(TokenStatistics)\n");
4091  RequiredLength = sizeof(TOKEN_STATISTICS);
4092 
4093  _SEH2_TRY
4094  {
4096  {
4097  ts->TokenId = Token->TokenId;
4098  ts->AuthenticationId = Token->AuthenticationId;
4099  ts->ExpirationTime = Token->ExpirationTime;
4100  ts->TokenType = Token->TokenType;
4101  ts->ImpersonationLevel = Token->ImpersonationLevel;
4102  ts->DynamicCharged = Token->DynamicCharged;
4103  ts->DynamicAvailable = Token->DynamicAvailable;
4104  ts->GroupCount = Token->UserAndGroupCount - 1;
4105  ts->PrivilegeCount = Token->PrivilegeCount;
4106  ts->ModifiedId = Token->ModifiedId;
4107  }
4108  else
4109  {
4111  }
4112 
4113  if (ReturnLength != NULL)
4114  {
4116  }
4117  }
4119  {
4121  }
4122  _SEH2_END;
4123 
4124  break;
4125  }
4126 
4127  case TokenOrigin:
4128  {
4129  PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
4130 
4131  DPRINT("NtQueryInformationToken(TokenOrigin)\n");
4132  RequiredLength = sizeof(TOKEN_ORIGIN);
4133 
4134  _SEH2_TRY
4135  {
4137  {
4139  &Token->AuthenticationId);
4140  }
4141  else
4142  {
4144  }
4145 
4146  if (ReturnLength != NULL)
4147  {
4149  }
4150  }
4152  {
4154  }
4155  _SEH2_END;
4156 
4157  break;
4158  }
4159 
4161  DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
4163  break;
4164 
4165  case TokenRestrictedSids:
4166  {
4167  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
4168 
4169  DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
4170  RequiredLength = sizeof(tg->GroupCount) +
4171  RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
4172 
4173  _SEH2_TRY
4174  {
4176  {
4177  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
4178  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
4179  PSID Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
4180  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
4181 
4182  tg->GroupCount = Token->RestrictedSidCount;
4183  Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
4184  Token->RestrictedSids,
4185  SidLen,
4186  &tg->Groups[0],
4187  Sid,
4188  &Unused.PSid,
4189  &Unused.Ulong);
4190  }
4191  else
4192  {
4194  }
4195 
4196  if (ReturnLength != NULL)
4197  {
4199  }
4200  }
4202  {
4204  }
4205  _SEH2_END;
4206 
4207  break;
4208  }
4209 
4210  case TokenSandBoxInert:
4211  DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
4213  break;
4214 
4215  case TokenSessionId:
4216  {
4217  ULONG SessionId = 0;
4218 
4219  DPRINT("NtQueryInformationToken(TokenSessionId)\n");
4220 
4222  if (NT_SUCCESS(Status))
4223  {
4224  _SEH2_TRY
4225  {
4226  /* Buffer size was already verified, no need to check here again */
4227  *(PULONG)TokenInformation = SessionId;
4228 
4229  if (ReturnLength != NULL)
4230  {
4231  *ReturnLength = sizeof(ULONG);
4232  }
4233  }
4235  {
4237  }
4238  _SEH2_END;
4239  }
4240 
4241  break;
4242  }
4243 
4244  default:
4245  DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
4247  break;
4248  }
4249 
4250  /* Unlock and dereference the token */
4253  }
4254 
4255  return Status;
4256 }
LUID AuthenticationId
Definition: setypes.h:1065
enum _SECURITY_IMPERSONATION_LEVEL * PSECURITY_IMPERSONATION_LEVEL
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
_Must_inspect_result_ typedef _In_ PVOID Unused
Definition: iotypes.h:1166
struct _TOKEN_PRIMARY_GROUP * PTOKEN_PRIMARY_GROUP
_In_ TOKEN_INFORMATION_CLASS _In_ ULONG TokenInformationLength
Definition: sefuncs.h:312
#define TRUE
Definition: types.h:120
struct _TOKEN_DEFAULT_DACL TOKEN_DEFAULT_DACL
enum _TOKEN_TYPE * PTOKEN_TYPE
$ULONG GroupCount
Definition: setypes.h:1071
$ULONG DynamicCharged
Definition: setypes.h:1069
ULONG SessionId
Definition: dllmain.c:28
NTSYSAPI NTSTATUS NTAPI RtlCopySidAndAttributesArray(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src, _In_ ULONG SidAreaSize, _In_ PSID_AND_ATTRIBUTES Dest, _In_ PSID SidArea, _Out_ PSID *RemainingSidArea, _Out_ PULONG RemainingSidAreaSize)
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
struct _TOKEN_USER TOKEN_USER
static __inline NTSTATUS DefaultQueryInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength, PULONG_PTR ReturnLengthPtr, KPROCESSOR_MODE PreviousMode, BOOLEAN CompleteProbing)
Definition: probe.h:59
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
static ULONG RtlLengthSidAndAttributes(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src)
Computes the length size of a SID.
Definition: token.c:823
return STATUS_NOT_IMPLEMENTED
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
struct _TOKEN_DEFAULT_DACL * PTOKEN_DEFAULT_DACL
NTSYSAPI VOID NTAPI RtlCopyLuidAndAttributesArray(ULONG Count, PLUID_AND_ATTRIBUTES Src, PLUID_AND_ATTRIBUTES Dest)
Definition: luid.c:33
enum _SECURITY_IMPERSONATION_LEVEL SECURITY_IMPERSONATION_LEVEL
struct _TOKEN_ORIGIN * PTOKEN_ORIGIN
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1103
PSID Owner
Definition: setypes.h:1006
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
TOKEN_TYPE TokenType
Definition: setypes.h:1067
struct _TOKEN_GROUPS * PTOKEN_GROUPS
LUID OriginatingLogonSession
Definition: setypes.h:1085
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
struct _ACL * PACL
Definition: security.c:104
Status
Definition: gdiplustypes.h:24
struct _SID_AND_ATTRIBUTES * PSID_AND_ATTRIBUTES
Definition: security.c:129
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
LARGE_INTEGER ExpirationTime
Definition: setypes.h:1066
struct _TOKEN_SOURCE * PTOKEN_SOURCE
#define TOKEN_QUERY
Definition: setypes.h:906
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _TOKEN_OWNER TOKEN_OWNER
struct _TOKEN_SOURCE TOKEN_SOURCE
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
struct _SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES
#define ObDereferenceObject
Definition: obfuncs.h:203
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: setypes.h:1068
#define TOKEN_QUERY_SOURCE
Definition: setypes.h:907
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
struct _SID * PSID
Definition: eventlog.c:35
struct _TOKEN_OWNER * PTOKEN_OWNER
struct _TOKEN_PRIVILEGES * PTOKEN_PRIVILEGES
struct _TOKEN_STATISTICS * PTOKEN_STATISTICS
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define SepReleaseTokenLock(Token)
Definition: se.h:231
NTSYSAPI BOOLEAN WINAPI RtlCopySid(DWORD, PSID, PSID)
enum _TOKEN_TYPE TOKEN_TYPE
_SEH2_END
Definition: create.c:4400
$ULONG PrivilegeCount
Definition: setypes.h:1072
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]
Definition: setypes.h:996
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:29
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
NTSYSAPI void WINAPI RtlCopyLuid(PLUID, const LUID *)
$ULONG GroupCount
Definition: setypes.h:992
#define SepAcquireTokenLockShared(Token)
Definition: se.h:225
unsigned int ULONG
Definition: retypes.h:1
struct _TOKEN_USER * PTOKEN_USER
SID_AND_ATTRIBUTES User
Definition: setypes.h:988
static const INFORMATION_CLASS_INFO SeTokenInformationClass[]
Definition: token.c:32
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define DPRINT
Definition: sndvol32.h:71
NTSTATUS NTAPI SeQuerySessionIdToken(_In_ PACCESS_TOKEN Token, _Out_ PULONG pSessionId)
Queries the session ID of an access token.
Definition: token.c:3397
$ULONG DynamicAvailable
Definition: setypes.h:1070
struct _TOKEN_STATISTICS TOKEN_STATISTICS
unsigned long Ulong
Definition: utypes.h:42
struct _TOKEN_PRIMARY_GROUP TOKEN_PRIMARY_GROUP
_In_ TOKEN_INFORMATION_CLASS TokenInformationClass
Definition: sefuncs.h:310
struct _TOKEN_ORIGIN TOKEN_ORIGIN
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:401
#define PAGED_CODE()

Referenced by CreateProcessAsUserCommon(), CsrGetProcessLuid(), CsrSetProcessSecurity(), DoAdminUnlock(), DuplicateTokenAsEffective(), GetCallerLuid(), GetSiteSidFromToken(), GetTokenInformation(), GetUserSid(), GetUserSidStringFromToken(), ImpersonateLoggedOnUser(), IsTokenRestricted(), LsapIsTrustedClient(), PlayLogonSoundThread(), RegOpenUserClassesRoot(), RtlDefaultNpAcl(), RtlNewInstanceSecurityObject(), RtlNewSecurityGrantedAccess(), and START_TEST().

◆ NtSetInformationToken()

_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtSetInformationToken ( _In_ HANDLE  TokenHandle,
_In_ TOKEN_INFORMATION_CLASS  TokenInformationClass,
_In_reads_bytes_(TokenInformationLength) PVOID  TokenInformation,
_In_ ULONG  TokenInformationLength 
)

Sets (modifies) some specific information in regard of an access token. The calling thread must have specific access rights in order to modify token's information data.

@unimplemented

Parameters
[in]TokenHandleA handle of a token where information is to be modified.
[in]TokenInformationClassToken information class.
[in]TokenInformationAn arbitrary pointer to a buffer with token information to set. Such arbitrary buffer depends on the information class chosen that the caller wants to modify such information data of a token.
[in]TokenInformationLengthLength of the token information buffer, in bytes.
Returns
Returns STATUS_SUCCESS if information setting has completed successfully. STATUS_INFO_LENGTH_MISMATCH is returned if the information length of the buffer is less than the required length. STATUS_INSUFFICIENT_RESOURCES is returned if memory pool allocation has failed. STATUS_PRIVILEGE_NOT_HELD is returned if the calling thread hasn't the required privileges to perform the operation in question. A failure NTSTATUS code is returned otherwise.
Remarks
The function is partly implemented, mainly TokenOrigin and TokenDefaultDacl.

Definition at line 4294 of file token.c.

4299 {
4300  NTSTATUS Status;
4301  PTOKEN Token;
4303  ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
4304 
4305  PAGED_CODE();
4306 
4308 
4312  TokenInformation,
4314  PreviousMode);
4315  if (!NT_SUCCESS(Status))
4316  {
4317  /* Invalid buffers */
4318  DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
4319  return Status;
4320  }
4321 
4323  {
4324  NeededAccess |= TOKEN_ADJUST_SESSIONID;
4325  }
4326 
4328  NeededAccess,
4330  PreviousMode,
4331  (PVOID*)&Token,
4332  NULL);
4333  if (NT_SUCCESS(Status))
4334  {
4335  switch (TokenInformationClass)
4336  {
4337  case TokenOwner:
4338  {
4339  if (TokenInformationLength >= sizeof(TOKEN_OWNER))
4340  {
4341  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
4342  PSID InputSid = NULL, CapturedSid;
4343  ULONG DefaultOwnerIndex;
4344 
4345  _SEH2_TRY
4346  {
4347  InputSid = to->Owner;
4348  }
4350  {
4352  _SEH2_YIELD(goto Cleanup);
4353  }
4354  _SEH2_END;
4355 
4356  Status = SepCaptureSid(InputSid,
4357  PreviousMode,
4358  PagedPool,
4359  FALSE,
4360  &CapturedSid);
4361  if (NT_SUCCESS(Status))
4362  {
4363  /* Lock the token */
4365 
4366  /* Find the owner amongst the existing token user and groups */
4368  NULL,
4369  CapturedSid,
4370  NULL,
4371  &DefaultOwnerIndex);
4372  if (NT_SUCCESS(Status))
4373  {
4374  /* Found it */
4375  Token->DefaultOwnerIndex = DefaultOwnerIndex;
4376  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4377  }
4378 
4379  /* Unlock the token */
4381 
4382  SepReleaseSid(CapturedSid,
4383  PreviousMode,
4384  FALSE);
4385  }
4386  }
4387  else
4388  {
4390  }
4391  break;
4392  }
4393 
4394  case TokenPrimaryGroup:
4395  {
4397  {
4398  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
4399  PSID InputSid = NULL, CapturedSid;
4400  ULONG PrimaryGroupIndex;
4401 
4402  _SEH2_TRY
4403  {
4404  InputSid = tpg->PrimaryGroup;
4405  }
4407  {
4409  _SEH2_YIELD(goto Cleanup);
4410  }
4411  _SEH2_END;
4412 
4413  Status = SepCaptureSid(InputSid,
4414  PreviousMode,
4415  PagedPool,
4416  FALSE,
4417  &CapturedSid);
4418  if (NT_SUCCESS(Status))
4419  {
4420  /* Lock the token */
4422 
4423  /* Find the primary group amongst the existing token user and groups */
4425  CapturedSid,
4426  NULL,
4427  &PrimaryGroupIndex,
4428  NULL);
4429  if (NT_SUCCESS(Status))
4430  {
4431  /* Found it */
4432  Token->PrimaryGroup = Token->UserAndGroups[PrimaryGroupIndex].Sid;
4433  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4434  }
4435 
4436  /* Unlock the token */
4438 
4439  SepReleaseSid(CapturedSid,
4440  PreviousMode,
4441  FALSE);
4442  }
4443  }
4444  else
4445  {
4447  }
4448  break;
4449  }
4450 
4451  case TokenDefaultDacl:
4452  {
4454  {
4455  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
4456  PACL InputAcl = NULL;
4457 
4458  _SEH2_TRY
4459  {
4460  InputAcl = tdd->DefaultDacl;
4461  }
4463  {
4465  _SEH2_YIELD(goto Cleanup);
4466  }
4467  _SEH2_END;
4468 
4469  if (InputAcl != NULL)
4470  {
4471  PACL CapturedAcl;
4472 
4473  /* Capture and copy the dacl */
4474  Status = SepCaptureAcl(InputAcl,
4475  PreviousMode,
4476  PagedPool,
4477  TRUE,
4478  &CapturedAcl);
4479  if (NT_SUCCESS(Status))
4480  {
4481  ULONG DynamicLength;
4482 
4483  /* Lock the token */
4485 
4486  //
4487  // NOTE: So far our dynamic area only contains
4488  // the default dacl, so this makes the following
4489  // code pretty simple. The day where it stores
4490  // other data, the code will require adaptations.
4491  //
4492 
4493  DynamicLength = Token->DynamicAvailable;
4494  // Add here any other data length present in the dynamic area...
4495  if (Token->DefaultDacl)
4496  DynamicLength += Token->DefaultDacl->AclSize;
4497 
4498  /* Reallocate the dynamic area if it is too small */
4500  if ((DynamicLength < CapturedAcl->AclSize) ||
4501  (Token->DynamicPart == NULL))
4502  {
4503  PVOID NewDynamicPart;
4504 
4505  NewDynamicPart = ExAllocatePoolWithTag(PagedPool,
4506  CapturedAcl->AclSize,
4508  if (NewDynamicPart == NULL)
4509  {
4511  }
4512  else
4513  {
4514  if (Token->DynamicPart != NULL)
4515  {
4516  // RtlCopyMemory(NewDynamicPart, Token->DynamicPart, DynamicLength);
4517  ExFreePoolWithTag(Token->DynamicPart, TAG_TOKEN_DYNAMIC);
4518  }
4519  Token->DynamicPart = NewDynamicPart;
4520  Token->DynamicAvailable = 0;
4521  }
4522  }
4523  else
4524  {
4525  Token->DynamicAvailable = DynamicLength - CapturedAcl->AclSize;
4526  }
4527 
4528  if (NT_SUCCESS(Status))
4529  {
4530  /* Set the new dacl */
4531  Token->DefaultDacl = (PVOID)Token->DynamicPart;
4532  RtlCopyMemory(Token->DefaultDacl,
4533  CapturedAcl,
4534  CapturedAcl->AclSize);
4535 
4536  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4537  }
4538 
4539  /* Unlock the token */
4541 
4542  ExFreePoolWithTag(CapturedAcl, TAG_ACL);
4543  }
4544  }
4545  else
4546  {
4547  /* Lock the token */
4549 
4550  /* Clear the default dacl if present */
4551  if (Token->DefaultDacl != NULL)
4552  {
4553  Token->DynamicAvailable += Token->DefaultDacl->AclSize;
4554  RtlZeroMemory(Token->DefaultDacl, Token->DefaultDacl->AclSize);
4555  Token->DefaultDacl = NULL;
4556 
4557  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4558  }
4559 
4560  /* Unlock the token */
4562  }
4563  }
4564  else
4565  {
4567  }
4568  break;
4569  }
4570 
4571  case TokenSessionId:
4572  {
4573  ULONG SessionId = 0;
4574 
4575  _SEH2_TRY
4576  {
4577  /* Buffer size was already verified, no need to check here again */
4578  SessionId = *(PULONG)TokenInformation;
4579  }
4581  {
4583  _SEH2_YIELD(goto Cleanup);
4584  }
4585  _SEH2_END;
4586 
4587  /* Check for TCB privilege */
4589  {
4591  break;
4592  }
4593 
4594  /* Lock the token */
4596 
4597  Token->SessionId = SessionId;
4598  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4599 
4600  /* Unlock the token */
4602 
4603  break;
4604  }
4605 
4606  case TokenSessionReference:
4607  {
4608  ULONG SessionReference;
4609 
4610  _SEH2_TRY
4611  {
4612  /* Buffer size was already verified, no need to check here again */
4613  SessionReference = *(PULONG)TokenInformation;
4614  }
4616  {
4618  _SEH2_YIELD(goto Cleanup);
4619  }
4620  _SEH2_END;
4621 
4622  /* Check for TCB privilege */
4624  {
4626  goto Cleanup;
4627  }
4628 
4629  /* Check if it is 0 */
4630  if (SessionReference == 0)
4631  {
4632  ULONG OldTokenFlags;
4633 
4634  /* Lock the token */
4636 
4637  /* Atomically set the flag in the token */
4638  OldTokenFlags = RtlInterlockedSetBits(&Token->TokenFlags,
4640  /*
4641  * If the flag was already set, do not dereference again
4642  * the logon session. Use SessionReference as an indicator
4643  * to know whether to really dereference the session.
4644  */
4645  if (OldTokenFlags == Token->TokenFlags)
4646  SessionReference = ULONG_MAX;
4647 
4648  /*
4649  * Otherwise if the flag was never set but just for this first time then
4650  * remove the referenced logon session data from the token and dereference
4651  * the logon session when needed.
4652  */
4653  if (SessionReference == 0)
4654  {
4656  SepRmDereferenceLogonSession(&Token->AuthenticationId);
4657  }
4658 
4659  /* Unlock the token */
4661  }
4662  break;
4663  }
4664 
4665  case TokenAuditPolicy:
4666  {
4667  PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation =
4668  (PTOKEN_AUDIT_POLICY_INFORMATION)TokenInformation;
4669  SEP_AUDIT_POLICY AuditPolicy;
4670  ULONG i;
4671 
4672  _SEH2_TRY
4673  {
4674  ProbeForRead(PolicyInformation,
4676  Policies[PolicyInformation->PolicyCount]),
4677  sizeof(ULONG));
4678 
4679  /* Loop all policies in the structure */
4680  for (i = 0; i < PolicyInformation->PolicyCount; i++)
4681  {
4682  /* Set the corresponding bits in the packed structure */
4683  switch (PolicyInformation->Policies[i].Category)
4684  {
4685  case AuditCategorySystem:
4686  AuditPolicy.PolicyElements.System = PolicyInformation->Policies[i].Value;
4687  break;
4688 
4689  case AuditCategoryLogon:
4690  AuditPolicy.PolicyElements.Logon = PolicyInformation->Policies[i].Value;
4691  break;
4692 
4694  AuditPolicy.PolicyElements.ObjectAccess = PolicyInformation->Policies[i].Value;
4695  break;
4696 
4698  AuditPolicy.PolicyElements.PrivilegeUse = PolicyInformation->Policies[i].Value;
4699  break;
4700 
4702  AuditPolicy.PolicyElements.DetailedTracking = PolicyInformation->Policies[i].Value;
4703  break;
4704 
4706  AuditPolicy.PolicyElements.PolicyChange = PolicyInformation->Policies[i].Value;
4707  break;
4708 
4710  AuditPolicy.PolicyElements.AccountManagement = PolicyInformation->Policies[i].Value;
4711  break;
4712 
4714  AuditPolicy.PolicyElements.DirectoryServiceAccess = PolicyInformation->Policies[i].Value;
4715  break;
4716 
4718  AuditPolicy.PolicyElements.AccountLogon = PolicyInformation->Policies[i].Value;
4719  break;
4720  }
4721  }
4722  }
4724  {
4726  _SEH2_YIELD(goto Cleanup);
4727  }
4728  _SEH2_END;
4729 
4730  /* Check for TCB privilege */
4732  {
4734  break;
4735  }
4736 
4737  /* Lock the token */
4739 
4740  /* Set the new audit policy */
4741  Token->AuditPolicy = AuditPolicy;
4742  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4743 
4744  /* Unlock the token */
4746 
4747  break;
4748  }
4749 
4750  case TokenOrigin:
4751  {
4753 
4754  _SEH2_TRY
4755  {
4756  /* Copy the token origin */
4757  TokenOrigin = *(PTOKEN_ORIGIN)TokenInformation;
4758  }
4760  {
4762  _SEH2_YIELD(goto Cleanup);
4763  }
4764  _SEH2_END;
4765 
4766  /* Check for TCB privilege */
4768  {
4770  break;
4771  }
4772 
4773  /* Lock the token */
4775 
4776  /* Check if there is no token origin set yet */
4777  if (RtlIsZeroLuid(&Token->OriginatingLogonSession))
4778  {
4779  /* Set the token origin */
4780  Token->OriginatingLogonSession =
4781  TokenOrigin.OriginatingLogonSession;
4782 
4783  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4784  }
4785 
4786  /* Unlock the token */
4788 
4789  break;
4790  }
4791 
4792  default:
4793  {
4794  DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
4797  break;
4798  }
4799  }
4800 Cleanup:
4802  }
4803 
4804  if (!NT_SUCCESS(Status))
4805  {
4806  DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status);
4807  }
4808 
4809  return Status;
4810 }
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:220
static NTSTATUS SepFindPrimaryGroupAndDefaultOwner(_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
Finds the primary group and default owner entity based on the submitted primary group instance and an...
Definition: token.c:869
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
struct _TOKEN_PRIMARY_GROUP * PTOKEN_PRIMARY_GROUP
_In_ TOKEN_INFORMATION_CLASS _In_ ULONG TokenInformationLength
Definition: sefuncs.h:312
#define TRUE
Definition: types.h:120
USHORT AclSize
Definition: ms-dtyp.idl:296
NTSTATUS NTAPI SepCaptureSid(_In_ PSID InputSid, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID *CapturedSid)
Captures a SID.
Definition: sid.c:314
ULONG SessionId
Definition: dllmain.c:28
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
static __inline NTSTATUS DefaultSetInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, KPROCESSOR_MODE PreviousMode)
Definition: probe.h:8
VOID NTAPI SepReleaseSid(_In_ PSID CapturedSid, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID.
Definition: sid.c:400
_SEH2_TRY
Definition: create.c:4226
NTSTATUS SepRmDereferenceLogonSession(_Inout_ PLUID LogonLuid)
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
struct _TOKEN_DEFAULT_DACL * PTOKEN_DEFAULT_DACL
#define FALSE
Definition: types.h:117
struct _TOKEN_ORIGIN * PTOKEN_ORIGIN
NTSTATUS NTAPI SepCaptureAcl(_In_ PACL InputAcl, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PACL *CapturedAcl)
Captures an access control list from an already valid input ACL.
Definition: acl.c:352
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
PSID Owner
Definition: setypes.h:1006
#define TOKEN_ADJUST_DEFAULT
Definition: setypes.h:910
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
void * PVOID
Definition: retypes.h:9
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
#define RtlIsZeroLuid(_L1)
Definition: rtlfuncs.h:753
SEP_AUDIT_POLICY_CATEGORIES PolicyElements
Definition: setypes.h:158
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _TOKEN_OWNER * PTOKEN_OWNER
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define SepReleaseTokenLock(Token)
Definition: se.h:231
#define TAG_TOKEN_DYNAMIC
Definition: tag.h:153
static const WCHAR Cleanup[]
Definition: register.c:80
NTSTATUS NTAPI SepRmRemoveLogonSessionFromToken(_Inout_ PTOKEN Token)
Removes a logon session from an access token.
Definition: srm.c:449
const LUID SeTcbPrivilege
Definition: priv.c:26
#define TAG_ACL
Definition: tag.h:146
_SEH2_END
Definition: create.c:4400
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
VOID NTAPI ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
Definition: uuid.c:335
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
struct _TOKEN_AUDIT_POLICY_INFORMATION * PTOKEN_AUDIT_POLICY_INFORMATION
#define DPRINT1
Definition: precomp.h:8
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
#define RtlInterlockedSetBits(Flags, Flag)
Definition: rtlfuncs.h:3434
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static const INFORMATION_CLASS_INFO SeTokenInformationClass[]
Definition: token.c:32
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define DPRINT
Definition: sndvol32.h:71
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define TOKEN_ADJUST_SESSIONID
Definition: setypes.h:911
#define TOKEN_SESSION_NOT_REFERENCED
Definition: setypes.h:1162
_In_ TOKEN_INFORMATION_CLASS TokenInformationClass
Definition: sefuncs.h:310
#define ULONG_MAX
Definition: limits.h:44
struct _TOKEN_AUDIT_POLICY_INFORMATION::@1757 Policies[1]
#define PAGED_CODE()

Referenced by SetTokenInformation().

◆ RtlLengthSidAndAttributes()

static ULONG RtlLengthSidAndAttributes ( _In_ ULONG  Count,
_In_ PSID_AND_ATTRIBUTES  Src 
)
static

Computes the length size of a SID.

Parameters
[in]CountTotal count of entries that have SIDs in them (that being PSID_AND_ATTRIBUTES in this context).
[in]SrcSource that points to the attributes and SID entry structure.
Returns
Returns the total length of a SID size.

Definition at line 823 of file token.c.

826 {
827  ULONG i;
828  ULONG uLength;
829 
830  PAGED_CODE();
831 
832  uLength = Count * sizeof(SID_AND_ATTRIBUTES);
833  for (i = 0; i < Count; i++)
834  uLength += RtlLengthSid(Src[i].Sid);
835 
836  return uLength;
837 }
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1103
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
int Count
Definition: noreturn.cpp:7
struct _SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int ULONG
Definition: retypes.h:1
#define PAGED_CODE()

Referenced by NtQueryInformationToken(), SepPerformTokenFiltering(), and SeQueryInformationToken().

◆ SeAssignPrimaryToken()

VOID NTAPI SeAssignPrimaryToken ( _In_ PEPROCESS  Process,
_In_ PTOKEN  Token 
)

Assigns a primary access token to a given process.

Parameters
[in]ProcessProcess where the token is about to be assigned.
[in]TokenThe token to be assigned.
Returns
Nothing.

Definition at line 1613 of file token.c.

1616 {
1617  PAGED_CODE();
1618 
1619  /* Sanity checks */
1620  ASSERT(Token->TokenType == TokenPrimary);
1621  ASSERT(!Token->TokenInUse);
1622 
1623  /* Clean any previous token */
1624  if (Process->Token.Object) SeDeassignPrimaryToken(Process);
1625 
1626  /* Set the new token */
1628  Token->TokenInUse = TRUE;
1630 }
#define TRUE
Definition: types.h:120
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
#define ASSERT(a)
Definition: mode.c:44
VOID FASTCALL ObInitializeFastReference(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:107
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define ObReferenceObject
Definition: obfuncs.h:204
VOID NTAPI SeDeassignPrimaryToken(_Inout_ PEPROCESS Process)
Removes the primary token of a process.
Definition: token.c:794
#define PAGED_CODE()

◆ SeCopyClientToken()

NTSTATUS NTAPI SeCopyClientToken ( _In_ PACCESS_TOKEN  Token,
_In_ SECURITY_IMPERSONATION_LEVEL  Level,
_In_ KPROCESSOR_MODE  PreviousMode,
_Out_ PACCESS_TOKEN NewToken 
)

Copies an existing access token (technically duplicating a new one).

Parameters
[in]TokenToken to copy.
[in]LevelImpersonation security level to assign to the newly copied token.
[in]PreviousModeProcessor request level mode.
[out]NewTokenThe newly copied token.
Returns
Returns STATUS_SUCCESS when token copying has finished successfully. A failure NTSTATUS code is returned otherwise.

Definition at line 1490 of file token.c.

1495 {
1496  NTSTATUS Status;
1498 
1499  PAGED_CODE();
1500 
1502  NULL,
1503  0,
1504  NULL,
1505  NULL);
1506 
1509  FALSE,
1511  Level,
1512  PreviousMode,
1513  (PTOKEN*)NewToken);
1514 
1515  return Status;
1516 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
NTSTATUS NTAPI SepDuplicateToken(_In_ PTOKEN Token, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL Level, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *NewAccessToken)
Duplicates an access token, from an existing valid token.
Definition: token.c:995
#define FALSE
Definition: types.h:117
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define NULL
Definition: types.h:112
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define PAGED_CODE()

Referenced by PsImpersonateClient(), and SepCreateClientSecurity().

◆ SeDeassignPrimaryToken()

VOID NTAPI SeDeassignPrimaryToken ( _Inout_ PEPROCESS  Process)

Removes the primary token of a process.

Parameters
[in,out]ProcessThe process instance with the access token to be removed.
Returns
Nothing.

Definition at line 794 of file token.c.

796 {
797  PTOKEN OldToken;
798 
799  /* Remove the Token */
800  OldToken = ObFastReplaceObject(&Process->Token, NULL);
801 
802  /* Mark the Old Token as free */
803  OldToken->TokenInUse = FALSE;
804 
805  /* Dereference the Token */
806  ObDereferenceObject(OldToken);
807 }
#define FALSE
Definition: types.h:117
PVOID FASTCALL ObFastReplaceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
BOOLEAN TokenInUse
Definition: setypes.h:234
#define ObDereferenceObject
Definition: obfuncs.h:203
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219

Referenced by PspDeleteProcessSecurity(), and SeAssignPrimaryToken().

◆ SeExchangePrimaryToken()

NTSTATUS NTAPI SeExchangePrimaryToken ( _In_ PEPROCESS  Process,
_In_ PACCESS_TOKEN  NewAccessToken,
_Out_ PACCESS_TOKEN OldAccessToken 
)

Replaces the old access token of a process (pointed by the EPROCESS kernel structure) with a new access token. The new access token must be a primary token for use.

Parameters
[in]ProcessThe process instance where its access token is about to be replaced.
[in]NewAccessTokenThe new token that it's going to replace the old one.
[out]OldAccessTokenThe returned old token that's been replaced, which the caller can do anything.
Returns
Returns STATUS_SUCCESS if the exchange operation between tokens has completed successfully. STATUS_BAD_TOKEN_TYPE is returned if the new token is not a primary one so that we cannot exchange it with the old one from the process. STATUS_TOKEN_ALREADY_IN_USE is returned if both tokens aren't equal which means one of them has different properties (groups, privileges, etc.) and as such one of them is currently in use. A failure NTSTATUS code is returned otherwise.

Definition at line 704 of file token.c.

708 {
709  PTOKEN OldToken;
710  PTOKEN NewToken = (PTOKEN)NewAccessToken;
711 
712  PAGED_CODE();
713 
714  if (NewToken->TokenType != TokenPrimary)
715  return STATUS_BAD_TOKEN_TYPE;
716 
717  if (NewToken->TokenInUse)
718  {
721 
722  /* Maybe we're trying to set the same token */
723  OldToken = PsReferencePrimaryToken(Process);
724  if (OldToken == NewToken)
725  {
726  /* So it's a nop. */
727  *OldAccessToken = OldToken;
728  return STATUS_SUCCESS;
729  }
730 
731  Status = SepCompareTokens(OldToken, NewToken, &IsEqual);
732  if (!NT_SUCCESS(Status))
733  {
734  PsDereferencePrimaryToken(OldToken);
735  *OldAccessToken = NULL;
736  return Status;
737  }
738 
739  if (!IsEqual)
740  {
741  PsDereferencePrimaryToken(OldToken);
742  *OldAccessToken = NULL;
744  }
745  /* Silently return STATUS_SUCCESS but do not set the new token,
746  * as it's already in use elsewhere. */
747  *OldAccessToken = OldToken;
748  return STATUS_SUCCESS;
749  }
750 
751  /* Lock the new token */
753 
754  /* Mark new token in use */
755  NewToken->TokenInUse = TRUE;
756 
757  /* Set the session ID for the new token */
758  NewToken->SessionId = MmGetSessionId(Process);
759 
760  /* Unlock the new token */
761  SepReleaseTokenLock(NewToken);
762 
763  /* Reference the new token */
764  ObReferenceObject(NewToken);
765 
766  /* Replace the old with the new */
767  OldToken = ObFastReplaceObject(&Process->Token, NewToken);
768 
769  /* Lock the old token */
771 
772  /* Mark the old token as free */
773  OldToken->TokenInUse = FALSE;
774 
775  /* Unlock the old token */
776  SepReleaseTokenLock(OldToken);
777 
778  *OldAccessToken = (PACCESS_TOKEN)OldToken;
779  return STATUS_SUCCESS;
780 }
TOKEN_TYPE TokenType
Definition: setypes.h:231
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:220
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
PVOID PACCESS_TOKEN
Definition: setypes.h:11
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define STATUS_BAD_TOKEN_TYPE
Definition: ntstatus.h:404
ULONG SessionId
Definition: setypes.h:217
Status
Definition: gdiplustypes.h:24
PVOID FASTCALL ObFastReplaceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN TokenInUse
Definition: setypes.h:234
static NTSTATUS SepCompareTokens(_In_ PTOKEN FirstToken, _In_ PTOKEN SecondToken, _Out_ PBOOLEAN Equal)
Compares tokens if they're equal based on all the following properties. If all of the said conditions...
Definition: token.c:288
#define STATUS_TOKEN_ALREADY_IN_USE
Definition: ntstatus.h:535
#define SepReleaseTokenLock(Token)
Definition: se.h:231
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
struct _TOKEN * PTOKEN
#define NULL
Definition: types.h:112
VOID NTAPI PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
Definition: security.c:902
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define ObReferenceObject
Definition: obfuncs.h:204
ULONG NTAPI MmGetSessionId(IN PEPROCESS Process)
Definition: session.c:179
#define STATUS_SUCCESS
Definition: shellext.h:65
#define PAGED_CODE()

Referenced by PspAssignPrimaryToken().

◆ SeFilterToken()

NTSTATUS NTAPI SeFilterToken ( _In_ PACCESS_TOKEN  ExistingToken,
_In_ ULONG  Flags,
_In_opt_ PTOKEN_GROUPS  SidsToDisable,
_In_opt_ PTOKEN_PRIVILEGES  PrivilegesToDelete,
_In_opt_ PTOKEN_GROUPS  RestrictedSids,
_Out_ PACCESS_TOKEN FilteredToken 
)

Filters an access token from an existing token, making it more restricted than the previous one.

Parameters
[in]ExistingTokenAn existing token for filtering.
[in]FlagsPrivilege flag options. This parameter argument influences how the token is filtered. Such parameter can be 0. See NtFilterToken syscall for more information.
[in]SidsToDisableArray of SIDs to disable. Such parameter can be NULL.
[in]PrivilegesToDeleteArray of privileges to delete. If DISABLE_MAX_PRIVILEGE flag is specified in the Flags parameter, PrivilegesToDelete is ignored.
[in]RestrictedSidsAn array of restricted SIDs for the new filtered token. Such parameter can be NULL.
[out]FilteredTokenThe newly filtered token, returned to the caller.
Returns
Returns STATUS_SUCCESS if the function has successfully completed its operations and that the access token has been filtered. STATUS_INVALID_PARAMETER is returned if one or more of the parameter are not valid. A failure NTSTATUS code is returned otherwise.
Remarks
WARNING – The caller IS RESPONSIBLE for locking the existing access token before attempting to do any kind of filtering operation into the token. The lock MUST BE RELEASED after this kernel routine has finished doing its work.

Definition at line 2947 of file token.c.

2954 {
2955  NTSTATUS Status;
2956  PTOKEN AccessToken;
2957  ULONG PrivilegesCount = 0;
2958  ULONG SidsCount = 0;
2959  ULONG RestrictedSidsCount = 0;
2960  PAGED_CODE();
2961 
2962  /* Begin copying the counters */
2963  if (SidsToDisable != NULL)
2964  {
2965  SidsCount = SidsToDisable->GroupCount;
2966  }
2967 
2968  if (PrivilegesToDelete != NULL)
2969  {
2970  PrivilegesCount = PrivilegesToDelete->PrivilegeCount;
2971  }
2972 
2973  if (RestrictedSids != NULL)
2974  {
2975  RestrictedSidsCount = RestrictedSids->GroupCount;
2976  }
2977 
2978  /* Call the internal API */
2979  Status = SepPerformTokenFiltering(ExistingToken,
2980  PrivilegesToDelete->Privileges,
2981  SidsToDisable->Groups,
2982  RestrictedSids->Groups,
2983  PrivilegesCount,
2984  SidsCount,
2985  RestrictedSidsCount,
2986  Flags,
2987  KernelMode,
2988  &AccessToken);
2989  if (!NT_SUCCESS(Status))
2990  {
2991  DPRINT1("SeFilterToken(): Failed to filter the token (Status 0x%lx)\n", Status);
2992  return Status;
2993  }
2994 
2995  /* Insert the filtered token */
2996  Status = ObInsertObject(AccessToken,
2997  NULL,
2998  0,
2999  0,
3000  NULL,
3001  NULL);
3002  if (!NT_SUCCESS(Status))
3003  {
3004  DPRINT1("SeFilterToken(): Failed to insert the token (Status 0x%lx)\n", Status);
3005  return Status;
3006  }
3007 
3008  /* Give it to the caller */
3009  *FilteredToken = AccessToken;
3010  return Status;
3011 }
LONG NTSTATUS
Definition: precomp.h:26
static NTSTATUS SepPerformTokenFiltering(_In_ PTOKEN Token, _In_opt_ PLUID_AND_ATTRIBUTES PrivilegesToBeDeleted, _In_opt_ PSID_AND_ATTRIBUTES SidsToBeDisabled, _In_opt_ PSID_AND_ATTRIBUTES RestrictedSidsIntoToken, _When_(PrivilegesToBeDeleted !=NULL, _In_) ULONG PrivilegesCount, _When_(SidsToBeDisabled !=NULL, _In_) ULONG RegularGroupsSidCount, _When_(RestrictedSidsIntoToken !=NULL, _In_) ULONG RestrictedSidsCount, _In_ ULONG PrivilegeFlags, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *FilteredToken)
Private helper function responsible for creating a restricted access token, that is,...
Definition: token.c:2040
Status
Definition: gdiplustypes.h:24
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2934
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define PAGED_CODE()

Referenced by FatCreateRestrictEveryoneToken(), and FilterToken().

◆ SeIsTokenChild()

NTSTATUS NTAPI SeIsTokenChild ( _In_ PTOKEN  Token,
_Out_ PBOOLEAN  IsChild 
)

Checks if the token is a child of the other token of the current process that the calling thread is invoking this function.

Parameters
[in]TokenAn access token to determine if it's a child or not.
[out]IsChildThe returned boolean result.
Returns
Returns STATUS_SUCCESS when the function finishes its operation. STATUS_UNSUCCESSFUL is returned if primary token of the current calling process couldn't be referenced otherwise.

Definition at line 1381 of file token.c.

1384 {
1385  PTOKEN ProcessToken;
1386  LUID ProcessTokenId, CallerParentId;
1387 
1388  /* Assume failure */
1389  *IsChild = FALSE;
1390 
1391  /* Reference the process token */
1392  ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
1393  if (!ProcessToken)
1394  return STATUS_UNSUCCESSFUL;
1395 
1396  /* Get its token ID */
1397  ProcessTokenId = ProcessToken->TokenId;
1398 
1399  /* Dereference the token */
1401 
1402  /* Get our parent token ID */
1403  CallerParentId = Token->ParentTokenId;
1404 
1405  /* Compare the token IDs */
1406  if (RtlEqualLuid(&CallerParentId, &ProcessTokenId))
1407  *IsChild = TRUE;
1408 
1409  /* Return success */
1410  return STATUS_SUCCESS;
1411 }
#define TRUE
Definition: types.h:120
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
#define FALSE
Definition: types.h:117
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
LUID TokenId
Definition: setypes.h:210
BOOL WINAPI IsChild(_In_ HWND, _In_ HWND)
VOID FASTCALL ObFastDereferenceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:167
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by PspSetPrimaryToken().

◆ SeIsTokenSibling()

NTSTATUS NTAPI SeIsTokenSibling ( _In_ PTOKEN  Token,
_Out_ PBOOLEAN  IsSibling 
)

Checks if the token is a sibling of the other token of the current process that the calling thread is invoking this function.

Parameters
[in]TokenAn access token to determine if it's a sibling or not.
[out]IsSiblingThe returned boolean result.
Returns
Returns STATUS_SUCCESS when the function finishes its operation. STATUS_UNSUCCESSFUL is returned if primary token of the current calling process couldn't be referenced otherwise.

Definition at line 1430 of file token.c.

1433 {
1434  PTOKEN ProcessToken;
1435  LUID ProcessParentId, ProcessAuthId;
1436  LUID CallerParentId, CallerAuthId;
1437 
1438  /* Assume failure */
1439  *IsSibling = FALSE;
1440 
1441  /* Reference the process token */
1442  ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
1443  if (!ProcessToken)
1444  return STATUS_UNSUCCESSFUL;
1445 
1446  /* Get its parent and authentication IDs */
1447  ProcessParentId = ProcessToken->ParentTokenId;
1448  ProcessAuthId = ProcessToken->AuthenticationId;
1449 
1450  /* Dereference the token */
1452 
1453  /* Get our parent and authentication IDs */
1454  CallerParentId = Token->ParentTokenId;
1455  CallerAuthId = Token->AuthenticationId;
1456 
1457  /* Compare the token IDs */
1458  if (RtlEqualLuid(&CallerParentId, &ProcessParentId) &&
1459  RtlEqualLuid(&CallerAuthId, &ProcessAuthId))
1460  {
1461  *IsSibling = TRUE;
1462  }
1463 
1464  /* Return success */
1465  return STATUS_SUCCESS;
1466 }
#define TRUE
Definition: types.h:120
LUID AuthenticationId
Definition: setypes.h:211
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
#define FALSE
Definition: types.h:117
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
#define PsGetCurrentProcess
Definition: psfuncs.h:17
LUID ParentTokenId
Definition: setypes.h:212
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
VOID FASTCALL ObFastDereferenceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:167
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by PspSetPrimaryToken().

◆ SepAdjustGroups()

static NTSTATUS SepAdjustGroups ( _In_ PTOKEN  Token,
_In_opt_ PSID_AND_ATTRIBUTES  NewState,
_In_ ULONG  NewStateCount,
_In_ BOOLEAN  ApplyChanges,
_In_ BOOLEAN  ResetToDefaultStates,
_Out_ PBOOLEAN  ChangesMade,
_Out_opt_ PTOKEN_GROUPS  PreviousGroupsState,
_Out_ PULONG  ChangedGroups 
)
static

Private routine that iterates over the groups of an access token to be adjusted as per on request by the caller, where a group can be enabled or disabled.

Parameters
[in]TokenAccess token where its groups are to be enabled or disabled.
[in]NewStateA list of groups with new state attributes to be assigned to the token.
[in]NewStateCountThe captured count number of groups in the list.
[in]ApplyChangesIf set to FALSE, the function will only iterate over the token's groups without performing any kind of modification. If set to TRUE, the changes will be applied immediately when the function has done looping the groups.
[in]ResetToDefaultStatesThe function will reset the groups in an access token to default states if set to TRUE. In such scenario the function ignores NewState outright. Otherwise if set to FALSE, the function will use NewState to assign the newly attributes to adjust the token's groups. SE_GROUP_ENABLED_BY_DEFAULT is a flag indicator that is used for such purpose.
[out]ChangesMadeReturns TRUE if changes to token's groups have been made, otherwise FALSE is returned. Bear in mind such changes aren't always deterministic. See remarks for further details.
[out]PreviousGroupsStateIf requested by the caller, the function will return the previous state of groups in an access token prior taking action on adjusting the token. This is a UM (user mode) pointer and it's prone to raise exceptions if such pointer address is not valid.
[out]ChangedGroupsReturns the total number of changed groups in an access token. This argument could also indicate the number of groups to be changed if the calling thread hasn't chosen to apply the changes yet. A number of 0 indicates no groups have been or to be changed because the groups' attributes in a token are the same as the ones from NewState given by the caller.
Returns
STATUS_SUCCESS is returned if the function has successfully completed the operation of adjusting groups in a token. STATUS_CANT_DISABLE_MANDATORY is returned if there was an attempt to disable a mandatory group which is not possible. STATUS_CANT_ENABLE_DENY_ONLY is returned if there was an attempt to enable a "use for Deny only" group which is not allowed, that is, a restricted group. STATUS_NOT_ALL_ASSIGNED is returned if not all the groups are actually assigned to the token.
Remarks
Token groups adjusting can be judged to be deterministic or not based on the NT status code value. That is, STATUS_SUCCESS indicates the function not only has iterated over the whole groups in a token, it also has applied the changes thoroughly without impediment and the results perfectly match with the request desired by the caller. In this situation the condition is deemed deterministic. In a different situation however, if the status code was STATUS_NOT_ALL_ASSIGNED, the function would still continue looping the groups in a token and apply the changes whenever possible where the respective groups actually exist in the token. This kind of situation is deemed as indeterministic. For STATUS_CANT_DISABLE_MANDATORY and STATUS_CANT_ENABLE_DENY_ONLY the scenario is even more indeterministic as the iteration of groups comes to a halt thus leaving all other possible groups to be adjusted.

Definition at line 5068 of file token.c.

5077 {
5078  ULONG GroupsInToken, GroupsInList;
5079  ULONG ChangeCount, GroupsCount, NewAttributes;
5080 
5081  PAGED_CODE();
5082 
5083  /* Ensure that the token we get is not plain garbage */
5084  ASSERT(Token);
5085 
5086  /* Initialize the counters and begin the work */
5087  *ChangesMade = FALSE;
5088  GroupsCount = 0;
5089  ChangeCount = 0;
5090 
5091  /* Begin looping all the groups in the token */
5092  for (GroupsInToken = 0; GroupsInToken < Token->UserAndGroupCount; GroupsInToken++)
5093  {
5094  /* Does the caller want to reset groups to default states? */
5095  if (ResetToDefaultStates)
5096  {
5097  /*
5098  * SE_GROUP_ENABLED_BY_DEFAULT is a special indicator that informs us
5099  * if a certain group has been enabled by default or not. In case
5100  * a group is enabled by default but it is not currently enabled then
5101  * at that point we must enable it back by default. For now just
5102  * assign the respective SE_GROUP_ENABLED attribute as we'll do the
5103  * eventual work later.
5104  */
5105  if ((Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_ENABLED_BY_DEFAULT) &&
5106  (Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_ENABLED) == 0)
5107  {
5108  NewAttributes = Token->UserAndGroups[GroupsInToken].Attributes |= SE_GROUP_ENABLED;
5109  }
5110 
5111  /*
5112  * Unlike the case above, a group that hasn't been enabled by
5113  * default but it's currently enabled then we must disable
5114  * it back.
5115  */
5116  if ((Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_ENABLED_BY_DEFAULT) == 0 &&
5117  (Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_ENABLED))
5118  {
5119  NewAttributes = Token->UserAndGroups[GroupsInToken].Attributes & ~SE_GROUP_ENABLED;
5120  }
5121  }
5122  else
5123  {
5124  /* Loop the provided groups in the list then */
5125  for (GroupsInList = 0; GroupsInList < NewStateCount; GroupsInList++)
5126  {
5127  /* Does this group exist in the token? */
5128  if (RtlEqualSid(&Token->UserAndGroups[GroupsInToken].Sid,
5129  &NewState[GroupsInList].Sid))
5130  {
5131  /*
5132  * This is the group that we're looking for.
5133  * However, it could be that the group is a
5134  * mandatory group which we are not allowed
5135  * and cannot disable it.
5136  */
5137  if ((Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_MANDATORY) &&
5138  (NewState[GroupsInList].Attributes & SE_GROUP_ENABLED) == 0)
5139  {
5140  /* It is mandatory, forget about this group */
5141  DPRINT1("SepAdjustGroups(): The SID group is mandatory!\n");
5143  }
5144 
5145  /*
5146  * We've to ensure that apart the group mustn't be
5147  * mandatory, it mustn't be a restricted group as
5148  * well. That is, the group is marked with
5149  * SE_GROUP_USE_FOR_DENY_ONLY flag and no one
5150  * can enable it because it's for "deny" use only.
5151  */
5152  if ((Token->UserAnd