ReactOS  0.4.15-dev-3297-g037c744
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...
 
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)
 Opens a token that is tied to a thread handle. 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 4556 of file token.c.

4564 {
4565  PTOKEN Token;
4566  NTSTATUS Status;
4568  ULONG ChangeCount, RequiredLength;
4569  ULONG CapturedCount = 0;
4570  ULONG CapturedLength = 0;
4571  ULONG NewStateSize = 0;
4572  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
4573  BOOLEAN ChangesMade = FALSE;
4574  BOOLEAN LockAndReferenceAcquired = FALSE;
4575 
4576  PAGED_CODE();
4577 
4578  /*
4579  * If the caller doesn't want to reset the groups of an
4580  * access token to default states then at least we must
4581  * expect a list of groups to be adjusted based on NewState
4582  * parameter. Otherwise bail out because the caller has
4583  * no idea what they're doing.
4584  */
4585  if (!ResetToDefault && !NewState)
4586  {
4587  DPRINT1("NtAdjustGroupsToken(): The caller hasn't provided any list of groups to adjust!\n");
4588  return STATUS_INVALID_PARAMETER;
4589  }
4590 
4592 
4593  if (PreviousMode != KernelMode)
4594  {
4595  _SEH2_TRY
4596  {
4597  /* Probe NewState */
4598  if (!ResetToDefault)
4599  {
4600  /* Probe the header */
4601  ProbeForRead(NewState, sizeof(*NewState), sizeof(ULONG));
4602 
4603  CapturedCount = NewState->GroupCount;
4604  NewStateSize = FIELD_OFFSET(TOKEN_GROUPS, Groups[CapturedCount]);
4605 
4606  ProbeForRead(NewState, NewStateSize, sizeof(ULONG));
4607  }
4608 
4609  if (PreviousState != NULL)
4610  {
4612  ProbeForWrite(ReturnLength, sizeof(*ReturnLength), sizeof(ULONG));
4613  }
4614  }
4616  {
4617  /* Return the exception code */
4619  }
4620  _SEH2_END;
4621  }
4622  else
4623  {
4624  /*
4625  * We're calling directly from the kernel, just retrieve
4626  * the number count of captured groups outright.
4627  */
4628  if (!ResetToDefault)
4629  {
4630  CapturedCount = NewState->GroupCount;
4631  }
4632  }
4633 
4634  /* Time to capture the NewState list */
4635  if (!ResetToDefault)
4636  {
4637  _SEH2_TRY
4638  {
4639  Status = SeCaptureSidAndAttributesArray(NewState->Groups,
4640  CapturedCount,
4641  PreviousMode,
4642  NULL,
4643  0,
4644  PagedPool,
4645  TRUE,
4646  &CapturedGroups,
4647  &CapturedLength);
4648  }
4650  {
4652  }
4653  _SEH2_END;
4654 
4655  if (!NT_SUCCESS(Status))
4656  {
4657  DPRINT1("NtAdjustGroupsToken(): Failed to capture the NewState list of groups (Status 0x%lx)\n", Status);
4658  return Status;
4659  }
4660  }
4661 
4662  /* Time to reference the token */
4666  PreviousMode,
4667  (PVOID*)&Token,
4668  NULL);
4669  if (!NT_SUCCESS(Status))
4670  {
4671  /* We couldn't reference the access token, bail out */
4672  DPRINT1("NtAdjustGroupsToken(): Failed to reference the token (Status 0x%lx)\n", Status);
4673 
4674  if (CapturedGroups != NULL)
4675  {
4676  SeReleaseSidAndAttributesArray(CapturedGroups,
4677  PreviousMode,
4678  TRUE);
4679  }
4680 
4681  goto Quit;
4682  }
4683 
4684  /* Lock the token */
4686  LockAndReferenceAcquired = TRUE;
4687 
4688  /* Count the number of groups to be changed */
4690  CapturedGroups,
4691  CapturedCount,
4692  FALSE,
4693  ResetToDefault,
4694  &ChangesMade,
4695  NULL,
4696  &ChangeCount);
4697 
4698  /* Does the caller want the previous state of groups? */
4699  if (PreviousState != NULL)
4700  {
4701  /* Calculate the required length */
4703 
4704  /* Return the required length to the caller */
4705  _SEH2_TRY
4706  {
4708  }
4710  {
4711  /* Bail out and return the exception code */
4713  _SEH2_YIELD(goto Quit);
4714  }
4715  _SEH2_END;
4716 
4717  /* The buffer length provided is smaller than the required length, bail out */
4719  {
4721  goto Quit;
4722  }
4723  }
4724 
4725  /*
4726  * Now it's time to apply changes. Wrap the code
4727  * in SEH as we are returning the old groups state
4728  * list to the caller since PreviousState is a
4729  * UM pointer.
4730  */
4731  _SEH2_TRY
4732  {
4734  CapturedGroups,
4735  CapturedCount,
4736  TRUE,
4737  ResetToDefault,
4738  &ChangesMade,
4739  PreviousState,
4740  &ChangeCount);
4741  }
4743  {
4744  /* Bail out and return the exception code */
4746 
4747  /* Force the write as we touched the token still */
4748  ChangesMade = TRUE;
4749  _SEH2_YIELD(goto Quit);
4750  }
4751  _SEH2_END;
4752 
4753 Quit:
4754  /* Allocate a new ID for the token as we made changes */
4755  if (ChangesMade)
4756  {
4757  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4758  }
4759 
4760  /* Have we successfully acquired the lock and referenced the token before? */
4761  if (LockAndReferenceAcquired)
4762  {
4763  /* Unlock and dereference the token */
4766  }
4767 
4768  /* Release the captured groups */
4769  if (CapturedGroups != NULL)
4770  {
4771  SeReleaseSidAndAttributesArray(CapturedGroups,
4772  PreviousMode,
4773  TRUE);
4774  }
4775 
4776  return Status;
4777 }
#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:676
#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:3070
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:896
#define TOKEN_QUERY
Definition: setypes.h:893
#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:458
_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:4348
#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 4975 of file token.c.

4983 {
4984  NTSTATUS Status;
4986  PTOKEN Token;
4987  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
4988  ULONG CapturedCount = 0;
4989  ULONG CapturedLength = 0;
4990  ULONG NewStateSize = 0;
4991  ULONG ChangeCount;
4993  BOOLEAN ChangesMade = FALSE;
4994 
4995  PAGED_CODE();
4996 
4997  DPRINT("NtAdjustPrivilegesToken() called\n");
4998 
4999  /* Fail, if we do not disable all privileges but NewState is NULL */
5000  if (DisableAllPrivileges == FALSE && NewState == NULL)
5001  return STATUS_INVALID_PARAMETER;
5002 
5004  if (PreviousMode != KernelMode)
5005  {
5006  _SEH2_TRY
5007  {
5008  /* Probe NewState */
5009  if (DisableAllPrivileges == FALSE)
5010  {
5011  /* First probe the header */
5012  ProbeForRead(NewState, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG));
5013 
5014  CapturedCount = NewState->PrivilegeCount;
5015  NewStateSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedCount]);
5016 
5017  ProbeForRead(NewState, NewStateSize, sizeof(ULONG));
5018  }
5019 
5020  /* Probe PreviousState and ReturnLength */
5021  if (PreviousState != NULL)
5022  {
5024  ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
5025  }
5026  }
5028  {
5029  /* Return the exception code */
5031  }
5032  _SEH2_END;
5033  }
5034  else
5035  {
5036  /* This is kernel mode, we trust the caller */
5037  if (DisableAllPrivileges == FALSE)
5038  CapturedCount = NewState->PrivilegeCount;
5039  }
5040 
5041  /* Do we need to capture the new state? */
5042  if (DisableAllPrivileges == FALSE)
5043  {
5044  _SEH2_TRY
5045  {
5046  /* Capture the new state array of privileges */
5047  Status = SeCaptureLuidAndAttributesArray(NewState->Privileges,
5048  CapturedCount,
5049  PreviousMode,
5050  NULL,
5051  0,
5052  PagedPool,
5053  TRUE,
5054  &CapturedPrivileges,
5055  &CapturedLength);
5056  }
5058  {
5059  /* Return the exception code */
5061  }
5062  _SEH2_END;
5063 
5064  if (!NT_SUCCESS(Status))
5065  return Status;
5066  }
5067 
5068  /* Reference the token */
5072  PreviousMode,
5073  (PVOID*)&Token,
5074  NULL);
5075  if (!NT_SUCCESS(Status))
5076  {
5077  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
5078 
5079  /* Release the captured privileges */
5080  if (CapturedPrivileges != NULL)
5081  {
5082  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
5083  PreviousMode,
5084  TRUE);
5085  }
5086 
5087  return Status;
5088  }
5089 
5090  /* Lock the token */
5092 
5093  /* Count the privileges that need to be changed, do not apply them yet */
5095  DisableAllPrivileges,
5096  CapturedPrivileges,
5097  CapturedCount,
5098  NULL,
5099  FALSE,
5100  &ChangeCount,
5101  &ChangesMade);
5102 
5103  /* Check if the caller asked for the previous state */
5104  if (PreviousState != NULL)
5105  {
5106  /* Calculate the required length */
5108 
5109  /* Try to return the required buffer length */
5110  _SEH2_TRY
5111  {
5113  }
5115  {
5116  /* Do cleanup and return the exception code */
5118  _SEH2_YIELD(goto Cleanup);
5119  }
5120  _SEH2_END;
5121 
5122  /* Fail, if the buffer length is smaller than the required length */
5124  {
5126  goto Cleanup;
5127  }
5128  }
5129 
5130  /* Now enter SEH, since we might return the old privileges */
5131  _SEH2_TRY
5132  {
5133  /* This time apply the changes */
5135  DisableAllPrivileges,
5136  CapturedPrivileges,
5137  CapturedCount,
5138  PreviousState,
5139  TRUE,
5140  &ChangeCount,
5141  &ChangesMade);
5142  }
5144  {
5145  /* Do cleanup and return the exception code */
5147  ChangesMade = TRUE; // Force write.
5148  _SEH2_YIELD(goto Cleanup);
5149  }
5150  _SEH2_END;
5151 
5152 Cleanup:
5153  /* Touch the token if we made changes */
5154  if (ChangesMade)
5155  ExAllocateLocallyUniqueId(&Token->ModifiedId);
5156 
5157  /* Unlock and dereference the token */
5160 
5161  /* Release the captured privileges */
5162  if (CapturedPrivileges != NULL)
5163  {
5164  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
5165  PreviousMode,
5166  TRUE);
5167  }
5168 
5169  DPRINT ("NtAdjustPrivilegesToken() done\n");
5170  return Status;
5171 }
#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:4818
#define TOKEN_QUERY
Definition: setypes.h:893
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:895
_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 5754 of file token.c.

5758 {
5760  PTOKEN FirstToken, SecondToken;
5761  BOOLEAN IsEqual;
5762  NTSTATUS Status;
5763 
5764  PAGED_CODE();
5765 
5767 
5768  if (PreviousMode != KernelMode)
5769  {
5770  _SEH2_TRY
5771  {
5772  ProbeForWriteBoolean(Equal);
5773  }
5775  {
5776  /* Return the exception code */
5778  }
5779  _SEH2_END;
5780  }
5781 
5782  Status = ObReferenceObjectByHandle(FirstTokenHandle,
5783  TOKEN_QUERY,
5785  PreviousMode,
5786  (PVOID*)&FirstToken,
5787  NULL);
5788  if (!NT_SUCCESS(Status))
5789  {
5790  DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
5791  return Status;
5792  }
5793 
5794  Status = ObReferenceObjectByHandle(SecondTokenHandle,
5795  TOKEN_QUERY,
5797  PreviousMode,
5798  (PVOID*)&SecondToken,
5799  NULL);
5800  if (!NT_SUCCESS(Status))
5801  {
5802  DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
5803  ObDereferenceObject(FirstToken);
5804  return Status;
5805  }
5806 
5807  if (FirstToken != SecondToken)
5808  {
5809  Status = SepCompareTokens(FirstToken,
5810  SecondToken,
5811  &IsEqual);
5812  }
5813  else
5814  {
5815  IsEqual = TRUE;
5816  }
5817 
5818  ObDereferenceObject(SecondToken);
5819  ObDereferenceObject(FirstToken);
5820 
5821  if (NT_SUCCESS(Status))
5822  {
5823  _SEH2_TRY
5824  {
5825  *Equal = IsEqual;
5826  }
5828  {
5830  }
5831  _SEH2_END;
5832  }
5833 
5834  return Status;
5835 }
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3070
_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:893
#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:351
#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 5224 of file token.c.

5238 {
5239  HANDLE hToken;
5241  ULONG PrivilegeCount, GroupCount;
5242  PSID OwnerSid, PrimaryGroupSid;
5243  PACL DefaultDacl;
5244  LARGE_INTEGER LocalExpirationTime = {{0, 0}};
5245  LUID LocalAuthenticationId;
5246  TOKEN_SOURCE LocalTokenSource;
5247  SECURITY_QUALITY_OF_SERVICE LocalSecurityQos;
5248  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
5249  PSID_AND_ATTRIBUTES CapturedUser = NULL;
5250  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
5251  PSID CapturedOwnerSid = NULL;
5252  PSID CapturedPrimaryGroupSid = NULL;
5253  PACL CapturedDefaultDacl = NULL;
5254  ULONG PrivilegesLength, UserLength, GroupsLength;
5255  NTSTATUS Status;
5256 
5257  PAGED_CODE();
5258 
5260 
5261  if (PreviousMode != KernelMode)
5262  {
5263  _SEH2_TRY
5264  {
5266 
5267  if (ObjectAttributes != NULL)
5268  {
5270  sizeof(OBJECT_ATTRIBUTES),
5271  sizeof(ULONG));
5272  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
5273  }
5274 
5275  ProbeForRead(AuthenticationId,
5276  sizeof(LUID),
5277  sizeof(ULONG));
5278  LocalAuthenticationId = *AuthenticationId;
5279 
5280  LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
5281 
5283  sizeof(TOKEN_USER),
5284  sizeof(ULONG));
5285 
5287  sizeof(TOKEN_GROUPS),
5288  sizeof(ULONG));
5289  GroupCount = TokenGroups->GroupCount;
5290 
5292  sizeof(TOKEN_PRIVILEGES),
5293  sizeof(ULONG));
5294  PrivilegeCount = TokenPrivileges->PrivilegeCount;
5295 
5296  if (TokenOwner != NULL)
5297  {
5299  sizeof(TOKEN_OWNER),
5300  sizeof(ULONG));
5301  OwnerSid = TokenOwner->Owner;
5302  }
5303  else
5304  {
5305  OwnerSid = NULL;
5306  }
5307 
5309  sizeof(TOKEN_PRIMARY_GROUP),
5310  sizeof(ULONG));
5311  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
5312 
5313  if (TokenDefaultDacl != NULL)
5314  {
5316  sizeof(TOKEN_DEFAULT_DACL),
5317  sizeof(ULONG));
5318  DefaultDacl = TokenDefaultDacl->DefaultDacl;
5319  }
5320  else
5321  {
5322  DefaultDacl = NULL;
5323  }
5324 
5326  sizeof(TOKEN_SOURCE),
5327  sizeof(ULONG));
5328  LocalTokenSource = *TokenSource;
5329  }
5331  {
5332  /* Return the exception code */
5334  }
5335  _SEH2_END;
5336  }
5337  else
5338  {
5339  if (ObjectAttributes != NULL)
5340  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
5341  LocalAuthenticationId = *AuthenticationId;
5342  LocalExpirationTime = *ExpirationTime;
5343  GroupCount = TokenGroups->GroupCount;
5344  PrivilegeCount = TokenPrivileges->PrivilegeCount;
5345  OwnerSid = TokenOwner ? TokenOwner->Owner : NULL;
5346  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
5347  DefaultDacl = TokenDefaultDacl ? TokenDefaultDacl->DefaultDacl : NULL;
5348  LocalTokenSource = *TokenSource;
5349  }
5350 
5351  /* Check token type */
5352  if ((TokenType < TokenPrimary) ||
5354  {
5355  return STATUS_BAD_TOKEN_TYPE;
5356  }
5357 
5358  /* Check for token creation privilege */
5360  {
5362  }
5363 
5364  /* Capture the user SID and attributes */
5366  1,
5367  PreviousMode,
5368  NULL,
5369  0,
5370  PagedPool,
5371  FALSE,
5372  &CapturedUser,
5373  &UserLength);
5374  if (!NT_SUCCESS(Status))
5375  {
5376  goto Cleanup;
5377  }
5378 
5379  /* Capture the groups SID and attributes array */
5381  GroupCount,
5382  PreviousMode,
5383  NULL,
5384  0,
5385  PagedPool,
5386  FALSE,
5387  &CapturedGroups,
5388  &GroupsLength);
5389  if (!NT_SUCCESS(Status))
5390  {
5391  goto Cleanup;
5392  }
5393 
5394  /* Capture privileges */
5396  PrivilegeCount,
5397  PreviousMode,
5398  NULL,
5399  0,
5400  PagedPool,
5401  FALSE,
5402  &CapturedPrivileges,
5403  &PrivilegesLength);
5404  if (!NT_SUCCESS(Status))
5405  {
5406  goto Cleanup;
5407  }
5408 
5409  /* Capture the token owner SID */
5410  if (TokenOwner != NULL)
5411  {
5412  Status = SepCaptureSid(OwnerSid,
5413  PreviousMode,
5414  PagedPool,
5415  FALSE,
5416  &CapturedOwnerSid);
5417  if (!NT_SUCCESS(Status))
5418  {
5419  goto Cleanup;
5420  }
5421  }
5422 
5423  /* Capture the token primary group SID */
5424  Status = SepCaptureSid(PrimaryGroupSid,
5425  PreviousMode,
5426  PagedPool,
5427  FALSE,
5428  &CapturedPrimaryGroupSid);
5429  if (!NT_SUCCESS(Status))
5430  {
5431  goto Cleanup;
5432  }
5433 
5434  /* Capture DefaultDacl */
5435  if (DefaultDacl != NULL)
5436  {
5437  Status = SepCaptureAcl(DefaultDacl,
5438  PreviousMode,
5439  NonPagedPool,
5440  FALSE,
5441  &CapturedDefaultDacl);
5442  if (!NT_SUCCESS(Status))
5443  {
5444  goto Cleanup;
5445  }
5446  }
5447 
5448  /* Call the internal function */
5449  Status = SepCreateToken(&hToken,
5450  PreviousMode,
5451  DesiredAccess,
5453  TokenType,
5454  LocalSecurityQos.ImpersonationLevel,
5455  &LocalAuthenticationId,
5456  &LocalExpirationTime,
5457  CapturedUser,
5458  GroupCount,
5459  CapturedGroups,
5460  GroupsLength,
5461  PrivilegeCount,
5462  CapturedPrivileges,
5463  CapturedOwnerSid,
5464  CapturedPrimaryGroupSid,
5465  CapturedDefaultDacl,
5466  &LocalTokenSource,
5467  FALSE);
5468  if (NT_SUCCESS(Status))
5469  {
5470  _SEH2_TRY
5471  {
5472  *TokenHandle = hToken;
5473  }
5475  {
5477  }
5478  _SEH2_END;
5479  }
5480 
5481 Cleanup:
5482 
5483  /* Release what we captured */
5486  SeReleaseLuidAndAttributesArray(CapturedPrivileges, PreviousMode, FALSE);
5487  SepReleaseSid(CapturedOwnerSid, PreviousMode, FALSE);
5488  SepReleaseSid(CapturedPrimaryGroupSid, PreviousMode, FALSE);
5489  SepReleaseAcl(CapturedDefaultDacl, PreviousMode, FALSE);
5490 
5491  return Status;
5492 }
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:676
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:308
LONG NTSTATUS
Definition: precomp.h:26
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3070
VOID NTAPI SepReleaseSid(_In_ PSID CapturedSid, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID.
Definition: sid.c:394
_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:1700
_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:458
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:388
#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 4133 of file token.c.

4140 {
4142  HANDLE hToken;
4143  PTOKEN Token;
4144  PTOKEN NewToken;
4145  PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
4146  BOOLEAN QoSPresent;
4148  NTSTATUS Status;
4149 
4150  PAGED_CODE();
4151 
4152  if (TokenType != TokenImpersonation &&
4154  {
4155  return STATUS_INVALID_PARAMETER;
4156  }
4157 
4159 
4160  if (PreviousMode != KernelMode)
4161  {
4162  _SEH2_TRY
4163  {
4165  }
4167  {
4168  /* Return the exception code */
4170  }
4171  _SEH2_END;
4172  }
4173 
4175  PreviousMode,
4176  PagedPool,
4177  FALSE,
4178  &CapturedSecurityQualityOfService,
4179  &QoSPresent);
4180  if (!NT_SUCCESS(Status))
4181  {
4182  DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
4183  return Status;
4184  }
4185 
4186  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
4189  PreviousMode,
4190  (PVOID*)&Token,
4192  if (!NT_SUCCESS(Status))
4193  {
4194  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
4195  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
4196  PreviousMode,
4197  FALSE);
4198  return Status;
4199  }
4200 
4201  /*
4202  * Fail, if the original token is an impersonation token and the caller
4203  * tries to raise the impersonation level of the new token above the
4204  * impersonation level of the original token.
4205  */
4206  if (Token->TokenType == TokenImpersonation)
4207  {
4208  if (QoSPresent &&
4209  CapturedSecurityQualityOfService->ImpersonationLevel >Token->ImpersonationLevel)
4210  {
4212  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
4213  PreviousMode,
4214  FALSE);
4216  }
4217  }
4218 
4219  /*
4220  * Fail, if a primary token is to be created from an impersonation token
4221  * and and the impersonation level of the impersonation token is below SecurityImpersonation.
4222  */
4223  if (Token->TokenType == TokenImpersonation &&
4224  TokenType == TokenPrimary &&
4225  Token->ImpersonationLevel < SecurityImpersonation)
4226  {
4228  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
4229  PreviousMode,
4230  FALSE);
4232  }
4233 
4236  EffectiveOnly,
4237  TokenType,
4238  (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
4239  PreviousMode,
4240  &NewToken);
4241 
4243 
4244  if (NT_SUCCESS(Status))
4245  {
4246  Status = ObInsertObject(NewToken,
4247  NULL,
4248  (DesiredAccess ? DesiredAccess : HandleInformation.GrantedAccess),
4249  0,
4250  NULL,
4251  &hToken);
4252  if (NT_SUCCESS(Status))
4253  {
4254  _SEH2_TRY
4255  {
4256  *NewTokenHandle = hToken;
4257  }
4259  {
4261  }
4262  _SEH2_END;
4263  }
4264  }
4265 
4266  /* Free the captured structure */
4267  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
4268  PreviousMode,
4269  FALSE);
4270 
4271  return Status;
4272 }
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:388
#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:891
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:2931
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:388
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:388
#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 
)

Opens a token that is tied to a thread handle.

@unimplemented

Parameters
[in]ExistingTokenHandleAn existing token for filtering.
[in]FlagsPrivilege flag options. This parameter argument influences how the token is filtered. Such parameter can be 0.
[in]SidsToDisableArray of SIDs to disable.
[in]PrivilegesToDeleteArray of privileges to delete.
[in]RestrictedSidsAn array of restricted SIDs for the new filtered token.
[out]NewTokenHandleThe newly filtered token, returned to the caller.
Returns
To be added...

Definition at line 5866 of file token.c.

5873 {
5874  UNIMPLEMENTED;
5875  return STATUS_NOT_IMPLEMENTED;
5876 }
return STATUS_NOT_IMPLEMENTED
#define UNIMPLEMENTED
Definition: debug.h:115

◆ 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 5904 of file token.c.

5906 {
5907  PETHREAD Thread;
5909  NTSTATUS Status;
5910  PAGED_CODE();
5911 
5913 
5914  /* Obtain the thread object from the handle */
5915  Status = ObReferenceObjectByHandle(ThreadHandle,
5917  PsThreadType,
5918  PreviousMode,
5919  (PVOID*)&Thread,
5920  NULL);
5921  if (!NT_SUCCESS(Status))
5922  {
5923  DPRINT1("NtImpersonateAnonymousToken(): Failed to reference the object (Status 0x%lx)\n", Status);
5924  return Status;
5925  }
5926 
5927  /* Call the private routine to impersonate the token */
5929  if (!NT_SUCCESS(Status))
5930  {
5931  DPRINT1("NtImpersonateAnonymousToken(): Failed to impersonate the token (Status 0x%lx)\n", Status);
5932  }
5933 
5935  return Status;
5936 }
#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:3070
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 5725 of file token.c.

5730 {
5731  return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
5732  TokenHandle);
5733 }
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:5523
_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 5523 of file token.c.

5529 {
5530  PETHREAD Thread;
5531  HANDLE hToken;
5532  PTOKEN Token, NewToken = NULL, PrimaryToken;
5538  PACL Dacl = NULL;
5540  NTSTATUS Status;
5541  BOOLEAN RestoreImpersonation = FALSE;
5542 
5543  PAGED_CODE();
5544 
5546 
5547  if (PreviousMode != KernelMode)
5548  {
5549  _SEH2_TRY
5550  {
5552  }
5554  {
5555  /* Return the exception code */
5557  }
5558  _SEH2_END;
5559  }
5560 
5561  /* Validate object attributes */
5563 
5564  /*
5565  * At first open the thread token for information access and verify
5566  * that the token associated with thread is valid.
5567  */
5568 
5571  NULL);
5572  if (!NT_SUCCESS(Status))
5573  {
5574  return Status;
5575  }
5576 
5579  if (Token == NULL)
5580  {
5582  return STATUS_NO_TOKEN;
5583  }
5584 
5586  {
5590  }
5591 
5592  /*
5593  * Revert to self if OpenAsSelf is specified.
5594  */
5595 
5596  if (OpenAsSelf)
5597  {
5598  RestoreImpersonation = PsDisableImpersonation(PsGetCurrentThread(),
5600  }
5601 
5602  if (CopyOnOpen)
5603  {
5604  PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
5605 
5606  Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
5607 
5608  ObFastDereferenceObject(&Thread->ThreadsProcess->Token, PrimaryToken);
5609 
5610  if (NT_SUCCESS(Status))
5611  {
5612  if (Dacl)
5613  {
5616  if (!NT_SUCCESS(Status))
5617  {
5618  DPRINT1("NtOpenThreadTokenEx(): Failed to create a security descriptor (Status 0x%lx)\n", Status);
5619  }
5620 
5622  FALSE);
5623  if (!NT_SUCCESS(Status))
5624  {
5625  DPRINT1("NtOpenThreadTokenEx(): Failed to set a DACL to the security descriptor (Status 0x%lx)\n", Status);
5626  }
5627  }
5628 
5631 
5634  KernelMode, &NewToken);
5635  if (!NT_SUCCESS(Status))
5636  {
5637  DPRINT1("NtOpenThreadTokenEx(): Failed to duplicate the token (Status 0x%lx)\n");
5638  }
5639 
5640  ObReferenceObject(NewToken);
5641  Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
5642  &hToken);
5643  if (!NT_SUCCESS(Status))
5644  {
5645  DPRINT1("NtOpenThreadTokenEx(): Failed to insert the token object (Status 0x%lx)\n", Status);
5646  }
5647  }
5648  else
5649  {
5650  DPRINT1("NtOpenThreadTokenEx(): Failed to impersonate token from DACL (Status 0x%lx)\n", Status);
5651  }
5652  }
5653  else
5654  {
5657  PreviousMode, &hToken);
5658  if (!NT_SUCCESS(Status))
5659  {
5660  DPRINT1("NtOpenThreadTokenEx(): Failed to open the object (Status 0x%lx)\n", Status);
5661  }
5662  }
5663 
5665 
5666  if (RestoreImpersonation)
5667  {
5669  }
5670 
5672 
5673  if (NT_SUCCESS(Status) && CopyOnOpen)
5674  {
5676  if (!NT_SUCCESS(Status))
5677  {
5678  DPRINT1("NtOpenThreadTokenEx(): Failed to impersonate the client (Status 0x%lx)\n");
5679  }
5680  }
5681 
5682  if (NewToken) ObDereferenceObject(NewToken);
5683 
5685 
5686  if (NT_SUCCESS(Status))
5687  {
5688  _SEH2_TRY
5689  {
5690  *TokenHandle = hToken;
5691  }
5693  {
5695  }
5696  _SEH2_END;
5697  }
5698 
5699  return Status;
5700 }
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:3070
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:2738
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:174
_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:2931
#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:388
#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 2972 of file token.c.

2979 {
2980  NTSTATUS Status;
2982  PTOKEN Token;
2984  union
2985  {
2986  PSID PSid;
2987  ULONG Ulong;
2988  } Unused;
2989 
2990  PAGED_CODE();
2991 
2993 
2994  /* Check buffers and class validity */
2998  TokenInformation,
3000  ReturnLength,
3001  NULL,
3002  PreviousMode,
3003  TRUE);
3004  if (!NT_SUCCESS(Status))
3005  {
3006  DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
3007  return Status;
3008  }
3009 
3013  PreviousMode,
3014  (PVOID*)&Token,
3015  NULL);
3016  if (NT_SUCCESS(Status))
3017  {
3018  /* Lock the token */
3020 
3021  switch (TokenInformationClass)
3022  {
3023  case TokenUser:
3024  {
3025  PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
3026 
3027  DPRINT("NtQueryInformationToken(TokenUser)\n");
3028  RequiredLength = sizeof(TOKEN_USER) +
3029  RtlLengthSid(Token->UserAndGroups[0].Sid);
3030 
3031  _SEH2_TRY
3032  {
3034  {
3036  &Token->UserAndGroups[0],
3037  RequiredLength - sizeof(TOKEN_USER),
3038  &tu->User,
3039  (PSID)(tu + 1),
3040  &Unused.PSid,
3041  &Unused.Ulong);
3042  }
3043  else
3044  {
3046  }
3047 
3048  if (ReturnLength != NULL)
3049  {
3051  }
3052  }
3054  {
3056  }
3057  _SEH2_END;
3058 
3059  break;
3060  }
3061 
3062  case TokenGroups:
3063  {
3064  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
3065 
3066  DPRINT("NtQueryInformationToken(TokenGroups)\n");
3067  RequiredLength = sizeof(tg->GroupCount) +
3068  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
3069 
3070  _SEH2_TRY
3071  {
3073  {
3074  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
3075  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
3076  PSID Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
3077  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
3078 
3079  tg->GroupCount = Token->UserAndGroupCount - 1;
3080  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
3081  &Token->UserAndGroups[1],
3082  SidLen,
3083  &tg->Groups[0],
3084  Sid,
3085  &Unused.PSid,
3086  &Unused.Ulong);
3087  }
3088  else
3089  {
3091  }
3092 
3093  if (ReturnLength != NULL)
3094  {
3096  }
3097  }
3099  {
3101  }
3102  _SEH2_END;
3103 
3104  break;
3105  }
3106 
3107  case TokenPrivileges:
3108  {
3109  PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
3110 
3111  DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
3112  RequiredLength = sizeof(tp->PrivilegeCount) +
3113  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
3114 
3115  _SEH2_TRY
3116  {
3118  {
3119  tp->PrivilegeCount = Token->PrivilegeCount;
3120  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
3121  Token->Privileges,
3122  &tp->Privileges[0]);
3123  }
3124  else
3125  {
3127  }
3128 
3129  if (ReturnLength != NULL)
3130  {
3132  }
3133  }
3135  {
3137  }
3138  _SEH2_END;
3139 
3140  break;
3141  }
3142 
3143  case TokenOwner:
3144  {
3145  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
3146  ULONG SidLen;
3147 
3148  DPRINT("NtQueryInformationToken(TokenOwner)\n");
3149  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
3150  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
3151 
3152  _SEH2_TRY
3153  {
3155  {
3156  to->Owner = (PSID)(to + 1);
3157  Status = RtlCopySid(SidLen,
3158  to->Owner,
3159  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
3160  }
3161  else
3162  {
3164  }
3165 
3166  if (ReturnLength != NULL)
3167  {
3169  }
3170  }
3172  {
3174  }
3175  _SEH2_END;
3176 
3177  break;
3178  }
3179 
3180  case TokenPrimaryGroup:
3181  {
3182  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
3183  ULONG SidLen;
3184 
3185  DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
3186  SidLen = RtlLengthSid(Token->PrimaryGroup);
3187  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
3188 
3189  _SEH2_TRY
3190  {
3192  {
3193  tpg->PrimaryGroup = (PSID)(tpg + 1);
3194  Status = RtlCopySid(SidLen,
3195  tpg->PrimaryGroup,
3196  Token->PrimaryGroup);
3197  }
3198  else
3199  {
3201  }
3202 
3203  if (ReturnLength != NULL)
3204  {
3206  }
3207  }
3209  {
3211  }
3212  _SEH2_END;
3213 
3214  break;
3215  }
3216 
3217  case TokenDefaultDacl:
3218  {
3219  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
3220 
3221  DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
3223 
3224  if (Token->DefaultDacl != NULL)
3225  RequiredLength += Token->DefaultDacl->AclSize;
3226 
3227  _SEH2_TRY
3228  {
3230  {
3231  if (Token->DefaultDacl != NULL)
3232  {
3233  tdd->DefaultDacl = (PACL)(tdd + 1);
3235  Token->DefaultDacl,
3236  Token->DefaultDacl->AclSize);
3237  }
3238  else
3239  {
3240  tdd->DefaultDacl = NULL;
3241  }
3242  }
3243  else
3244  {
3246  }
3247 
3248  if (ReturnLength != NULL)
3249  {
3251  }
3252  }
3254  {
3256  }
3257  _SEH2_END;
3258 
3259  break;
3260  }
3261 
3262  case TokenSource:
3263  {
3264  PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
3265 
3266  DPRINT("NtQueryInformationToken(TokenSource)\n");
3267  RequiredLength = sizeof(TOKEN_SOURCE);
3268 
3269  _SEH2_TRY
3270  {
3272  {
3273  *ts = Token->TokenSource;
3274  }
3275  else
3276  {
3278  }
3279 
3280  if (ReturnLength != NULL)
3281  {
3283  }
3284  }
3286  {
3288  }
3289  _SEH2_END;
3290 
3291  break;
3292  }
3293 
3294  case TokenType:
3295  {
3296  PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
3297 
3298  DPRINT("NtQueryInformationToken(TokenType)\n");
3299  RequiredLength = sizeof(TOKEN_TYPE);
3300 
3301  _SEH2_TRY
3302  {
3304  {
3305  *tt = Token->TokenType;
3306  }
3307  else
3308  {
3310  }
3311 
3312  if (ReturnLength != NULL)
3313  {
3315  }
3316  }
3318  {
3320  }
3321  _SEH2_END;
3322 
3323  break;
3324  }
3325 
3327  {
3329 
3330  DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
3331 
3332  /* Fail if the token is not an impersonation token */
3333  if (Token->TokenType != TokenImpersonation)
3334  {
3336  break;
3337  }
3338 
3340 
3341  _SEH2_TRY
3342  {
3344  {
3345  *sil = Token->ImpersonationLevel;
3346  }
3347  else
3348  {
3350  }
3351 
3352  if (ReturnLength != NULL)
3353  {
3355  }
3356  }
3358  {
3360  }
3361  _SEH2_END;
3362 
3363  break;
3364  }
3365 
3366  case TokenStatistics:
3367  {
3368  PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
3369 
3370  DPRINT("NtQueryInformationToken(TokenStatistics)\n");
3371  RequiredLength = sizeof(TOKEN_STATISTICS);
3372 
3373  _SEH2_TRY
3374  {
3376  {
3377  ts->TokenId = Token->TokenId;
3378  ts->AuthenticationId = Token->AuthenticationId;
3379  ts->ExpirationTime = Token->ExpirationTime;
3380  ts->TokenType = Token->TokenType;
3381  ts->ImpersonationLevel = Token->ImpersonationLevel;
3382  ts->DynamicCharged = Token->DynamicCharged;
3383  ts->DynamicAvailable = Token->DynamicAvailable;
3384  ts->GroupCount = Token->UserAndGroupCount - 1;
3385  ts->PrivilegeCount = Token->PrivilegeCount;
3386  ts->ModifiedId = Token->ModifiedId;
3387  }
3388  else
3389  {
3391  }
3392 
3393  if (ReturnLength != NULL)
3394  {
3396  }
3397  }
3399  {
3401  }
3402  _SEH2_END;
3403 
3404  break;
3405  }
3406 
3407  case TokenOrigin:
3408  {
3409  PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
3410 
3411  DPRINT("NtQueryInformationToken(TokenOrigin)\n");
3412  RequiredLength = sizeof(TOKEN_ORIGIN);
3413 
3414  _SEH2_TRY
3415  {
3417  {
3419  &Token->AuthenticationId);
3420  }
3421  else
3422  {
3424  }
3425 
3426  if (ReturnLength != NULL)
3427  {
3429  }
3430  }
3432  {
3434  }
3435  _SEH2_END;
3436 
3437  break;
3438  }
3439 
3441  DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
3443  break;
3444 
3445  case TokenRestrictedSids:
3446  {
3447  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
3448 
3449  DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
3450  RequiredLength = sizeof(tg->GroupCount) +
3451  RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
3452 
3453  _SEH2_TRY
3454  {
3456  {
3457  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
3458  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
3459  PSID Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
3460  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
3461 
3462  tg->GroupCount = Token->RestrictedSidCount;
3463  Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
3464  Token->RestrictedSids,
3465  SidLen,
3466  &tg->Groups[0],
3467  Sid,
3468  &Unused.PSid,
3469  &Unused.Ulong);
3470  }
3471  else
3472  {
3474  }
3475 
3476  if (ReturnLength != NULL)
3477  {
3479  }
3480  }
3482  {
3484  }
3485  _SEH2_END;
3486 
3487  break;
3488  }
3489 
3490  case TokenSandBoxInert:
3491  DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
3493  break;
3494 
3495  case TokenSessionId:
3496  {
3497  ULONG SessionId = 0;
3498 
3499  DPRINT("NtQueryInformationToken(TokenSessionId)\n");
3500 
3502  if (NT_SUCCESS(Status))
3503  {
3504  _SEH2_TRY
3505  {
3506  /* Buffer size was already verified, no need to check here again */
3507  *(PULONG)TokenInformation = SessionId;
3508 
3509  if (ReturnLength != NULL)
3510  {
3511  *ReturnLength = sizeof(ULONG);
3512  }
3513  }
3515  {
3517  }
3518  _SEH2_END;
3519  }
3520 
3521  break;
3522  }
3523 
3524  default:
3525  DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
3527  break;
3528  }
3529 
3530  /* Unlock and dereference the token */
3533  }
3534 
3535  return Status;
3536 }
LUID AuthenticationId
Definition: setypes.h:1052
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:299
#define TRUE
Definition: types.h:120
struct _TOKEN_DEFAULT_DACL TOKEN_DEFAULT_DACL
enum _TOKEN_TYPE * PTOKEN_TYPE
$ULONG GroupCount
Definition: setypes.h:1058
$ULONG DynamicCharged
Definition: setypes.h:1056
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:3070
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:993
_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:1054
struct _TOKEN_GROUPS * PTOKEN_GROUPS
LUID OriginatingLogonSession
Definition: setypes.h:1072
_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:1053
struct _TOKEN_SOURCE * PTOKEN_SOURCE
#define TOKEN_QUERY
Definition: setypes.h:893
#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:1055
#define TOKEN_QUERY_SOURCE
Definition: setypes.h:894
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:1059
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]
Definition: setypes.h:983
_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:979
#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:975
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:2679
$ULONG DynamicAvailable
Definition: setypes.h:1057
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:297
struct _TOKEN_ORIGIN TOKEN_ORIGIN
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:388
#define PAGED_CODE()

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

◆ 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 3574 of file token.c.

3579 {
3580  NTSTATUS Status;
3581  PTOKEN Token;
3583  ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
3584 
3585  PAGED_CODE();
3586 
3588 
3592  TokenInformation,
3594  PreviousMode);
3595  if (!NT_SUCCESS(Status))
3596  {
3597  /* Invalid buffers */
3598  DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
3599  return Status;
3600  }
3601 
3603  {
3604  NeededAccess |= TOKEN_ADJUST_SESSIONID;
3605  }
3606 
3608  NeededAccess,
3610  PreviousMode,
3611  (PVOID*)&Token,
3612  NULL);
3613  if (NT_SUCCESS(Status))
3614  {
3615  switch (TokenInformationClass)
3616  {
3617  case TokenOwner:
3618  {
3619  if (TokenInformationLength >= sizeof(TOKEN_OWNER))
3620  {
3621  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
3622  PSID InputSid = NULL, CapturedSid;
3623  ULONG DefaultOwnerIndex;
3624 
3625  _SEH2_TRY
3626  {
3627  InputSid = to->Owner;
3628  }
3630  {
3632  _SEH2_YIELD(goto Cleanup);
3633  }
3634  _SEH2_END;
3635 
3636  Status = SepCaptureSid(InputSid,
3637  PreviousMode,
3638  PagedPool,
3639  FALSE,
3640  &CapturedSid);
3641  if (NT_SUCCESS(Status))
3642  {
3643  /* Lock the token */
3645 
3646  /* Find the owner amongst the existing token user and groups */
3648  NULL,
3649  CapturedSid,
3650  NULL,
3651  &DefaultOwnerIndex);
3652  if (NT_SUCCESS(Status))
3653  {
3654  /* Found it */
3655  Token->DefaultOwnerIndex = DefaultOwnerIndex;
3656  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3657  }
3658 
3659  /* Unlock the token */
3661 
3662  SepReleaseSid(CapturedSid,
3663  PreviousMode,
3664  FALSE);
3665  }
3666  }
3667  else
3668  {
3670  }
3671  break;
3672  }
3673 
3674  case TokenPrimaryGroup:
3675  {
3677  {
3678  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
3679  PSID InputSid = NULL, CapturedSid;
3680  ULONG PrimaryGroupIndex;
3681 
3682  _SEH2_TRY
3683  {
3684  InputSid = tpg->PrimaryGroup;
3685  }
3687  {
3689  _SEH2_YIELD(goto Cleanup);
3690  }
3691  _SEH2_END;
3692 
3693  Status = SepCaptureSid(InputSid,
3694  PreviousMode,
3695  PagedPool,
3696  FALSE,
3697  &CapturedSid);
3698  if (NT_SUCCESS(Status))
3699  {
3700  /* Lock the token */
3702 
3703  /* Find the primary group amongst the existing token user and groups */
3705  CapturedSid,
3706  NULL,
3707  &PrimaryGroupIndex,
3708  NULL);
3709  if (NT_SUCCESS(Status))
3710  {
3711  /* Found it */
3712  Token->PrimaryGroup = Token->UserAndGroups[PrimaryGroupIndex].Sid;
3713  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3714  }
3715 
3716  /* Unlock the token */
3718 
3719  SepReleaseSid(CapturedSid,
3720  PreviousMode,
3721  FALSE);
3722  }
3723  }
3724  else
3725  {
3727  }
3728  break;
3729  }
3730 
3731  case TokenDefaultDacl:
3732  {
3734  {
3735  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
3736  PACL InputAcl = NULL;
3737 
3738  _SEH2_TRY
3739  {
3740  InputAcl = tdd->DefaultDacl;
3741  }
3743  {
3745  _SEH2_YIELD(goto Cleanup);
3746  }
3747  _SEH2_END;
3748 
3749  if (InputAcl != NULL)
3750  {
3751  PACL CapturedAcl;
3752 
3753  /* Capture and copy the dacl */
3754  Status = SepCaptureAcl(InputAcl,
3755  PreviousMode,
3756  PagedPool,
3757  TRUE,
3758  &CapturedAcl);
3759  if (NT_SUCCESS(Status))
3760  {
3761  ULONG DynamicLength;
3762 
3763  /* Lock the token */
3765 
3766  //
3767  // NOTE: So far our dynamic area only contains
3768  // the default dacl, so this makes the following
3769  // code pretty simple. The day where it stores
3770  // other data, the code will require adaptations.
3771  //
3772 
3773  DynamicLength = Token->DynamicAvailable;
3774  // Add here any other data length present in the dynamic area...
3775  if (Token->DefaultDacl)
3776  DynamicLength += Token->DefaultDacl->AclSize;
3777 
3778  /* Reallocate the dynamic area if it is too small */
3780  if ((DynamicLength < CapturedAcl->AclSize) ||
3781  (Token->DynamicPart == NULL))
3782  {
3783  PVOID NewDynamicPart;
3784 
3785  NewDynamicPart = ExAllocatePoolWithTag(PagedPool,
3786  CapturedAcl->AclSize,
3788  if (NewDynamicPart == NULL)
3789  {
3791  }
3792  else
3793  {
3794  if (Token->DynamicPart != NULL)
3795  {
3796  // RtlCopyMemory(NewDynamicPart, Token->DynamicPart, DynamicLength);
3797  ExFreePoolWithTag(Token->DynamicPart, TAG_TOKEN_DYNAMIC);
3798  }
3799  Token->DynamicPart = NewDynamicPart;
3800  Token->DynamicAvailable = 0;
3801  }
3802  }
3803  else
3804  {
3805  Token->DynamicAvailable = DynamicLength - CapturedAcl->AclSize;
3806  }
3807 
3808  if (NT_SUCCESS(Status))
3809  {
3810  /* Set the new dacl */
3811  Token->DefaultDacl = (PVOID)Token->DynamicPart;
3812  RtlCopyMemory(Token->DefaultDacl,
3813  CapturedAcl,
3814  CapturedAcl->AclSize);
3815 
3816  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3817  }
3818 
3819  /* Unlock the token */
3821 
3822  ExFreePoolWithTag(CapturedAcl, TAG_ACL);
3823  }
3824  }
3825  else
3826  {
3827  /* Lock the token */
3829 
3830  /* Clear the default dacl if present */
3831  if (Token->DefaultDacl != NULL)
3832  {
3833  Token->DynamicAvailable += Token->DefaultDacl->AclSize;
3834  RtlZeroMemory(Token->DefaultDacl, Token->DefaultDacl->AclSize);
3835  Token->DefaultDacl = NULL;
3836 
3837  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3838  }
3839 
3840  /* Unlock the token */
3842  }
3843  }
3844  else
3845  {
3847  }
3848  break;
3849  }
3850 
3851  case TokenSessionId:
3852  {
3853  ULONG SessionId = 0;
3854 
3855  _SEH2_TRY
3856  {
3857  /* Buffer size was already verified, no need to check here again */
3858  SessionId = *(PULONG)TokenInformation;
3859  }
3861  {
3863  _SEH2_YIELD(goto Cleanup);
3864  }
3865  _SEH2_END;
3866 
3867  /* Check for TCB privilege */
3869  {
3871  break;
3872  }
3873 
3874  /* Lock the token */
3876 
3877  Token->SessionId = SessionId;
3878  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3879 
3880  /* Unlock the token */
3882 
3883  break;
3884  }
3885 
3886  case TokenSessionReference:
3887  {
3888  ULONG SessionReference;
3889 
3890  _SEH2_TRY
3891  {
3892  /* Buffer size was already verified, no need to check here again */
3893  SessionReference = *(PULONG)TokenInformation;
3894  }
3896  {
3898  _SEH2_YIELD(goto Cleanup);
3899  }
3900  _SEH2_END;
3901 
3902  /* Check for TCB privilege */
3904  {
3906  goto Cleanup;
3907  }
3908 
3909  /* Check if it is 0 */
3910  if (SessionReference == 0)
3911  {
3912  ULONG OldTokenFlags;
3913 
3914  /* Lock the token */
3916 
3917  /* Atomically set the flag in the token */
3918  OldTokenFlags = RtlInterlockedSetBits(&Token->TokenFlags,
3920  /*
3921  * If the flag was already set, do not dereference again
3922  * the logon session. Use SessionReference as an indicator
3923  * to know whether to really dereference the session.
3924  */
3925  if (OldTokenFlags == Token->TokenFlags)
3926  SessionReference = ULONG_MAX;
3927 
3928  /*
3929  * Otherwise if the flag was never set but just for this first time then
3930  * remove the referenced logon session data from the token and dereference
3931  * the logon session when needed.
3932  */
3933  if (SessionReference == 0)
3934  {
3936  SepRmDereferenceLogonSession(&Token->AuthenticationId);
3937  }
3938 
3939  /* Unlock the token */
3941  }
3942  break;
3943  }
3944 
3945  case TokenAuditPolicy:
3946  {
3947  PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation =
3948  (PTOKEN_AUDIT_POLICY_INFORMATION)TokenInformation;
3949  SEP_AUDIT_POLICY AuditPolicy;
3950  ULONG i;
3951 
3952  _SEH2_TRY
3953  {
3954  ProbeForRead(PolicyInformation,
3956  Policies[PolicyInformation->PolicyCount]),
3957  sizeof(ULONG));
3958 
3959  /* Loop all policies in the structure */
3960  for (i = 0; i < PolicyInformation->PolicyCount; i++)
3961  {
3962  /* Set the corresponding bits in the packed structure */
3963  switch (PolicyInformation->Policies[i].Category)
3964  {
3965  case AuditCategorySystem:
3966  AuditPolicy.PolicyElements.System = PolicyInformation->Policies[i].Value;
3967  break;
3968 
3969  case AuditCategoryLogon:
3970  AuditPolicy.PolicyElements.Logon = PolicyInformation->Policies[i].Value;
3971  break;
3972 
3974  AuditPolicy.PolicyElements.ObjectAccess = PolicyInformation->Policies[i].Value;
3975  break;
3976 
3978  AuditPolicy.PolicyElements.PrivilegeUse = PolicyInformation->Policies[i].Value;
3979  break;
3980 
3982  AuditPolicy.PolicyElements.DetailedTracking = PolicyInformation->Policies[i].Value;
3983  break;
3984 
3986  AuditPolicy.PolicyElements.PolicyChange = PolicyInformation->Policies[i].Value;
3987  break;
3988 
3990  AuditPolicy.PolicyElements.AccountManagement = PolicyInformation->Policies[i].Value;
3991  break;
3992 
3994  AuditPolicy.PolicyElements.DirectoryServiceAccess = PolicyInformation->Policies[i].Value;
3995  break;
3996 
3998  AuditPolicy.PolicyElements.AccountLogon = PolicyInformation->Policies[i].Value;
3999  break;
4000  }
4001  }
4002  }
4004  {
4006  _SEH2_YIELD(goto Cleanup);
4007  }
4008  _SEH2_END;
4009 
4010  /* Check for TCB privilege */
4012  {
4014  break;
4015  }
4016 
4017  /* Lock the token */
4019 
4020  /* Set the new audit policy */
4021  Token->AuditPolicy = AuditPolicy;
4022  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4023 
4024  /* Unlock the token */
4026 
4027  break;
4028  }
4029 
4030  case TokenOrigin:
4031  {
4033 
4034  _SEH2_TRY
4035  {
4036  /* Copy the token origin */
4037  TokenOrigin = *(PTOKEN_ORIGIN)TokenInformation;
4038  }
4040  {
4042  _SEH2_YIELD(goto Cleanup);
4043  }
4044  _SEH2_END;
4045 
4046  /* Check for TCB privilege */
4048  {
4050  break;
4051  }
4052 
4053  /* Lock the token */
4055 
4056  /* Check if there is no token origin set yet */
4057  if (RtlIsZeroLuid(&Token->OriginatingLogonSession))
4058  {
4059  /* Set the token origin */
4060  Token->OriginatingLogonSession =
4061  TokenOrigin.OriginatingLogonSession;
4062 
4063  ExAllocateLocallyUniqueId(&Token->ModifiedId);
4064  }
4065 
4066  /* Unlock the token */
4068 
4069  break;
4070  }
4071 
4072  default:
4073  {
4074  DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
4077  break;
4078  }
4079  }
4080 Cleanup:
4082  }
4083 
4084  if (!NT_SUCCESS(Status))
4085  {
4086  DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status);
4087  }
4088 
4089  return Status;
4090 }
#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:299
#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:308
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:3070
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:394
_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:993
#define TOKEN_ADJUST_DEFAULT
Definition: setypes.h:897
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
struct _TOKEN_AUDIT_POLICY_INFORMATION::@1760 Policies[1]
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:148
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:181
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:174
_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:898
#define TOKEN_SESSION_NOT_REFERENCED
Definition: setypes.h:1149
_In_ TOKEN_INFORMATION_CLASS TokenInformationClass
Definition: sefuncs.h:297
#define ULONG_MAX
Definition: limits.h:44
#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(), 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 1605 of file token.c.

1608 {
1609  PAGED_CODE();
1610 
1611  /* Sanity checks */
1612  ASSERT(Token->TokenType == TokenPrimary);
1613  ASSERT(!Token->TokenInUse);
1614 
1615  /* Clean any previous token */
1616  if (Process->Token.Object) SeDeassignPrimaryToken(Process);
1617 
1618  /* Set the new token */
1620  Token->TokenInUse = TRUE;
1622 }
#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 1482 of file token.c.

1487 {
1488  NTSTATUS Status;
1490 
1491  PAGED_CODE();
1492 
1494  NULL,
1495  0,
1496  NULL,
1497  NULL);
1498 
1501  FALSE,
1503  Level,
1504  PreviousMode,
1505  (PTOKEN*)NewToken);
1506 
1507  return Status;
1508 }
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:224
#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:221
#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:207
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:224
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.

@unimplemented

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.
[in]SidsToDisableArray of SIDs to disable.
[in]PrivilegesToDeleteArray of privileges to delete.
[in]RestrictedSidsAn array of restricted SIDs for the new filtered token.
[out]FilteredTokenThe newly filtered token, returned to the caller.
Returns
To be added...

Definition at line 2283 of file token.c.

2290 {
2291  UNIMPLEMENTED;
2292  return STATUS_NOT_IMPLEMENTED;
2293 }
return STATUS_NOT_IMPLEMENTED
#define UNIMPLEMENTED
Definition: debug.h:115

Referenced by FatCreateRestrictEveryoneToken().

◆ 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 1373 of file token.c.

1376 {
1377  PTOKEN ProcessToken;
1378  LUID ProcessTokenId, CallerParentId;
1379 
1380  /* Assume failure */
1381  *IsChild = FALSE;
1382 
1383  /* Reference the process token */
1384  ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
1385  if (!ProcessToken)
1386  return STATUS_UNSUCCESSFUL;
1387 
1388  /* Get its token ID */
1389  ProcessTokenId = ProcessToken->TokenId;
1390 
1391  /* Dereference the token */
1393 
1394  /* Get our parent token ID */
1395  CallerParentId = Token->ParentTokenId;
1396 
1397  /* Compare the token IDs */
1398  if (RtlEqualLuid(&CallerParentId, &ProcessTokenId))
1399  *IsChild = TRUE;
1400 
1401  /* Return success */
1402  return STATUS_SUCCESS;
1403 }
#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:200
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 1422 of file token.c.

1425 {
1426  PTOKEN ProcessToken;
1427  LUID ProcessParentId, ProcessAuthId;
1428  LUID CallerParentId, CallerAuthId;
1429 
1430  /* Assume failure */
1431  *IsSibling = FALSE;
1432 
1433  /* Reference the process token */
1434  ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
1435  if (!ProcessToken)
1436  return STATUS_UNSUCCESSFUL;
1437 
1438  /* Get its parent and authentication IDs */
1439  ProcessParentId = ProcessToken->ParentTokenId;
1440  ProcessAuthId = ProcessToken->AuthenticationId;
1441 
1442  /* Dereference the token */
1444 
1445  /* Get our parent and authentication IDs */
1446  CallerParentId = Token->ParentTokenId;
1447  CallerAuthId = Token->AuthenticationId;
1448 
1449  /* Compare the token IDs */
1450  if (RtlEqualLuid(&CallerParentId, &ProcessParentId) &&
1451  RtlEqualLuid(&CallerAuthId, &ProcessAuthId))
1452  {
1453  *IsSibling = TRUE;
1454  }
1455 
1456  /* Return success */
1457  return STATUS_SUCCESS;
1458 }
#define TRUE
Definition: types.h:120
LUID AuthenticationId
Definition: setypes.h:201
_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:202
#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 4348 of file token.c.

4357 {
4358  ULONG GroupsInToken, GroupsInList;
4359  ULONG ChangeCount, GroupsCount, NewAttributes;
4360 
4361  PAGED_CODE();
4362 
4363  /* Ensure that the token we get is not plain garbage */
4364  ASSERT(Token);
4365 
4366  /* Initialize the counters and begin the work */
4367  *ChangesMade = FALSE;
4368  GroupsCount = 0;
4369  ChangeCount = 0;
4370 
4371  /* Begin looping all the groups in the token */
4372  for (GroupsInToken = 0; GroupsInToken < Token->UserAndGroupCount; GroupsInToken++)
4373  {
4374  /* Does the caller want to reset groups to default states? */
4375  if (ResetToDefaultStates)
4376  {
4377  /*
4378  * SE_GROUP_ENABLED_BY_DEFAULT is a special indicator that informs us
4379  * if a certain group has been enabled by default or not. In case
4380  * a group is enabled by default but it is not currently enabled then
4381  * at that point we must enable it back by default. For now just
4382  * assign the respective SE_GROUP_ENABLED attribute as we'll do the
4383  * eventual work later.
4384  */
4385  if ((Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_ENABLED_BY_DEFAULT) &&
4386  (Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_ENABLED) == 0)
4387  {
4388  NewAttributes = Token->UserAndGroups[GroupsInToken].Attributes |= SE_GROUP_ENABLED;
4389  }
4390 
4391  /*
4392  * Unlike the case above, a group that hasn't been enabled by
4393  * default but it's currently enabled then we must disable
4394  * it back.
4395  */
4396  if ((Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_ENABLED_BY_DEFAULT) == 0 &&
4397  (Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_ENABLED))
4398  {
4399  NewAttributes = Token->UserAndGroups[GroupsInToken].Attributes & ~SE_GROUP_ENABLED;
4400  }
4401  }
4402  else
4403  {
4404  /* Loop the provided groups in the list then */
4405  for (GroupsInList = 0; GroupsInList < NewStateCount; GroupsInList++)
4406  {
4407  /* Does this group exist in the token? */
4408  if (RtlEqualSid(&Token->UserAndGroups[GroupsInToken].Sid,
4409  &NewState[GroupsInList].Sid))
4410  {
4411  /*
4412  * This is the group that we're looking for.
4413  * However, it could be that the group is a
4414  * mandatory group which we are not allowed
4415  * and cannot disable it.
4416  */
4417  if ((Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_MANDATORY) &&
4418  (NewState[GroupsInList].Attributes & SE_GROUP_ENABLED) == 0)
4419  {
4420  /* It is mandatory, forget about this group */
4421  DPRINT1("SepAdjustGroups(): The SID group is mandatory!\n");
4423  }
4424 
4425  /*
4426  * We've to ensure that apart the group mustn't be
4427  * mandatory, it mustn't be a restricted group as
4428  * well. That is, the group is marked with
4429  * SE_GROUP_USE_FOR_DENY_ONLY flag and no one
4430  * can enable it because it's for "deny" use only.
4431  */
4432  if ((Token->UserAndGroups[GroupsInToken].Attributes & SE_GROUP_USE_FOR_DENY_ONLY) &&
4433  (NewState[GroupsInList].Attributes & SE_GROUP_ENABLED))
4434  {
4435  /* This group is restricted, forget about it */
4436  DPRINT1("SepAdjustGroups(): The SID group is for use deny only!\n");
4438  }
4439 
4440  /* Copy the attributes and stop searching */
4441  NewAttributes = NewState[GroupsInList].Attributes;
4442  NewAttributes &= SE_GROUP_ENABLED;
4443  NewAttributes = Token->UserAndGroups[GroupsInToken].Attributes & ~SE_GROUP_ENABLED;
4444  break;
4445  }
4446 
4447  /* Did we find the specific group we wanted? */
4448  if (GroupsInList == NewStateCount)
4449  {
4450  /* We didn't, continue with the next token's group */
4451  continue;
4452  }
4453  }
4454 
4455  /* Count the group that we found it */
4456  GroupsCount++;
4457 
4458  /* Does the token have the same attributes as the caller requested them? */
4459  if (Token->UserAndGroups[GroupsInToken].Attributes != NewAttributes)
4460  {
4461  /*
4462  * No, then it's time to make some adjustment to the
4463  * token's groups. Does the caller want the previous states
4464  * of groups?
4465  */
4466  if (PreviousGroupsState != NULL)
4467  {
4468  PreviousGroupsState->Groups[ChangeCount] = Token->UserAndGroups[GroupsInToken];
4469  }
4470 
4471  /* Time to apply the changes now? */
4472  if (ApplyChanges)
4473  {
4474  /* The caller gave us consent, apply and report that we made changes! */
4475  Token->UserAndGroups[GroupsInToken].Attributes = NewAttributes;
4476  *ChangesMade = TRUE;
4477  }
4478 
4479  /* Increment the count change */
4480  ChangeCount++;
4481  }
4482  }
4483  }
4484 
4485  /* Report the number of previous saved groups */
4486  if (PreviousGroupsState != NULL)
4487  {
4488  PreviousGroupsState->GroupCount = ChangeCount;
4489  }
4490 
4491  /* Report the number of changed groups */
4492  *ChangedGroups = ChangeCount;
4493 
4494  /* Did we miss some groups? */
4495  if (!ResetToDefaultStates && (GroupsCount < NewStateCount))
4496  {
4497  /*
4498  * If we're at this stage then we are in a situation
4499  * where the adjust changes done to token's groups is
4500  * not deterministic as the caller might have wanted
4501  * as per NewState parameter.
4502  */
4503  DPRINT1("SepAdjustGroups(): The token hasn't all the groups assigned!\n");
4504  return STATUS_NOT_ALL_ASSIGNED;
4505  }
4506 
4507  return STATUS_SUCCESS;
4508 }
#define STATUS_NOT_ALL_ASSIGNED
Definition: ntstatus.h:85
#define TRUE
Definition: types.h:120
BOOL ApplyChanges(HWND hwndDlg)
Definition: sounds.c:961
_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 SE_GROUP_ENABLED_BY_DEFAULT
Definition: setypes.h:91
#define STATUS_CANT_DISABLE_MANDATORY
Definition: ntstatus.h:329
#define ASSERT(a)
Definition: mode.c:44
#define SE_GROUP_ENABLED
Definition: setypes.h:92
#define SE_GROUP_MANDATORY
Definition: setypes.h:90
#define SE_GROUP_USE_FOR_DENY_ONLY
Definition: setypes.h:94
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
#define STATUS_CANT_ENABLE_DENY_ONLY
Definition: ntstatus.h:806
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
#define PAGED_CODE()

Referenced by NtAdjustGroupsToken().

◆ SepAdjustPrivileges()

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 
)
static

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 4818 of file token.c.

4827 {
4828  ULONG i, j, PrivilegeCount, ChangeCount, NewAttributes;
4829 
4830  PAGED_CODE();
4831 
4832  /* Count the found privileges and those that need to be changed */
4833  PrivilegeCount = 0;
4834  ChangeCount = 0;
4835  *ChangesMade = FALSE;
4836 
4837  /* Loop all privileges in the token */
4838  for (i = 0; i < Token->PrivilegeCount; i++)
4839  {
4840  /* Shall all of them be disabled? */
4841  if (DisableAllPrivileges)
4842  {
4843  /* The new attributes are the old ones, but disabled */
4844  NewAttributes = Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
4845  }
4846  else
4847  {
4848  /* Otherwise loop all provided privileges */
4849  for (j = 0; j < NewStateCount; j++)
4850  {
4851  /* Check if this is the LUID we are looking for */
4852  if (RtlEqualLuid(&Token->Privileges[i].Luid, &NewState[j].Luid))
4853  {
4854  DPRINT("Found privilege\n");
4855 
4856  /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
4857  NewAttributes = NewState[j].Attributes;
4858  NewAttributes &= (SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED);
4859  NewAttributes |= Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
4860 
4861  /* Stop looking */
4862  break;
4863  }
4864  }
4865 
4866  /* Check if we didn't find the privilege */
4867  if (j == NewStateCount)
4868  {
4869  /* Continue with the token's next privilege */
4870  continue;
4871  }
4872  }
4873 
4874  /* We found a privilege, count it */
4875  PrivilegeCount++;
4876 
4877  /* Does the privilege need to be changed? */
4878  if (Token->Privileges[i].Attributes != NewAttributes)
4879  {
4880  /* Does the caller want the old privileges? */
4881  if (PreviousState != NULL)
4882  {
4883  /* Copy the old privilege */
4884  PreviousState->Privileges[ChangeCount] = Token->Privileges[i];
4885  }
4886 
4887  /* Does the caller want to apply the changes? */
4888  if (ApplyChanges)
4889  {
4890  /* Shall we remove the privilege? */
4891  if (NewAttributes & SE_PRIVILEGE_REMOVED)
4892  {
4893  /* Set the token as disabled and update flags for it */
4894  Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
4896 
4897  /* Remove the privilege */
4899 
4900  *ChangesMade = TRUE;
4901 
4902  /* Fix the running index and continue with next one */
4903  i--;
4904  continue;
4905  }
4906 
4907  /* Set the new attributes and update flags */
4908  Token->Privileges[i].Attributes = NewAttributes;
4910  *ChangesMade = TRUE;
4911  }
4912 
4913  /* Increment the change count */
4914  ChangeCount++;
4915  }
4916  }
4917 
4918  /* Set the number of saved privileges */
4919  if (PreviousState != NULL)
4920  PreviousState->PrivilegeCount = ChangeCount;
4921 
4922  /* Return the number of changed privileges */
4923  *ChangedPrivileges = ChangeCount;
4924 
4925  /* Check if we missed some */
4926  if (!DisableAllPrivileges && (PrivilegeCount < NewStateCount))
4927  {
4928  return STATUS_NOT_ALL_ASSIGNED;
4929  }
4930 
4931  return STATUS_SUCCESS;
4932 }
#define STATUS_NOT_ALL_ASSIGNED
Definition: ntstatus.h:85
#define TRUE
Definition: types.h:120
BOOL ApplyChanges(HWND hwndDlg)
Definition: sounds.c:961
_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 SE_PRIVILEGE_REMOVED
Definition: setypes.h:64
static VOID SepUpdateSinglePrivilegeFlagToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Updates the token's flags based upon the privilege that the token has been granted....
Definition: token.c:488
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
#define FALSE
Definition: types.h:117
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
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 GLint GLint j
Definition: glfuncs.h:250
static VOID SepRemovePrivilegeToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Removes a privilege from the token.
Definition: token.c:580
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 NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829
#define PAGED_CODE()

Referenced by NtAdjustPrivilegesToken().

◆ SepComparePrivilegeAndAttributesFromTokens()

static BOOLEAN SepComparePrivilegeAndAttributesFromTokens ( _In_ PLUID_AND_ATTRIBUTES  PrivArrayToken1,
_In_ ULONG  CountPrivArray1,
_In_ PLUID_AND_ATTRIBUTES  PrivArrayToken2,
_In_ ULONG  CountPrivArray2 
)
static

Compares the elements of privilege arrays provided by tokens. The elements that are being compared for equality are the privileges and their attributes.

Parameters
[in]PrivArrayToken1Privilege array from the first token.
[in]CountPrivArray1Privilege count array from the first token.
[in]PrivArrayToken2Privilege array from the second token.
[in]CountPrivArray2Privilege count array from the second token.
Returns
Returns TRUE if the elements match from either arrays, FALSE otherwise.

Definition at line 219 of file token.c.

224 {
225  ULONG FirstCount, SecondCount;
226  PLUID_AND_ATTRIBUTES FirstPrivArray, SecondPrivArray;
227  PAGED_CODE();
228 
229  /* Bail out if index counters provided are not equal */
230  if (CountPrivArray1 != CountPrivArray2)
231  {
232  DPRINT("SepComparePrivilegeAndAttributesFromTokens(): Index counters are not the same!\n");
233  return FALSE;
234  }
235 
236  /* Loop over the privilege arrays and compare them */
237  for (FirstCount = 0; FirstCount < CountPrivArray1; FirstCount++)
238  {
239  for (SecondCount = 0; SecondCount < CountPrivArray2; SecondCount++)
240  {
241  FirstPrivArray = &PrivArrayToken1[FirstCount];
242  SecondPrivArray = &PrivArrayToken2[SecondCount];
243 
244  if (RtlEqualLuid(&FirstPrivArray->Luid, &SecondPrivArray->Luid) &&
245  FirstPrivArray->Attributes == SecondPrivArray->Attributes)
246  {
247  break;
248  }
249  }
250 
251  /* We've exhausted the array of the second token without finding this one */
252  if (SecondCount == CountPrivArray2)
253  {
254  DPRINT("SepComparePrivilegeAndAttributesFromTokens(): No matching elements could be found in either token!\n");
255  return FALSE;
256  }
257  }
258 
259  return TRUE;
260 }
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
unsigned int ULONG
Definition: retypes.h:1
#define DPRINT
Definition: sndvol32.h:71
#define PAGED_CODE()

Referenced by SepCompareTokens().

◆ SepCompareSidAndAttributesFromTokens()

static BOOLEAN SepCompareSidAndAttributesFromTokens ( _In_ PSID_AND_ATTRIBUTES  SidArrayToken1,
_In_ ULONG  CountSidArray1,
_In_ PSID_AND_ATTRIBUTES  SidArrayToken2,
_In_ ULONG  CountSidArray2 
)
static

Compares the elements of SID arrays provided by tokens. The elements that are being compared for equality are the SIDs and their attributes.

Parameters
[in]SidArrayToken1SID array from the first token.
[in]CountSidArray1SID count array from the first token.
[in]SidArrayToken2SID array from the second token.
[in]CountSidArray2SID count array from the second token.
Returns
Returns TRUE if the elements match from either arrays, FALSE otherwise.

Definition at line 152 of file token.c.

157 {
158  ULONG FirstCount, SecondCount;
159  PSID_AND_ATTRIBUTES FirstSidArray, SecondSidArray;
160  PAGED_CODE();
161 
162  /* Bail out if index counters provided are not equal */
163  if (CountSidArray1 != CountSidArray2)
164  {
165  DPRINT("SepCompareSidAndAttributesFromTokens(): Index counters are not the same!\n");
166  return FALSE;
167  }
168 
169  /* Loop over the SID arrays and compare them */
170  for (FirstCount = 0; FirstCount < CountSidArray1; FirstCount++)
171  {
172  for (SecondCount = 0; SecondCount < CountSidArray2; SecondCount++)
173  {
174  FirstSidArray = &SidArrayToken1[FirstCount];
175  SecondSidArray = &SidArrayToken2[SecondCount];
176 
177  if (RtlEqualSid(FirstSidArray->Sid, SecondSidArray->Sid) &&
178  FirstSidArray->Attributes == SecondSidArray->Attributes)
179  {
180  break;
181  }
182  }
183 
184  /* We've exhausted the array of the second token without finding this one */
185  if (SecondCount == CountSidArray2)
186  {
187  DPRINT("SepCompareSidAndAttributesFromTokens(): No matching elements could be found in either token!\n");
188  return FALSE;
189  }
190  }
191 
192  return TRUE;
193 }
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int ULONG
Definition: retypes.h:1
#define DPRINT
Definition: sndvol32.h:71
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
#define PAGED_CODE()

Referenced by SepCompareTokens().

◆ SepCompareTokens()

static NTSTATUS SepCompareTokens ( _In_ PTOKEN  FirstToken,
_In_ PTOKEN  SecondToken,
_Out_ PBOOLEAN