ReactOS 0.4.16-dev-401-g45b008d
token.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for token.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

NTSTATUS SepCreateTokenLock (_Inout_ PTOKEN Token)
 Creates a lock for the token.
 
VOID SepDeleteTokenLock (_Inout_ PTOKEN Token)
 Deletes a lock of a token.
 
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.
 
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.
 
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.
 
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.
 
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.
 
BOOLEAN NTAPI SepTokenIsOwner (_In_ PACCESS_TOKEN _Token, _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ BOOLEAN TokenLocked)
 Checks if a token belongs to the main user, being the owner.
 
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.
 
VOID SepRemovePrivilegeToken (_Inout_ PTOKEN Token, _In_ ULONG Index)
 Removes a privilege from the token.
 
VOID SepRemoveUserGroupToken (_Inout_ PTOKEN Token, _In_ ULONG Index)
 Removes a group from the token.
 
ULONG SepComputeAvailableDynamicSpace (_In_ ULONG DynamicCharged, _In_ PSID PrimaryGroup, _In_opt_ PACL DefaultDacl)
 Computes the exact available dynamic area of an access token whilst querying token statistics.
 
NTSTATUS SepRebuildDynamicPartOfToken (_Inout_ PTOKEN AccessToken, _In_ ULONG NewDynamicPartSize)
 Re-builds the dynamic part area of an access token during an a default DACL or primary group replacement within the said token if the said dynamic area can't hold the new security content.
 
VOID NTAPI SepFreeProxyData (_Inout_ PVOID ProxyData)
 Frees (de-allocates) the proxy data memory block of a token.
 
NTSTATUS NTAPI SepCopyProxyData (_Out_ PVOID *Dest, _In_ PVOID Src)
 Copies the proxy data from the source into the destination of a token.
 
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.
 
VOID NTAPI SeDeassignPrimaryToken (_Inout_ PEPROCESS Process)
 Removes the primary token of a process.
 
ULONG RtlLengthSidAndAttributes (_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src)
 Computes the length size of a SID.
 
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.
 
static NTSTATUS SepOpenThreadToken (_In_ PETHREAD Thread, _In_ HANDLE ThreadHandle, _In_ PTOKEN ThreadToken, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _In_ BOOLEAN EffectiveOnly, _In_ BOOLEAN CopyOnOpen, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PHANDLE OpenedTokenHandle)
 Internal private function that returns an opened handle of an access token associated with a thread.
 
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.
 
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.
 
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.
 
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).
 
BOOLEAN NTAPI SeTokenIsInert (_In_ PTOKEN Token)
 Determines if a token is a sandbox inert token or not, based upon the token flags.
 
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.
 
VOID NTAPI SepInitializeTokenImplementation (VOID)
 Internal function that initializes critical kernel data for access token implementation in SRM.
 
VOID NTAPI SeAssignPrimaryToken (_In_ PEPROCESS Process, _In_ PTOKEN Token)
 Assigns a primary access token to a given process.
 
VOID NTAPI SeGetTokenControlInformation (_In_ PACCESS_TOKEN _Token, _Out_ PTOKEN_CONTROL TokenControl)
 Retrieves token control information.
 
PTOKEN NTAPI SepCreateSystemProcessToken (VOID)
 Creates the system process token.
 
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.
 
PTOKEN SepCreateSystemAnonymousLogonTokenNoEveryone (VOID)
 Creates the anonymous logon token for the system. This kind of token doesn't include the everyone SID group (being SeWorldSid).
 
NTSTATUS NTAPI SeQuerySessionIdToken (_In_ PACCESS_TOKEN Token, _Out_ PULONG pSessionId)
 Queries the session ID of an access token.
 
NTSTATUS NTAPI SeQueryAuthenticationIdToken (_In_ PACCESS_TOKEN Token, _Out_ PLUID LogonId)
 Queries the authentication ID of an access token.
 
SECURITY_IMPERSONATION_LEVEL NTAPI SeTokenImpersonationLevel (_In_ PACCESS_TOKEN Token)
 Gathers the security impersonation level of an access token.
 
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.
 
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.
 
BOOLEAN NTAPI SeTokenIsRestricted (_In_ PACCESS_TOKEN Token)
 Determines if a token is restricted or not, based upon the token flags.
 
BOOLEAN NTAPI SeTokenIsWriteRestricted (_In_ PACCESS_TOKEN Token)
 Determines if a token is write restricted, that is, nobody can write anything to it.
 
BOOLEAN NTAPI SeTokenCanImpersonate (_In_ PTOKEN ProcessToken, _In_ PTOKEN TokenToImpersonate, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
 Determines whether the server is allowed to impersonate on behalf of a client or not. For further details, see Remarks.
 
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.
 
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.
 
NTSTATUS NTAPI NtCompareTokens (_In_ HANDLE FirstTokenHandle, _In_ HANDLE SecondTokenHandle, _Out_ PBOOLEAN Equal)
 Compares tokens if they're equal or not.
 
NTSTATUS NTAPI NtImpersonateAnonymousToken (_In_ HANDLE ThreadHandle)
 Allows the calling thread to impersonate the system's anonymous logon token.
 

Variables

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

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file token.c.

Function Documentation

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

2507{
2509 PTOKEN FirstToken, SecondToken;
2512
2513 PAGED_CODE();
2514
2516
2517 if (PreviousMode != KernelMode)
2518 {
2519 _SEH2_TRY
2520 {
2521 ProbeForWriteBoolean(Equal);
2522 }
2524 {
2525 /* Return the exception code */
2527 }
2528 _SEH2_END;
2529 }
2530
2531 Status = ObReferenceObjectByHandle(FirstTokenHandle,
2535 (PVOID*)&FirstToken,
2536 NULL);
2537 if (!NT_SUCCESS(Status))
2538 {
2539 DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
2540 return Status;
2541 }
2542
2543 Status = ObReferenceObjectByHandle(SecondTokenHandle,
2547 (PVOID*)&SecondToken,
2548 NULL);
2549 if (!NT_SUCCESS(Status))
2550 {
2551 DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
2552 ObDereferenceObject(FirstToken);
2553 return Status;
2554 }
2555
2556 if (FirstToken != SecondToken)
2557 {
2558 Status = SepCompareTokens(FirstToken,
2559 SecondToken,
2560 &IsEqual);
2561 }
2562 else
2563 {
2564 IsEqual = TRUE;
2565 }
2566
2567 ObDereferenceObject(SecondToken);
2568 ObDereferenceObject(FirstToken);
2569
2570 if (NT_SUCCESS(Status))
2571 {
2572 _SEH2_TRY
2573 {
2574 *Equal = IsEqual;
2575 }
2577 {
2579 }
2580 _SEH2_END;
2581 }
2582
2583 return Status;
2584}
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ExGetPreviousMode
Definition: ex.h:143
@ IsEqual
Definition: fatprocs.h:1887
Status
Definition: gdiplustypes.h:25
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:349
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define KernelMode
Definition: asm.h:38
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:243
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
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 _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define ProbeForWriteBoolean(Ptr)
Definition: probe.h:31
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define TOKEN_QUERY
Definition: setypes.h:928

Referenced by START_TEST().

◆ NtImpersonateAnonymousToken()

NTSTATUS NTAPI NtImpersonateAnonymousToken ( _In_ HANDLE  ThreadHandle)

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

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

Definition at line 2612 of file token.c.

2614{
2618 PAGED_CODE();
2619
2621
2622 /* Obtain the thread object from the handle */
2623 Status = ObReferenceObjectByHandle(ThreadHandle,
2627 (PVOID*)&Thread,
2628 NULL);
2629 if (!NT_SUCCESS(Status))
2630 {
2631 DPRINT1("NtImpersonateAnonymousToken(): Failed to reference the object (Status 0x%lx)\n", Status);
2632 return Status;
2633 }
2634
2635 /* Call the private routine to impersonate the token */
2637 if (!NT_SUCCESS(Status))
2638 {
2639 DPRINT1("NtImpersonateAnonymousToken(): Failed to impersonate the token (Status 0x%lx)\n", Status);
2640 }
2641
2643 return Status;
2644}
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define THREAD_IMPERSONATE
Definition: pstypes.h:152
POBJECT_TYPE PsThreadType
Definition: thread.c:20
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:334

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

2479{
2480 return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
2481 TokenHandle);
2482}
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:726
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:2331
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_In_ ACCESS_MASK _In_ BOOLEAN OpenAsSelf
Definition: zwfuncs.h:700

Referenced by BaseGetNamedObjectDirectory(), CheckTokenMembership(), CreateProcessAsUserCommon(), CsrGetProcessLuid(), GetCallerLuid(), LsarSetSecurityObject(), NetpGetClientLogonId(), 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 2331 of file token.c.

2337{
2339 HANDLE hToken;
2340 PTOKEN Token;
2346 BOOLEAN RestoreImpersonation = FALSE;
2347
2348 PAGED_CODE();
2349
2351
2352 /* Ensure that we can give the handle to the caller */
2353 if (PreviousMode != KernelMode)
2354 {
2355 _SEH2_TRY
2356 {
2358 }
2360 {
2361 /* Return the exception code */
2363 }
2364 _SEH2_END;
2365 }
2366
2367 /* Validate object attributes */
2369
2370 /*
2371 * At first open the thread token for information access and verify
2372 * that the token associated with the thread is valid.
2373 */
2376 NULL);
2377 if (!NT_SUCCESS(Status))
2378 {
2379 DPRINT1("Failed to reference the object thread (Status 0x%lx)\n", Status);
2380 return Status;
2381 }
2382
2383 /* Reference the token from the thread */
2386 if (Token == NULL)
2387 {
2388 DPRINT("Failed to reference the thread's impersonation token, thread has no token\n");
2390 return STATUS_NO_TOKEN;
2391 }
2392
2393 /* Ensure the token has no anonymous security */
2395 {
2396 DPRINT1("The thread token has anonymous security, can't open it\n");
2400 }
2401
2402 /* Revert to self if OpenAsSelf is specified */
2403 if (OpenAsSelf)
2404 {
2405 RestoreImpersonation = PsDisableImpersonation(PsGetCurrentThread(),
2407 }
2408
2409 /* Call the private function to do the job */
2411 ThreadHandle,
2412 Token,
2416 CopyOnOpen,
2419 &hToken);
2420
2421 /* Restore the impersonation back if needed */
2422 if (RestoreImpersonation)
2423 {
2425 }
2426
2427 /* Dereference the access token and the associated thread */
2430
2431 if (!NT_SUCCESS(Status))
2432 {
2433 DPRINT1("Failed to open the thread's token (Status 0x%lx)\n", Status);
2434 return Status;
2435 }
2436
2437 /* Give the opened token handle to the caller */
2438 _SEH2_TRY
2439 {
2440 *TokenHandle = hToken;
2441 }
2443 {
2445 }
2446 _SEH2_END;
2447
2448 return Status;
2449}
#define FALSE
Definition: types.h:117
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define THREAD_QUERY_INFORMATION
Definition: pstypes.h:150
enum _SECURITY_IMPERSONATION_LEVEL SECURITY_IMPERSONATION_LEVEL
@ SecurityAnonymous
Definition: lsa.idl:55
#define PsDereferenceImpersonationToken(T)
Definition: imports.h:298
_In_ HANDLE _In_opt_ HANDLE _Out_opt_ PHANDLE _In_ ACCESS_MASK _In_ ULONG HandleAttributes
Definition: obfuncs.h:433
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN EffectiveOnly
Definition: sefuncs.h:410
BOOLEAN NTAPI PsDisableImpersonation(IN PETHREAD Thread, OUT PSE_IMPERSONATION_STATE ImpersonationState)
Definition: security.c:937
VOID NTAPI PsRestoreImpersonation(IN PETHREAD Thread, IN PSE_IMPERSONATION_STATE ImpersonationState)
Definition: security.c:987
PACCESS_TOKEN NTAPI PsReferenceImpersonationToken(IN PETHREAD Thread, OUT PBOOLEAN CopyOnOpen, OUT PBOOLEAN EffectiveOnly, OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Definition: security.c:871
static NTSTATUS SepOpenThreadToken(_In_ PETHREAD Thread, _In_ HANDLE ThreadHandle, _In_ PTOKEN ThreadToken, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _In_ BOOLEAN EffectiveOnly, _In_ BOOLEAN CopyOnOpen, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PHANDLE OpenedTokenHandle)
Internal private function that returns an opened handle of an access token associated with a thread.
Definition: token.c:1170
#define STATUS_NO_TOKEN
Definition: ntstatus.h:360
#define STATUS_CANT_OPEN_ANONYMOUS
Definition: ntstatus.h:402
FORCEINLINE ULONG ObpValidateAttributes(IN ULONG Attributes, IN KPROCESSOR_MODE PreviousMode)
Definition: ob_x.h:22
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
#define DPRINT
Definition: sndvol32.h:73
_Out_ PBOOLEAN CopyOnOpen
Definition: psfuncs.h:154
_Inout_ PSE_IMPERSONATION_STATE ImpersonationState
Definition: psfuncs.h:189
_Out_ PBOOLEAN _Out_ PBOOLEAN _Out_ PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: psfuncs.h:156

Referenced by NtOpenThreadToken(), and START_TEST().

◆ RtlLengthSidAndAttributes()

ULONG RtlLengthSidAndAttributes ( _In_ ULONG  Count,
_In_ PSID_AND_ATTRIBUTES  Src 
)

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

968{
969 ULONG i;
970 ULONG uLength;
971
972 PAGED_CODE();
973
974 uLength = Count * sizeof(SID_AND_ATTRIBUTES);
975 for (i = 0; i < Count; i++)
976 uLength += RtlLengthSid(Src[i].Sid);
977
978 return uLength;
979}
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
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1145
int Count
Definition: noreturn.cpp:7
uint32_t ULONG
Definition: typedefs.h:59
struct _SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES

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

◆ SeAssignPrimaryToken()

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

Assigns a primary access token to a given process.

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

Definition at line 1686 of file token.c.

1689{
1690 PAGED_CODE();
1691
1692 /* Sanity checks */
1693 ASSERT(Token->TokenType == TokenPrimary);
1694 ASSERT(!Token->TokenInUse);
1695
1696 /* Clean any previous token */
1697 if (Process->Token.Object) SeDeassignPrimaryToken(Process);
1698
1699 /* Set the new token */
1701 Token->TokenInUse = TRUE;
1703}
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
#define ASSERT(a)
Definition: mode.c:44
@ TokenPrimary
Definition: imports.h:273
VOID NTAPI SeDeassignPrimaryToken(_Inout_ PEPROCESS Process)
Removes the primary token of a process.
Definition: token.c:936
VOID FASTCALL ObInitializeFastReference(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:107
#define ObReferenceObject
Definition: obfuncs.h:204

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

1547{
1550
1551 PAGED_CODE();
1552
1554 NULL,
1555 0,
1556 NULL,
1557 NULL);
1558
1561 FALSE,
1563 Level,
1565 (PTOKEN*)NewToken);
1566
1567 return Status;
1568}
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
@ TokenImpersonation
Definition: imports.h:274
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
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: tokenlif.c:471
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56

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

938{
939 PTOKEN OldToken;
940
941 /* Remove the Token */
942 OldToken = ObFastReplaceObject(&Process->Token, NULL);
943
944 /* Mark the Old Token as free */
945 OldToken->TokenInUse = FALSE;
946
947 /* Dereference the Token */
948 ObDereferenceObject(OldToken);
949}
PVOID FASTCALL ObFastReplaceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
BOOLEAN TokenInUse
Definition: setypes.h:242

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

850{
851 PTOKEN OldToken;
852 PTOKEN NewToken = (PTOKEN)NewAccessToken;
853
854 PAGED_CODE();
855
856 if (NewToken->TokenType != TokenPrimary)
858
859 if (NewToken->TokenInUse)
860 {
863
864 /* Maybe we're trying to set the same token */
866 if (OldToken == NewToken)
867 {
868 /* So it's a nop. */
869 *OldAccessToken = OldToken;
870 return STATUS_SUCCESS;
871 }
872
873 Status = SepCompareTokens(OldToken, NewToken, &IsEqual);
874 if (!NT_SUCCESS(Status))
875 {
877 *OldAccessToken = NULL;
878 return Status;
879 }
880
881 if (!IsEqual)
882 {
884 *OldAccessToken = NULL;
886 }
887 /* Silently return STATUS_SUCCESS but do not set the new token,
888 * as it's already in use elsewhere. */
889 *OldAccessToken = OldToken;
890 return STATUS_SUCCESS;
891 }
892
893 /* Lock the new token */
895
896 /* Mark new token in use */
897 NewToken->TokenInUse = TRUE;
898
899 /* Set the session ID for the new token */
900 NewToken->SessionId = MmGetSessionId(Process);
901
902 /* Unlock the new token */
903 SepReleaseTokenLock(NewToken);
904
905 /* Reference the new token */
906 ObReferenceObject(NewToken);
907
908 /* Replace the old with the new */
909 OldToken = ObFastReplaceObject(&Process->Token, NewToken);
910
911 /* Lock the old token */
913
914 /* Mark the old token as free */
915 OldToken->TokenInUse = FALSE;
916
917 /* Unlock the old token */
918 SepReleaseTokenLock(OldToken);
919
920 *OldAccessToken = (PACCESS_TOKEN)OldToken;
921 return STATUS_SUCCESS;
922}
#define PsDereferencePrimaryToken(T)
Definition: imports.h:301
struct _TOKEN * PTOKEN
ULONG NTAPI MmGetSessionId(IN PEPROCESS Process)
Definition: session.c:179
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:285
#define SepReleaseTokenLock(Token)
Definition: se.h:296
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
#define STATUS_TOKEN_ALREADY_IN_USE
Definition: ntstatus.h:535
#define STATUS_BAD_TOKEN_TYPE
Definition: ntstatus.h:404
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG SessionId
Definition: setypes.h:225
TOKEN_TYPE TokenType
Definition: setypes.h:239
PVOID PACCESS_TOKEN
Definition: setypes.h:11

Referenced by PspAssignPrimaryToken().

◆ SeGetTokenControlInformation()

VOID NTAPI SeGetTokenControlInformation ( _In_ PACCESS_TOKEN  _Token,
_Out_ PTOKEN_CONTROL  TokenControl 
)

Retrieves token control information.

Parameters
[in]_TokenA valid token object.
[out]SecurityDescriptorThe returned token control information.
Returns
Nothing.

Definition at line 1720 of file token.c.

1723{
1724 PTOKEN Token = _Token;
1725 PAGED_CODE();
1726
1727 /* Capture the main fields */
1728 TokenControl->AuthenticationId = Token->AuthenticationId;
1729 TokenControl->TokenId = Token->TokenId;
1730 TokenControl->TokenSource = Token->TokenSource;
1731
1732 /* Lock the token */
1734
1735 /* Capture the modified ID */
1736 TokenControl->ModifiedId = Token->ModifiedId;
1737
1738 /* Unlock it */
1740}
#define SepAcquireTokenLockShared(Token)
Definition: se.h:290

Referenced by SepCreateClientSecurity().

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

1436{
1437 PTOKEN ProcessToken;
1438 LUID ProcessTokenId, CallerParentId;
1439
1440 /* Assume failure */
1441 *IsChild = FALSE;
1442
1443 /* Reference the process token */
1445 if (!ProcessToken)
1446 return STATUS_UNSUCCESSFUL;
1447
1448 /* Get its token ID */
1449 ProcessTokenId = ProcessToken->TokenId;
1450
1451 /* Dereference the token */
1453
1454 /* Get our parent token ID */
1455 CallerParentId = Token->ParentTokenId;
1456
1457 /* Compare the token IDs */
1458 if (RtlEqualLuid(&CallerParentId, &ProcessTokenId))
1459 *IsChild = TRUE;
1460
1461 /* Return success */
1462 return STATUS_SUCCESS;
1463}
VOID FASTCALL ObFastDereferenceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:167
LUID TokenId
Definition: setypes.h:218
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
BOOL WINAPI IsChild(_In_ HWND, _In_ HWND)
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:304

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

1485{
1486 PTOKEN ProcessToken;
1487 LUID ProcessParentId, ProcessAuthId;
1488 LUID CallerParentId, CallerAuthId;
1489
1490 /* Assume failure */
1491 *IsSibling = FALSE;
1492
1493 /* Reference the process token */
1495 if (!ProcessToken)
1496 return STATUS_UNSUCCESSFUL;
1497
1498 /* Get its parent and authentication IDs */
1499 ProcessParentId = ProcessToken->ParentTokenId;
1500 ProcessAuthId = ProcessToken->AuthenticationId;
1501
1502 /* Dereference the token */
1504
1505 /* Get our parent and authentication IDs */
1506 CallerParentId = Token->ParentTokenId;
1507 CallerAuthId = Token->AuthenticationId;
1508
1509 /* Compare the token IDs */
1510 if (RtlEqualLuid(&CallerParentId, &ProcessParentId) &&
1511 RtlEqualLuid(&CallerAuthId, &ProcessAuthId))
1512 {
1513 *IsSibling = TRUE;
1514 }
1515
1516 /* Return success */
1517 return STATUS_SUCCESS;
1518}
LUID AuthenticationId
Definition: setypes.h:219
LUID ParentTokenId
Definition: setypes.h:220

Referenced by PspSetPrimaryToken().

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

179{
180 ULONG FirstCount, SecondCount;
181 PLUID_AND_ATTRIBUTES FirstPrivArray, SecondPrivArray;
182 PAGED_CODE();
183
184 /* Bail out if index counters provided are not equal */
185 if (CountPrivArray1 != CountPrivArray2)
186 {
187 DPRINT("SepComparePrivilegeAndAttributesFromTokens(): Index counters are not the same!\n");
188 return FALSE;
189 }
190
191 /* Loop over the privilege arrays and compare them */
192 for (FirstCount = 0; FirstCount < CountPrivArray1; FirstCount++)
193 {
194 for (SecondCount = 0; SecondCount < CountPrivArray2; SecondCount++)
195 {
196 FirstPrivArray = &PrivArrayToken1[FirstCount];
197 SecondPrivArray = &PrivArrayToken2[SecondCount];
198
199 if (RtlEqualLuid(&FirstPrivArray->Luid, &SecondPrivArray->Luid) &&
200 FirstPrivArray->Attributes == SecondPrivArray->Attributes)
201 {
202 break;
203 }
204 }
205
206 /* We've exhausted the array of the second token without finding this one */
207 if (SecondCount == CountPrivArray2)
208 {
209 DPRINT("SepComparePrivilegeAndAttributesFromTokens(): No matching elements could be found in either token!\n");
210 return FALSE;
211 }
212 }
213
214 return TRUE;
215}

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

112{
113 ULONG FirstCount, SecondCount;
114 PSID_AND_ATTRIBUTES FirstSidArray, SecondSidArray;
115 PAGED_CODE();
116
117 /* Bail out if index counters provided are not equal */
118 if (CountSidArray1 != CountSidArray2)
119 {
120 DPRINT("SepCompareSidAndAttributesFromTokens(): Index counters are not the same!\n");
121 return FALSE;
122 }
123
124 /* Loop over the SID arrays and compare them */
125 for (FirstCount = 0; FirstCount < CountSidArray1; FirstCount++)
126 {
127 for (SecondCount = 0; SecondCount < CountSidArray2; SecondCount++)
128 {
129 FirstSidArray = &SidArrayToken1[FirstCount];
130 SecondSidArray = &SidArrayToken2[SecondCount];
131
132 if (RtlEqualSid(FirstSidArray->Sid, SecondSidArray->Sid) &&
133 FirstSidArray->Attributes == SecondSidArray->Attributes)
134 {
135 break;
136 }
137 }
138
139 /* We've exhausted the array of the second token without finding this one */
140 if (SecondCount == CountSidArray2)
141 {
142 DPRINT("SepCompareSidAndAttributesFromTokens(): No matching elements could be found in either token!\n");
143 return FALSE;
144 }
145 }
146
147 return TRUE;
148}
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)

Referenced by SepCompareTokens().

◆ SepCompareTokens()

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

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.

  • Every SID that is present in either token is also present in the other one.
  • Both or none of the tokens are restricted.
  • If both tokens are restricted, every SID that is restricted in either token is also restricted in the other one.
  • Every privilege present in either token is also present in the other one.
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.

Definition at line 243 of file token.c.

247{
249 PAGED_CODE();
250
251 ASSERT(FirstToken != SecondToken);
252
253 /* Lock the tokens */
254 SepAcquireTokenLockShared(FirstToken);
255 SepAcquireTokenLockShared(SecondToken);
256
257 /* Check if every SID that is present in either token is also present in the other one */
258 if (!SepCompareSidAndAttributesFromTokens(FirstToken->UserAndGroups,
259 FirstToken->UserAndGroupCount,
260 SecondToken->UserAndGroups,
261 SecondToken->UserAndGroupCount))
262 {
263 goto Quit;
264 }
265
266 /* Is one token restricted but the other isn't? */
267 Restricted = SeTokenIsRestricted(FirstToken);
268 if (Restricted != SeTokenIsRestricted(SecondToken))
269 {
270 /* If that's the case then bail out */
271 goto Quit;
272 }
273
274 /*
275 * If both tokens are restricted check if every SID
276 * that is restricted in either token is also restricted
277 * in the other one.
278 */
279 if (Restricted)
280 {
281 if (!SepCompareSidAndAttributesFromTokens(FirstToken->RestrictedSids,
282 FirstToken->RestrictedSidCount,
283 SecondToken->RestrictedSids,
284 SecondToken->RestrictedSidCount))
285 {
286 goto Quit;
287 }
288 }
289
290 /* Check if every privilege present in either token is also present in the other one */
291 if (!SepComparePrivilegeAndAttributesFromTokens(FirstToken->Privileges,
292 FirstToken->PrivilegeCount,
293 SecondToken->Privileges,
294 SecondToken->PrivilegeCount))
295 {
296 goto Quit;
297 }
298
299 /* If we're here then the tokens are equal */
300 IsEqual = TRUE;
301 DPRINT("SepCompareTokens(): Tokens are equal!\n");
302
303Quit:
304 /* Unlock the tokens */
305 SepReleaseTokenLock(SecondToken);
306 SepReleaseTokenLock(FirstToken);
307
308 *Equal = IsEqual;
309 return STATUS_SUCCESS;
310}
UNICODE_STRING Restricted
Definition: utils.c:24
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 fo...
Definition: token.c:174
BOOLEAN NTAPI SeTokenIsRestricted(_In_ PACCESS_TOKEN Token)
Determines if a token is restricted or not, based upon the token flags.
Definition: token.c:2126
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 equa...
Definition: token.c:107

Referenced by NtCompareTokens(), and SeExchangePrimaryToken().

◆ SepComputeAvailableDynamicSpace()

ULONG SepComputeAvailableDynamicSpace ( _In_ ULONG  DynamicCharged,
_In_ PSID  PrimaryGroup,
_In_opt_ PACL  DefaultDacl 
)

Computes the exact available dynamic area of an access token whilst querying token statistics.

Parameters
[in]DynamicChargedThe current charged dynamic area of an access token. This must not be 0!
[in]PrimaryGroupA pointer to a primary group SID.
[in]DefaultDaclIf provided, this pointer points to a default DACL of an access token.
Returns
Returns the calculated available dynamic area.

Definition at line 659 of file token.c.

663{
664 ULONG DynamicAvailable;
665
666 PAGED_CODE();
667
668 /* A token's dynamic area is always charged */
669 ASSERT(DynamicCharged != 0);
670
671 /*
672 * Take into account the default DACL if
673 * the token has one. Otherwise the occupied
674 * space is just the present primary group.
675 */
676 DynamicAvailable = DynamicCharged - RtlLengthSid(PrimaryGroup);
677 if (DefaultDacl)
678 {
679 DynamicAvailable -= DefaultDacl->AclSize;
680 }
681
682 return DynamicAvailable;
683}
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID _Inout_ PULONG _Out_writes_bytes_to_opt_ PrimaryGroupSize PSID PrimaryGroup
Definition: rtlfuncs.h:1611

Referenced by NtQueryInformationToken(), and SeQueryInformationToken().

◆ SepCopyProxyData()

NTSTATUS NTAPI SepCopyProxyData ( _Out_ PVOID Dest,
_In_ PVOID  Src 
)

Copies the proxy data from the source into the destination of a token.

@unimplemented

Parameters
[out]DestThe destination path where the proxy data is to be copied to.
[in]SrcThe source path where the proxy data is be copied from.
Returns
To be added...

Definition at line 815 of file token.c.

818{
821}
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42

◆ SepCreateSystemAnonymousLogonToken()

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.

Returns
Returns the system's anonymous logon token if the operations have completed successfully.

Definition at line 1868 of file token.c.

1869{
1870 SID_AND_ATTRIBUTES UserSid;
1872 PTOKEN Token;
1873 ULONG GroupsLength;
1874 LARGE_INTEGER Expiration;
1877
1878 /* The token never expires */
1879 Expiration.QuadPart = -1;
1880
1881 /* The user is the anonymous logon */
1882 UserSid.Sid = SeAnonymousLogonSid;
1883 UserSid.Attributes = 0;
1884
1885 /* The primary group is also the anonymous logon */
1887
1888 /* The only group for the token is the World */
1889 SID_AND_ATTRIBUTES Groups[] =
1890 {
1892 };
1893 GroupsLength = sizeof(SID_AND_ATTRIBUTES) +
1894 SeLengthSid(Groups[0].Sid);
1895 ASSERT(GroupsLength <= (sizeof(Groups) * sizeof(ULONG)));
1896
1897 /* Initialise the object attributes for the token */
1900
1901 /* Create token */
1903 KernelMode,
1904 0,
1909 &Expiration,
1910 &UserSid,
1911 RTL_NUMBER_OF(Groups),
1912 Groups,
1913 GroupsLength,
1914 0,
1915 NULL,
1916 NULL,
1920 TRUE);
1922
1923 /* Return the anonymous logon token */
1924 return Token;
1925}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define SE_GROUP_MANDATORY
Definition: setypes.h:90
#define SE_GROUP_ENABLED_BY_DEFAULT
Definition: setypes.h:91
#define SE_GROUP_ENABLED
Definition: setypes.h:92
PACL SeSystemAnonymousLogonDacl
Definition: acl.c:22
PSID SeAnonymousLogonSid
Definition: se.h:213
PSID SeWorldSid
Definition: sid.c:25
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: tokenlif.c:97
TOKEN_SOURCE SeSystemTokenSource
Definition: token.c:19
LUID SeAnonymousAuthenticationId
Definition: token.c:21
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
LONGLONG QuadPart
Definition: typedefs.h:114
#define SeLengthSid(Sid)
Definition: sefuncs.h:570

Referenced by SepInitializationPhase0().

◆ SepCreateSystemAnonymousLogonTokenNoEveryone()

PTOKEN SepCreateSystemAnonymousLogonTokenNoEveryone ( VOID  )

Creates the anonymous logon token for the system. This kind of token doesn't include the everyone SID group (being SeWorldSid).

Returns
Returns the system's anonymous logon token if the operations have completed successfully.

Definition at line 1938 of file token.c.

1939{
1940 SID_AND_ATTRIBUTES UserSid;
1942 PTOKEN Token;
1943 LARGE_INTEGER Expiration;
1946
1947 /* The token never expires */
1948 Expiration.QuadPart = -1;
1949
1950 /* The user is the anonymous logon */
1951 UserSid.Sid = SeAnonymousLogonSid;
1952 UserSid.Attributes = 0;
1953
1954 /* The primary group is also the anonymous logon */
1956
1957 /* Initialise the object attributes for the token */
1960
1961 /* Create token */
1963 KernelMode,
1964 0,
1969 &Expiration,
1970 &UserSid,
1971 0,
1972 NULL,
1973 0,
1974 0,
1975 NULL,
1976 NULL,
1980 TRUE);
1982
1983 /* Return the anonymous (not including everyone) logon token */
1984 return Token;
1985}

Referenced by SepInitializationPhase0().

◆ SepCreateSystemProcessToken()

PTOKEN NTAPI SepCreateSystemProcessToken ( VOID  )

Creates the system process token.

Returns
Returns the system process token if the operations have completed successfully.

Definition at line 1753 of file token.c.

1754{
1755 ULONG GroupAttributes, OwnerAttributes;
1756 LARGE_INTEGER Expiration;
1757 SID_AND_ATTRIBUTES UserSid;
1758 ULONG GroupsLength;
1761 PSID Owner;
1762 PTOKEN Token;
1764
1765 /* Don't ever expire */
1766 Expiration.QuadPart = -1;
1767
1768 /* All groups mandatory and enabled */
1771
1772 /* User is Local System */
1773 UserSid.Sid = SeLocalSystemSid;
1774 UserSid.Attributes = 0;
1775
1776 /* Primary group is Local System */
1778
1779 /* Owner is Administrators */
1781
1782 /* Groups are Administrators, World, and Authenticated Users */
1783 SID_AND_ATTRIBUTES Groups[] =
1784 {
1785 {SeAliasAdminsSid, OwnerAttributes},
1786 {SeWorldSid, GroupAttributes},
1787 {SeAuthenticatedUsersSid, GroupAttributes},
1788 {SeLocalSid, SE_GROUP_ENABLED} // HACK: Temporarily add the local group. See CORE-18250.
1789 };
1790 GroupsLength = sizeof(SID_AND_ATTRIBUTES) +
1791 SeLengthSid(Groups[0].Sid) +
1792 SeLengthSid(Groups[1].Sid) +
1793 SeLengthSid(Groups[2].Sid) +
1794 SeLengthSid(Groups[3].Sid); // HACK
1795 ASSERT(GroupsLength <= (sizeof(Groups) * sizeof(ULONG)));
1796
1797 /* Setup the privileges */
1799 {
1814 {SeBackupPrivilege, 0},
1815 {SeRestorePrivilege, 0},
1820 {SeUndockPrivilege, 0},
1824 };
1825
1826 /* Setup the object attributes */
1829
1830 /* Create the token */
1832 KernelMode,
1833 0,
1838 &Expiration,
1839 &UserSid,
1840 RTL_NUMBER_OF(Groups),
1841 Groups,
1842 GroupsLength,
1844 Privileges,
1845 Owner,
1849 TRUE);
1851
1852 /* Return the token */
1853 return Token;
1854}
static const LUID SeCreateGlobalPrivilege
Definition: authpackage.c:168
static const LUID SeChangeNotifyPrivilege
Definition: authpackage.c:167
static const LUID SeImpersonatePrivilege
Definition: authpackage.c:169
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1609
#define SE_GROUP_OWNER
Definition: setypes.h:93
PSID SeLocalSystemSid
Definition: sid.c:38
const LUID SeDebugPrivilege
Definition: priv.c:39
const LUID SeCreateTokenPrivilege
Definition: priv.c:21
const LUID SeBackupPrivilege
Definition: priv.c:36
const LUID SeAssignPrimaryTokenPrivilege
Definition: priv.c:22
const LUID SeSystemtimePrivilege
Definition: priv.c:31
PSID SeAliasAdminsSid
Definition: sid.c:41
const LUID SeTcbPrivilege
Definition: priv.c:26
const LUID SeManageVolumePrivilege
Definition: priv.c:47
const LUID SeRestorePrivilege
Definition: priv.c:37
const LUID SeLoadDriverPrivilege
Definition: priv.c:29
const LUID SeIncreaseBasePriorityPrivilege
Definition: priv.c:33
const LUID SeLockMemoryPrivilege
Definition: priv.c:23
const LUID SeCreatePermanentPrivilege
Definition: priv.c:35
PSID SeLocalSid
Definition: sid.c:26
const LUID SeUndockPrivilege
Definition: priv.c:44
const LUID SeCreatePagefilePrivilege
Definition: priv.c:34
const LUID SeTakeOwnershipPrivilege
Definition: priv.c:28
const LUID SeProfileSingleProcessPrivilege
Definition: priv.c:32
const LUID SeShutdownPrivilege
Definition: priv.c:38
const LUID SeSystemEnvironmentPrivilege
Definition: priv.c:41
const LUID SeSecurityPrivilege
Definition: priv.c:27
PSID SeAuthenticatedUsersSid
Definition: sid.c:49
const LUID SeAuditPrivilege
Definition: priv.c:40
const LUID SeIncreaseQuotaPrivilege
Definition: priv.c:24
PACL SeSystemDefaultDacl
Definition: acl.c:17
LUID SeSystemAuthenticationId
Definition: token.c:20
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET * Privileges
Definition: sefuncs.h:17
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
#define SE_PRIVILEGE_ENABLED_BY_DEFAULT
Definition: setypes.h:62

Referenced by SepInitializationPhase0().

◆ SepCreateTokenLock()

NTSTATUS SepCreateTokenLock ( _Inout_ PTOKEN  Token)

Creates a lock for the token.

Parameters
[in,out]TokenA token which lock has to be created.
Returns
STATUS_SUCCESS if the pool allocation and resource initialisation have completed successfully, otherwise STATUS_INSUFFICIENT_RESOURCES on a pool allocation failure.

Definition at line 45 of file token.c.

47{
48 PAGED_CODE();
49
51 sizeof(ERESOURCE),
53 if (Token->TokenLock == NULL)
54 {
55 DPRINT1("SepCreateTokenLock(): Failed to allocate memory!\n");
57 }
58
60 return STATUS_SUCCESS;
61}
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define NonPagedPool
Definition: env_spec_w32.h:307
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define TAG_SE_TOKEN_LOCK
Definition: tag.h:162
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by SepCreateToken(), SepDuplicateToken(), and SepPerformTokenFiltering().

◆ SepDeleteToken()

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.

Parameters
[in]ObjectBodyThe object body that represents an access token object.
Returns
Nothing.

Definition at line 1605 of file token.c.

1607{
1609 PTOKEN AccessToken = (PTOKEN)ObjectBody;
1610
1611 DPRINT("SepDeleteToken()\n");
1612
1613 /* Remove the referenced logon session from token */
1614 if (AccessToken->LogonSession)
1615 {
1617 if (!NT_SUCCESS(Status))
1618 {
1619 /* Something seriously went wrong */
1620 DPRINT1("SepDeleteToken(): Failed to remove the logon session from token (Status: 0x%lx)\n", Status);
1621 return;
1622 }
1623 }
1624
1625 /* Dereference the logon session */
1626 if ((AccessToken->TokenFlags & TOKEN_SESSION_NOT_REFERENCED) == 0)
1628
1629 /* Delete the token lock */
1630 if (AccessToken->TokenLock)
1631 SepDeleteTokenLock(AccessToken);
1632
1633 /* Delete the dynamic information area */
1634 if (AccessToken->DynamicPart)
1636}
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
NTSTATUS NTAPI SepRmRemoveLogonSessionFromToken(_Inout_ PTOKEN Token)
Removes a logon session from an access token.
Definition: srm.c:449
NTSTATUS SepRmDereferenceLogonSession(_Inout_ PLUID LogonLuid)
VOID SepDeleteTokenLock(_Inout_ PTOKEN Token)
Deletes a lock of a token.
Definition: token.c:74
ULONG TokenFlags
Definition: setypes.h:241
PERESOURCE TokenLock
Definition: setypes.h:222
PULONG DynamicPart
Definition: setypes.h:237
PSEP_LOGON_SESSION_REFERENCES LogonSession
Definition: setypes.h:245
#define TAG_TOKEN_DYNAMIC
Definition: tag.h:158
#define TOKEN_SESSION_NOT_REFERENCED
Definition: setypes.h:1184

Referenced by SepInitializeTokenImplementation().

◆ SepDeleteTokenLock()

VOID SepDeleteTokenLock ( _Inout_ PTOKEN  Token)

Deletes a lock of a token.

Parameters
[in,out]TokenA token which contains the lock.
Returns
Nothing.

Definition at line 74 of file token.c.

76{
77 PAGED_CODE();
78
79 ExDeleteResourceLite(Token->TokenLock);
81}
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647

Referenced by SepDeleteToken().

◆ SepFindPrimaryGroupAndDefaultOwner()

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.

Parameters
[in]TokenAccess token to begin the search query of primary group and default owner.
[in]PrimaryGroupA primary group SID to be used for search query, determining if user & groups of a token and the submitted primary group do match.
[in]DefaultOwnerThe default owner. If specified, it's used to determine if the token belongs to the actual user, that is, being the owner himself.
[out]PrimaryGroupIndexReturns the primary group index.
[out]DefaultOwnerIndexReturns the default owner index.
Returns
Returns STATUS_SUCCESS if the find query operation has completed successfully and that at least one search result is requested by the caller. STATUS_INVALID_PARAMETER is returned if the caller hasn't requested any search result. STATUS_INVALID_OWNER is returned if the specified default user owner does not match with the other user from the token. STATUS_INVALID_PRIMARY_GROUP is returned if the specified default primary group does not match with the other group from the token.

Definition at line 1011 of file token.c.

1017{
1018 ULONG i;
1019
1020 /* We should return at least a search result */
1021 if (!PrimaryGroupIndex && !DefaultOwnerIndex)
1023
1024 if (PrimaryGroupIndex)
1025 {
1026 /* Initialize with an invalid index */
1027 // Token->PrimaryGroup = NULL;
1028 *PrimaryGroupIndex = Token->UserAndGroupCount;
1029 }
1030
1031 if (DefaultOwnerIndex)
1032 {
1033 if (DefaultOwner)
1034 {
1035 /* An owner is specified: check whether this is actually the user */
1036 if (RtlEqualSid(Token->UserAndGroups[0].Sid, DefaultOwner))
1037 {
1038 /*
1039 * It's the user (first element in array): set it
1040 * as the owner and stop the search for it.
1041 */
1042 *DefaultOwnerIndex = 0;
1043 DefaultOwnerIndex = NULL;
1044 }
1045 else
1046 {
1047 /* An owner is specified: initialize with an invalid index */
1048 *DefaultOwnerIndex = Token->UserAndGroupCount;
1049 }
1050 }
1051 else
1052 {
1053 /*
1054 * No owner specified: set the user (first element in array)
1055 * as the owner and stop the search for it.
1056 */
1057 *DefaultOwnerIndex = 0;
1058 DefaultOwnerIndex = NULL;
1059 }
1060 }
1061
1062 /* Validate and set the primary group and default owner indices */
1063 for (i = 0; i < Token->UserAndGroupCount; i++)
1064 {
1065 /* Stop the search if we have found what we searched for */
1066 if (!PrimaryGroupIndex && !DefaultOwnerIndex)
1067 break;
1068
1069 if (DefaultOwnerIndex && DefaultOwner &&
1070 RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner) &&
1071 (Token->UserAndGroups[i].Attributes & SE_GROUP_OWNER))
1072 {
1073 /* Owner is found, stop the search for it */
1074 *DefaultOwnerIndex = i;
1075 DefaultOwnerIndex = NULL;
1076 }
1077
1078 if (PrimaryGroupIndex &&
1079 RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
1080 {
1081 /* Primary group is found, stop the search for it */
1082 // Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
1083 *PrimaryGroupIndex = i;
1084 PrimaryGroupIndex = NULL;
1085 }
1086 }
1087
1088 if (DefaultOwnerIndex)
1089 {
1090 if (*DefaultOwnerIndex == Token->UserAndGroupCount)
1091 return STATUS_INVALID_OWNER;
1092 }
1093
1094 if (PrimaryGroupIndex)
1095 {
1096 if (*PrimaryGroupIndex == Token->UserAndGroupCount)
1097 // if (Token->PrimaryGroup == NULL)
1099 }
1100
1101 return STATUS_SUCCESS;
1102}
#define STATUS_INVALID_PRIMARY_GROUP
Definition: ntstatus.h:327
#define STATUS_INVALID_OWNER
Definition: ntstatus.h:326
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135

Referenced by NtSetInformationToken(), SepCreateToken(), SepDuplicateToken(), and SepPerformTokenFiltering().

◆ SepFreeProxyData()

VOID NTAPI SepFreeProxyData ( _Inout_ PVOID  ProxyData)

Frees (de-allocates) the proxy data memory block of a token.

@unimplemented

Parameters
[in,out]ProxyDataThe proxy data to be freed.
Returns
Nothing.

Definition at line 793 of file token.c.

795{
797}

◆ SepImpersonateAnonymousToken()

static NTSTATUS SepImpersonateAnonymousToken ( _In_ PETHREAD  Thread,
_In_ KPROCESSOR_MODE  PreviousMode 
)
static

Private function that impersonates the system's anonymous logon token. The major bulk of the impersonation procedure is done here.

Parameters
[in]ThreadThe executive thread object that is to impersonate the client.
[in]PreviousModeThe access processor mode, indicating if the call is executed in kernel or user mode.
Returns
Returns STATUS_SUCCESS if the impersonation has succeeded. STATUS_UNSUCCESSFUL is returned if the primary token couldn't be obtained from the current process to perform additional tasks. STATUS_ACCESS_DENIED is returned if the process' primary token is restricted, which for this matter we cannot impersonate onto a restricted process. Otherwise a failure NTSTATUS code is returned.

Definition at line 334 of file token.c.

337{
339 PTOKEN TokenToImpersonate, ProcessToken;
340 ULONG IncludeEveryoneValueData;
341 PAGED_CODE();
342
343 /*
344 * We must check first which kind of token
345 * shall we assign for the thread to impersonate,
346 * the one with Everyone Group SID or the other
347 * without. Invoke the registry helper to
348 * return the data value for us.
349 */
350 Status = SepRegQueryHelper(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Lsa",
351 L"EveryoneIncludesAnonymous",
352 REG_DWORD,
353 sizeof(IncludeEveryoneValueData),
354 &IncludeEveryoneValueData);
355 if (!NT_SUCCESS(Status))
356 {
357 DPRINT1("SepRegQueryHelper(): Failed to query the registry value (Status 0x%lx)\n", Status);
358 return Status;
359 }
360
361 if (IncludeEveryoneValueData == 0)
362 {
363 DPRINT("SepImpersonateAnonymousToken(): Assigning the token not including the Everyone Group SID...\n");
364 TokenToImpersonate = SeAnonymousLogonTokenNoEveryone;
365 }
366 else
367 {
368 DPRINT("SepImpersonateAnonymousToken(): Assigning the token including the Everyone Group SID...\n");
369 TokenToImpersonate = SeAnonymousLogonToken;
370 }
371
372 /*
373 * Tell the object manager that we're going to use this token
374 * object now by incrementing the reference count.
375 */
376 Status = ObReferenceObjectByPointer(TokenToImpersonate,
380 if (!NT_SUCCESS(Status))
381 {
382 DPRINT1("SepImpersonateAnonymousToken(): Couldn't be able to use the token, bail out...\n");
383 return Status;
384 }
385
386 /*
387 * Reference the primary token of the current process that the anonymous
388 * logon token impersonation procedure is being performed. We'll be going
389 * to use the process' token to figure out if the process is actually
390 * restricted or not.
391 */
393 if (!ProcessToken)
394 {
395 DPRINT1("SepImpersonateAnonymousToken(): Couldn't be able to get the process' primary token, bail out...\n");
396 ObDereferenceObject(TokenToImpersonate);
397 return STATUS_UNSUCCESSFUL;
398 }
399
400 /* Now, is the token from the current process restricted? */
401 if (SeTokenIsRestricted(ProcessToken))
402 {
403 DPRINT1("SepImpersonateAnonymousToken(): The process is restricted, can't do anything. Bail out...\n");
404 PsDereferencePrimaryToken(ProcessToken);
405 ObDereferenceObject(TokenToImpersonate);
407 }
408
409 /*
410 * Finally it's time to impersonate! But first, fast dereference the
411 * process' primary token as we no longer need it.
412 */
415 if (!NT_SUCCESS(Status))
416 {
417 DPRINT1("SepImpersonateAnonymousToken(): Failed to impersonate, bail out...\n");
418 ObDereferenceObject(TokenToImpersonate);
419 return Status;
420 }
421
422 return Status;
423}
@ SecurityImpersonation
Definition: lsa.idl:57
PTOKEN SeAnonymousLogonToken
Definition: semgr.c:19
NTSTATUS NTAPI SepRegQueryHelper(_In_ PCWSTR KeyName, _In_ PCWSTR ValueName, _In_ ULONG ValueType, _In_ ULONG DataLength, _Out_ PVOID ValueData)
A private registry helper that returns the desired value data based on the specifics requested by the...
Definition: srm.c:93
PTOKEN SeAnonymousLogonTokenNoEveryone
Definition: semgr.c:20
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
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
#define REG_DWORD
Definition: sdbapi.c:596
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define TOKEN_IMPERSONATE
Definition: setypes.h:927

Referenced by NtImpersonateAnonymousToken().

◆ SepInitializeTokenImplementation()

VOID NTAPI SepInitializeTokenImplementation ( VOID  )

Internal function that initializes critical kernel data for access token implementation in SRM.

Returns
Nothing.

Definition at line 1649 of file token.c.

1650{
1652 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
1653
1654 DPRINT("Creating Token Object Type\n");
1655
1656 /* Initialize the Token type */
1657 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
1658 RtlInitUnicodeString(&Name, L"Token");
1659 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
1660 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
1661 ObjectTypeInitializer.SecurityRequired = TRUE;
1662 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(TOKEN);
1663 ObjectTypeInitializer.GenericMapping = SepTokenMapping;
1664 ObjectTypeInitializer.PoolType = PagedPool;
1665 ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS;
1666 ObjectTypeInitializer.UseDefaultObject = TRUE;
1667 ObjectTypeInitializer.DeleteProcedure = SepDeleteToken;
1668 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &SeTokenObjectType);
1669}
struct NameRec_ * Name
Definition: cdprocs.h:460
#define PagedPool
Definition: env_spec_w32.h:308
#define OBJ_OPENLINK
Definition: winternl.h:230
struct _TOKEN TOKEN
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
VOID NTAPI SepDeleteToken(_In_ PVOID ObjectBody)
Internal function that deals with access token object destruction and deletion. The function is used ...
Definition: token.c:1605
static GENERIC_MAPPING SepTokenMapping
Definition: token.c:23
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1136
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define TOKEN_ALL_ACCESS
Definition: setypes.h:946

Referenced by SepInitializationPhase0().

◆ SepOpenThreadToken()

static NTSTATUS SepOpenThreadToken ( _In_ PETHREAD  Thread,
_In_ HANDLE  ThreadHandle,
_In_ PTOKEN  ThreadToken,
_In_ ACCESS_MASK  DesiredAccess,
_In_ ULONG  HandleAttributes,
_In_ BOOLEAN  EffectiveOnly,
_In_ BOOLEAN  CopyOnOpen,
_In_ SECURITY_IMPERSONATION_LEVEL  ImpersonationLevel,
_In_ KPROCESSOR_MODE  PreviousMode,
_Out_ PHANDLE  OpenedTokenHandle 
)
static

Internal private function that returns an opened handle of an access token associated with a thread.

Parameters
[in]ThreadA pointer to a Executive thread. This parameter is used to validate that the newly obtained thread in this function hasn't diverged. This could potentially lead to a scenario that we might get an access token from a different token which is not what we want. The validation is performed if the token has to copied and can't be opened directly.
[in]ThreadHandleA handle to a thread, of which an access token is to be opened and given from that thread.
[in]ThreadTokenA pointer to an access token associated with the specific thread. The function assumes that the token is an impersonation one prior the calling of this function.
[in]DesiredAccessThe desired access rights for the access token.
[in]HandleAttributesHandle attributes of which they are used for the newly creation of the opened thread token. The function assumes that they have been validated prior the calling of this function.
[in]EffectiveOnlyIf set to TRUE, the function will copy a new access token with privileges and groups that are effectively enabled. Any disabled privilege or group is removed from the copied token. Otherwise if set to FALSE, the function retains all the enabled and disabled privielges and groups.
[in]CopyOnOpenIf set to TRUE, it tells the function that the access token cannot be directly opened due to the security impersonation info of the associated thread being enforced. In this case the function will make a copy of the said token by duplicating it. Otherwise if set to FALSE, the function will just open the access token directly.
[in]ImpersonationLevelThe security impersonation level, at which it is allowed to access the token.
[in]PreviousModeThe processor request level mode.
[out]OpenedTokenHandleA pointer to an opened access token handle associated with the specific thread, returned to the caller. Initially this parameter is set to NULL and if the function fails to open the thread's token, it will stay NULL.
Returns
Returns STATUS_SUCCESS if the function has successfully opened the thread's token. STATUS_OBJECT_TYPE_MISMATCH is returned if the obtained thread object no longer matches with the other thread that has been obtained previously. STATUS_NO_TOKEN is returned if the associated thread's process has no primary access token. A failure NTSTATUS code is returned otherwise.

Definition at line 1170 of file token.c.

1181{
1186 PTOKEN NewToken, PrimaryToken;
1188 PACL Dacl;
1189
1190 PAGED_CODE();
1191
1192 /* Assume no opened token handle at first */
1193 *OpenedTokenHandle = NULL;
1194
1195 /* Check if we have to do a copy of the token on open or not */
1196 if (!CopyOnOpen)
1197 {
1198 /* Just open the thread's token directly */
1199 Status = ObOpenObjectByPointer(ThreadToken,
1201 NULL,
1205 &TokenHandle);
1206 if (!NT_SUCCESS(Status))
1207 {
1208 DPRINT1("Failed to open the thread's token object (Status 0x%lx)\n", Status);
1209 return Status;
1210 }
1211
1212 /* Give it to caller */
1213 *OpenedTokenHandle = TokenHandle;
1214 return STATUS_SUCCESS;
1215 }
1216
1217 /*
1218 * The caller asks to do a copy of that token whilst it's opened.
1219 * Obtain a thread object again but this time we have to obtain
1220 * it in our side, kernel mode, and request all the access needed
1221 * to do a copy of the token because the original thread only has
1222 * query access needed for access token validation.
1223 */
1224 Status = ObReferenceObjectByHandle(ThreadHandle,
1227 KernelMode,
1228 (PVOID*)&Thread2,
1229 NULL);
1230 if (!NT_SUCCESS(Status))
1231 {
1232 DPRINT1("Failed to reference the object thread (Status 0x%lx)\n", Status);
1233 return Status;
1234 }
1235
1236 /* Check that one of the threads hasn't diverged */
1237 if (Thread != Thread2)
1238 {
1239 DPRINT1("One of the threads aren't the same (original thread 0x%p, thread 0x%p)\n", Thread, Thread2);
1242 }
1243
1244 /* Reference the primary token of the process' thread */
1245 PrimaryToken = PsReferencePrimaryToken(Thread2->ThreadsProcess);
1246 if (!PrimaryToken)
1247 {
1248 DPRINT1("Failed to reference the primary token of thread\n");
1250 return STATUS_NO_TOKEN;
1251 }
1252
1253 /* Create an impersonation DACL from the tokens we got */
1254 Status = SepCreateImpersonationTokenDacl(ThreadToken, PrimaryToken, &Dacl);
1255 ObFastDereferenceObject(&Thread2->ThreadsProcess->Token, PrimaryToken);
1256 if (!NT_SUCCESS(Status))
1257 {
1258 DPRINT1("Failed to create an impersonation token DACL (Status 0x%lx)\n", Status);
1260 return Status;
1261 }
1262
1263 /* Create a security descriptor with the DACL we got */
1266 if (!NT_SUCCESS(Status))
1267 {
1268 DPRINT1("Failed to create a security descriptor (Status 0x%lx)\n", Status);
1271 return Status;
1272 }
1273
1274 /* Attach the DACL to that security descriptor */
1276 TRUE,
1277 Dacl,
1278 FALSE);
1279 if (!NT_SUCCESS(Status))
1280 {
1281 DPRINT1("Failed to set the DACL to the security descriptor (Status 0x%lx)\n", Status);
1284 return Status;
1285 }
1286
1287 /*
1288 * Initialize the object attributes for the token we
1289 * are going to duplicate.
1290 */
1292 NULL,
1294 NULL,
1296
1297 /* Duplicate (copy) it now */
1298 Status = SepDuplicateToken(ThreadToken,
1303 KernelMode,
1304 &NewToken);
1305 if (!NT_SUCCESS(Status))
1306 {
1307 DPRINT1("Failed to duplicate the token (Status 0x%lx)\n", Status);
1310 return Status;
1311 }
1312
1313 /* Insert that copied token into the handle now */
1314 ObReferenceObject(NewToken);
1315 Status = ObInsertObject(NewToken,
1316 NULL,
1318 0,
1319 NULL,
1320 &TokenHandle);
1321 if (!NT_SUCCESS(Status))
1322 {
1323 DPRINT1("Failed to insert the token object (Status 0x%lx)\n", Status);
1325 ObDereferenceObject(NewToken);
1327 return Status;
1328 }
1329
1330 /* We're almost done, free the DACL if we got one */
1332
1333 /* Impersonate the client finally */
1335 if (!NT_SUCCESS(Status))
1336 {
1337 DPRINT1("Failed to impersonate the client (Status 0x%lx)\n", Status);
1338 ObDereferenceObject(NewToken);
1340 return Status;
1341 }
1342
1343 /* Give the newly opened token handle to caller */
1344 *OpenedTokenHandle = TokenHandle;
1345 ObDereferenceObject(NewToken);
1347 return Status;
1348}
static DWORD WINAPI Thread2(_Inout_opt_ PVOID Parameter)
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: d3dkmdt.h:46
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1605
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
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
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:2935
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:2742
#define TAG_ACL
Definition: tag.h:151
_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:191
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58

Referenced by NtOpenThreadTokenEx().

◆ SepRebuildDynamicPartOfToken()

NTSTATUS SepRebuildDynamicPartOfToken ( _Inout_ PTOKEN  AccessToken,
_In_ ULONG  NewDynamicPartSize 
)

Re-builds the dynamic part area of an access token during an a default DACL or primary group replacement within the said token if the said dynamic area can't hold the new security content.

Parameters
[in]AccessTokenA pointer to an access token where its dynamic part is to be re-built and expanded based upon the new dynamic part size provided by the caller. Dynamic part expansion is not always guaranteed. See Remarks for further information.
[in]NewDynamicPartSizeThe new dynamic part size.
Returns
Returns STATUS_SUCCESS if the function has completed its operations successfully. STATUS_INSUFFICIENT_RESOURCES is returned if the new dynamic part could not be allocated.
Remarks
STATUS_SUCCESS does not indicate if the function has re-built the dynamic part of a token. If the current dynamic area size suffices the new dynamic area length provided by the caller then the dynamic area can hold the new security content buffer so dynamic part expansion is not necessary.

Definition at line 715 of file token.c.

718{
719 PVOID NewDynamicPart;
720 PVOID PreviousDynamicPart;
721 ULONG CurrentDynamicLength;
722
723 PAGED_CODE();
724
725 /* Sanity checks */
726 ASSERT(AccessToken);
727 ASSERT(NewDynamicPartSize != 0);
728
729 /*
730 * Compute the exact length of the available
731 * dynamic part of the access token.
732 */
733 CurrentDynamicLength = AccessToken->DynamicAvailable + RtlLengthSid(AccessToken->PrimaryGroup);
734 if (AccessToken->DefaultDacl)
735 {
736 CurrentDynamicLength += AccessToken->DefaultDacl->AclSize;
737 }
738
739 /*
740 * Figure out if the current dynamic part is too small
741 * to fit new contents inside the said dynamic part.
742 * Rebuild the dynamic area and expand it if necessary.
743 */
744 if (CurrentDynamicLength < NewDynamicPartSize)
745 {
746 NewDynamicPart = ExAllocatePoolWithTag(PagedPool,
747 NewDynamicPartSize,
749 if (NewDynamicPart == NULL)
750 {
751 DPRINT1("SepRebuildDynamicPartOfToken(): Insufficient resources to allocate new dynamic part!\n");
753 }
754
755 /* Copy the existing dynamic part */
756 PreviousDynamicPart = AccessToken->DynamicPart;
757 RtlCopyMemory(NewDynamicPart, PreviousDynamicPart, CurrentDynamicLength);
758
759 /* Update the available dynamic area and assign new dynamic */
760 AccessToken->DynamicAvailable += NewDynamicPartSize - CurrentDynamicLength;
761 AccessToken->DynamicPart = NewDynamicPart;
762
763 /* Move the contents (primary group and default DACL) addresses as well */
764 AccessToken->PrimaryGroup = (PSID)((ULONG_PTR)AccessToken->DynamicPart +
765 ((ULONG_PTR)AccessToken->PrimaryGroup - (ULONG_PTR)PreviousDynamicPart));
766 if (AccessToken->DefaultDacl != NULL)
767 {
768 AccessToken->DefaultDacl = (PACL)((ULONG_PTR)AccessToken->DynamicPart +
769 ((ULONG_PTR)AccessToken->DefaultDacl - (ULONG_PTR)PreviousDynamicPart));
770 }
771
772 /* And discard the previous dynamic part */
773 DPRINT("SepRebuildDynamicPartOfToken(): The dynamic part has been re-built with success!\n");
774 ExFreePoolWithTag(PreviousDynamicPart, TAG_TOKEN_DYNAMIC);
775 }
776
777 return STATUS_SUCCESS;
778}
#define ULONG_PTR
Definition: config.h:101
struct _SID * PSID
Definition: eventlog.c:35
struct _ACL * PACL
Definition: security.c:105
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65

◆ SepRemovePrivilegeToken()

VOID SepRemovePrivilegeToken ( _Inout_ PTOKEN  Token,
_In_ ULONG  Index 
)

Removes a privilege from the token.

Parameters
[in,out]TokenThe token where the privilege is to be removed.
[in]IndexThe index count which represents the number position of the privilege we want to remove.
Returns
Nothing.

Definition at line 582 of file token.c.

585{
586 ULONG MoveCount;
587 ASSERT(Index < Token->PrivilegeCount);
588
589 /* Calculate the number of trailing privileges */
590 MoveCount = Token->PrivilegeCount - Index - 1;
591 if (MoveCount != 0)
592 {
593 /* Move them one location ahead */
594 RtlMoveMemory(&Token->Privileges[Index],
595 &Token->Privileges[Index + 1],
596 MoveCount * sizeof(LUID_AND_ATTRIBUTES));
597 }
598
599 /* Update privilege count */
600 Token->PrivilegeCount--;
601}
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
_In_ WDFCOLLECTION _In_ ULONG Index

Referenced by SepAdjustPrivileges(), SepDuplicateToken(), and SepPerformTokenFiltering().

◆ SepRemoveUserGroupToken()

VOID SepRemoveUserGroupToken ( _Inout_ PTOKEN  Token,
_In_ ULONG  Index 
)

Removes a group from the token.

Parameters
[in,out]TokenThe token where the group is to be removed.
[in]IndexThe index count which represents the number position of the group we want to remove.
Returns
Nothing.

Definition at line 618 of file token.c.

621{
622 ULONG MoveCount;
623 ASSERT(Index < Token->UserAndGroupCount);
624
625 /* Calculate the number of trailing groups */
626 MoveCount = Token->UserAndGroupCount - Index - 1;
627 if (MoveCount != 0)
628 {
629 /* Time to remove the group by moving one location ahead */
630 RtlMoveMemory(&Token->UserAndGroups[Index],
631 &Token->UserAndGroups[Index + 1],
632 MoveCount * sizeof(SID_AND_ATTRIBUTES));
633 }
634
635 /* Remove one group count */
636 Token->UserAndGroupCount--;
637}

Referenced by SepDuplicateToken().

◆ SepTokenIsOwner()

BOOLEAN NTAPI SepTokenIsOwner ( _In_ PACCESS_TOKEN  _Token,
_In_ PSECURITY_DESCRIPTOR  SecurityDescriptor,
_In_ BOOLEAN  TokenLocked 
)

Checks if a token belongs to the main user, being the owner.

Parameters
[in]_TokenA valid token object.
[in]SecurityDescriptorA security descriptor where the owner is to be found.
[in]TokenLockedIf set to TRUE, the token has been already locked and there's no need to lock it again. Otherwise the function will acquire the lock.
Returns
Returns TRUE if the token belongs to a owner, FALSE otherwise.

Definition at line 511 of file token.c.

515{
516 PSID Sid;
518 PTOKEN Token = _Token;
519
520 /* Get the owner SID */
522 ASSERT(Sid != NULL);
523
524 /* Lock the token if needed */
525 if (!TokenLocked) SepAcquireTokenLockShared(Token);
526
527 /* Check if the owner SID is found, handling restricted case as well */
529 if ((Result) && (Token->TokenFlags & TOKEN_IS_RESTRICTED))
530 {
532 }
533
534 /* Release the lock if we had acquired it */
535 if (!TokenLocked) SepReleaseTokenLock(Token);
536
537 /* Return the result */
538 return Result;
539}
FORCEINLINE PSID SepGetOwnerFromDescriptor(_Inout_ PSECURITY_DESCRIPTOR _Descriptor)
Definition: se.h:109
BOOLEAN NTAPI SepSidInToken(_In_ PACCESS_TOKEN _Token, _In_ PSID Sid)
Checks if a SID is present in a token.
Definition: sid.c:547
BOOLEAN NTAPI SepSidInTokenEx(_In_ PACCESS_TOKEN _Token, _In_ PSID PrincipalSelfSid, _In_ PSID _Sid, _In_ BOOLEAN Deny, _In_ BOOLEAN Restricted)
Checks if a SID is present in a token.
Definition: sid.c:443
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define TOKEN_IS_RESTRICTED
Definition: setypes.h:1183

Referenced by SeAccessCheck(), and SepAccessCheck().

◆ SepUpdatePrivilegeFlagsToken()

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.

Parameters
[in,out]TokenThe token where the flags are to be changed.
Returns
Nothing.

Definition at line 554 of file token.c.

556{
557 ULONG i;
558
559 /* Loop all privileges */
560 for (i = 0; i < Token->PrivilegeCount; i++)
561 {
562 /* Updates the flags for this privilege */
564 }
565}
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:442

Referenced by SepCreateToken().

◆ SepUpdateSinglePrivilegeFlagToken()

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.

Parameters
[in,out]TokenThe token where the flags are to be changed.
[in]IndexThe index count which represents the total sum of privileges. The count in question MUST NOT exceed the expected privileges count of the token.
Returns
Nothing.

Definition at line 442 of file token.c.

445{
446 ULONG TokenFlag;
447 ASSERT(Index < Token->PrivilegeCount);
448
449 /* The high part of all values we are interested in is 0 */
450 if (Token->Privileges[Index].Luid.HighPart != 0)
451 {
452 return;
453 }
454
455 /* Check for certain privileges to update flags */
456 if (Token->Privileges[Index].Luid.LowPart == SE_CHANGE_NOTIFY_PRIVILEGE)
457 {
459 }
460 else if (Token->Privileges[Index].Luid.LowPart == SE_BACKUP_PRIVILEGE)
461 {
462 TokenFlag = TOKEN_HAS_BACKUP_PRIVILEGE;
463 }
464 else if (Token->Privileges[Index].Luid.LowPart == SE_RESTORE_PRIVILEGE)
465 {
466 TokenFlag = TOKEN_HAS_RESTORE_PRIVILEGE;
467 }
468 else if (Token->Privileges[Index].Luid.LowPart == SE_IMPERSONATE_PRIVILEGE)
469 {
471 }
472 else
473 {
474 /* Nothing to do */
475 return;
476 }
477
478 /* Check if the specified privilege is enabled */
479 if (Token->Privileges[Index].Attributes & SE_PRIVILEGE_ENABLED)
480 {
481 /* It is enabled, so set the flag */
482 Token->TokenFlags |= TokenFlag;
483 }
484 else
485 {
486 /* Is is disabled, so remove the flag */
487 Token->TokenFlags &= ~TokenFlag;
488 }
489}
#define SE_IMPERSONATE_PRIVILEGE
Definition: security.c:683
#define SE_BACKUP_PRIVILEGE
Definition: security.c:671
#define SE_RESTORE_PRIVILEGE
Definition: security.c:672
#define SE_CHANGE_NOTIFY_PRIVILEGE
Definition: security.c:677
#define TOKEN_HAS_TRAVERSE_PRIVILEGE
Definition: setypes.h:1178
#define TOKEN_HAS_BACKUP_PRIVILEGE
Definition: setypes.h:1179
#define TOKEN_HAS_IMPERSONATE_PRIVILEGE
Definition: setypes.h:1186
#define TOKEN_HAS_RESTORE_PRIVILEGE
Definition: setypes.h:1180

Referenced by SepAdjustPrivileges(), SepPerformTokenFiltering(), and SepUpdatePrivilegeFlagsToken().

◆ SeQueryAuthenticationIdToken()

NTSTATUS NTAPI SeQueryAuthenticationIdToken ( _In_ PACCESS_TOKEN  Token,
_Out_ PLUID  LogonId 
)

Queries the authentication ID of an access token.

Parameters
[in]TokenA valid access token where the authentication ID has to be gathered.
[out]pSessionIdThe returned pointer to an authentication ID to the caller.
Returns
Returns STATUS_SUCCESS.

Definition at line 2036 of file token.c.

2039{
2040 PAGED_CODE();
2041
2042 *LogonId = ((PTOKEN)Token)->AuthenticationId;
2043
2044 return STATUS_SUCCESS;
2045}
_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 LogonId

Referenced by GetProcessLuid(), KsecGetKeyData(), nfs41_GetLUID(), NtSetUuidSeed(), ObpReferenceDeviceMap(), ObpSetCurrentProcessDeviceMap(), RxGetUid(), and RxInitializeVNetRootParameters().

◆ SeQuerySessionIdToken()

NTSTATUS NTAPI SeQuerySessionIdToken ( _In_ PACCESS_TOKEN  Token,
_Out_ PULONG  pSessionId 
)

Queries the session ID of an access token.

Parameters
[in]TokenA valid access token where the session ID has to be gathered.
[out]pSessionIdThe returned pointer to a session ID to the caller.
Returns
Returns STATUS_SUCCESS.

Definition at line 2004 of file token.c.

2007{
2008 PAGED_CODE();
2009
2010 /* Lock the token */
2012
2013 *pSessionId = ((PTOKEN)Token)->SessionId;
2014
2015 /* Unlock the token */
2017
2018 return STATUS_SUCCESS;
2019}

Referenced by NtQueryInformationToken(), RxGetSessionId(), RxInitializeVNetRootParameters(), and SeQueryInformationToken().

◆ SeSubProcessToken()

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.

Parameters
[in]ParentTokenThe parent access token for duplication.
[out]TokenThe new duplicated token.
[in]InUseSet this to TRUE if the token is about to be used immediately after the call execution of this function, FALSE otherwise.
[in]SessionIdSession ID for the token to be assigned.
Returns
Returns STATUS_SUCCESS if token subtracting and duplication have completed successfully. A failure NTSTATUS code is returned otherwise.

Definition at line 1373 of file token.c.

1378{
1379 PTOKEN NewToken;
1382
1383 /* Initialize the attributes and duplicate it */
1385 Status = SepDuplicateToken(ParentToken,
1387 FALSE,
1389 ParentToken->ImpersonationLevel,
1390 KernelMode,
1391 &NewToken);
1392 if (NT_SUCCESS(Status))
1393 {
1394 /* Insert it */
1395 Status = ObInsertObject(NewToken,
1396 NULL,
1397 0,
1398 0,
1399 NULL,
1400 NULL);
1401 if (NT_SUCCESS(Status))
1402 {
1403 /* Set the session ID */
1404 NewToken->SessionId = SessionId;
1405 NewToken->TokenInUse = InUse;
1406
1407 /* Return the token */
1408 *Token = NewToken;
1409 }
1410 }
1411
1412 /* Return status */
1413 return Status;
1414}
ULONG SessionId
Definition: dllmain.c:28

Referenced by PspInitializeProcessSecurity().

◆ SeTokenCanImpersonate()

BOOLEAN NTAPI SeTokenCanImpersonate ( _In_ PTOKEN  ProcessToken,
_In_ PTOKEN  TokenToImpersonate,
_In_ SECURITY_IMPERSONATION_LEVEL  ImpersonationLevel 
)

Determines whether the server is allowed to impersonate on behalf of a client or not. For further details, see Remarks.

Parameters
[in]ProcessTokenA pointer to the primary access token of the server process that requests impersonation of the client target.
[in]TokenToImpersonateA pointer to an access token that represents a client that is to be impersonated.
[in]ImpersonationLevelThe requested impersonation level.
Returns
Returns TRUE if the conditions checked are met for token impersonation, FALSE otherwise.
Remarks
The server has to meet the following criteria in order to impersonate a client, that is:
  • The server must not impersonate a client beyond the level that the client imposed on itself.
  • The server must be authenticated on the same logon session of the target client.
  • IF NOT then the server's user ID has to match to that of the target client.
  • The server must not be restricted in order to impersonate a client that is not restricted.

If the associated access token that represents the security properties of the server is granted the SeImpersonatePrivilege privilege the server is given immediate impersonation, regardless of the conditions above. If the client in question is associated with an anonymous token then the server is given immediate impersonation. Or if the server simply doesn't ask for impersonation but instead it wants to get the security identification of a client, the server is given immediate impersonation.

Definition at line 2207 of file token.c.

2211{
2212 BOOLEAN CanImpersonate;
2213 PAGED_CODE();
2214
2215 /*
2216 * The server may want to obtain identification details of a client
2217 * instead of impersonating so just give the server a pass.
2218 */
2220 {
2221 DPRINT("The server doesn't ask for impersonation\n");
2222 return TRUE;
2223 }
2224
2225 /* Time to lock our tokens */
2226 SepAcquireTokenLockShared(ProcessToken);
2227 SepAcquireTokenLockShared(TokenToImpersonate);
2228
2229 /*
2230 * As the name implies, an anonymous token has invisible security
2231 * identification details. By the general rule these tokens do not
2232 * pose a danger in terms of power escalation so give the server a pass.
2233 */
2234 if (RtlEqualLuid(&TokenToImpersonate->AuthenticationId,
2236 {
2237 DPRINT("The token to impersonate has an anonymous authentication ID, allow impersonation either way\n");
2238 CanImpersonate = TRUE;
2239 goto Quit;
2240 }
2241
2242 /* Allow impersonation for the process server if it's granted the impersonation privilege */
2243 if ((ProcessToken->TokenFlags & TOKEN_HAS_IMPERSONATE_PRIVILEGE) != 0)
2244 {
2245 DPRINT("The process is granted the impersonation privilege, allow impersonation\n");
2246 CanImpersonate = TRUE;
2247 goto Quit;
2248 }
2249
2250 /*
2251 * Deny impersonation for the server if it wants to impersonate a client
2252 * beyond what the impersonation level originally permits.
2253 */
2254 if (ImpersonationLevel > TokenToImpersonate->ImpersonationLevel)
2255 {
2256 DPRINT1("Cannot impersonate a client above the permitted impersonation level!\n");
2257 CanImpersonate = FALSE;
2258 goto Quit;
2259 }
2260
2261 /* Is the server authenticated on the same client originating session? */
2262 if (!RtlEqualLuid(&ProcessToken->AuthenticationId,
2263 &TokenToImpersonate->OriginatingLogonSession))
2264 {
2265 /* It's not, check that at least both the server and client are the same user */
2266 if (!RtlEqualSid(ProcessToken->UserAndGroups[0].Sid,
2267 TokenToImpersonate->UserAndGroups[0].Sid))
2268 {
2269 DPRINT1("Server and client aren't the same user!\n");
2270 CanImpersonate = FALSE;
2271 goto Quit;
2272 }
2273
2274 /*
2275 * Make sure the tokens haven't diverged in terms of restrictions
2276 * that is one token is restricted but the other one isn't. If that
2277 * would have been the case then the server would have impersonated
2278 * a less restricted client thus potentially triggering an elevation,
2279 * which is not what we want.
2280 */
2281 if (SeTokenIsRestricted(ProcessToken) !=
2282 SeTokenIsRestricted(TokenToImpersonate))
2283 {
2284 DPRINT1("Attempting to impersonate a less restricted client token, bail out!\n");
2285 CanImpersonate = FALSE;
2286 goto Quit;
2287 }
2288 }
2289
2290 /* If we've reached that far then we can impersonate! */
2291 DPRINT("We can impersonate\n");
2292 CanImpersonate = TRUE;
2293
2294Quit:
2295 SepReleaseTokenLock(TokenToImpersonate);
2296 SepReleaseTokenLock(ProcessToken);
2297 return CanImpersonate;
2298}
@ SecurityIdentification
Definition: lsa.idl:56

Referenced by PsImpersonateClient().

◆ SeTokenImpersonationLevel()

SECURITY_IMPERSONATION_LEVEL NTAPI SeTokenImpersonationLevel ( _In_ PACCESS_TOKEN  Token)

Gathers the security impersonation level of an access token.

Parameters
[in]TokenA valid access token where the impersonation level has to be gathered.
Returns
Returns the security impersonation level from a valid token.

Definition at line 2059 of file token.c.

2061{
2062 PAGED_CODE();
2063
2064 return ((PTOKEN)Token)->ImpersonationLevel;
2065}

Referenced by PsAssignImpersonationToken().

◆ SeTokenIsAdmin()

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.

Parameters
[in]TokenA valid access token to determine if such token is admin or not.
Returns
Returns TRUE if the token is an admin one, FALSE otherwise.

Definition at line 2103 of file token.c.

2105{
2106 PAGED_CODE();
2107
2108 // NOTE: Win7+ instead really checks the list of groups in the token
2109 // (since TOKEN_HAS_ADMIN_GROUP == TOKEN_WRITE_RESTRICTED ...)
2110 return (((PTOKEN)Token)->TokenFlags & TOKEN_HAS_ADMIN_GROUP) != 0;
2111}
#define TOKEN_HAS_ADMIN_GROUP
Definition: setypes.h:1182

Referenced by PsImpersonateClient(), and SepAccessCheckWorker().

◆ SeTokenIsInert()

BOOLEAN NTAPI SeTokenIsInert ( _In_ PTOKEN  Token)

Determines if a token is a sandbox inert token or not, based upon the token flags.

Parameters
[in]TokenA valid access token to determine if such token is inert.
Returns
Returns TRUE if the token is inert, FALSE otherwise.

Definition at line 1583 of file token.c.

1585{
1586 PAGED_CODE();
1587
1588 return (((PTOKEN)Token)->TokenFlags & TOKEN_SANDBOX_INERT) != 0;
1589}
#define TOKEN_SANDBOX_INERT
Definition: setypes.h:1185

Referenced by NtQueryInformationToken().

◆ SeTokenIsRestricted()

BOOLEAN NTAPI SeTokenIsRestricted ( _In_ PACCESS_TOKEN  Token)

Determines if a token is restricted or not, based upon the token flags.

Parameters
[in]TokenA valid access token to determine if such token is restricted.
Returns
Returns TRUE if the token is restricted, FALSE otherwise.

Definition at line 2126 of file token.c.

2128{
2129 PAGED_CODE();
2130
2131 return (((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0;
2132}

Referenced by NtQueryInformationToken(), PsImpersonateClient(), RxInitializeVNetRootParameters(), SepAccessCheckWorker(), SepCompareTokens(), SepDumpTokenDebugInfo(), SepImpersonateAnonymousToken(), and SeTokenCanImpersonate().

◆ SeTokenIsWriteRestricted()

BOOLEAN NTAPI SeTokenIsWriteRestricted ( _In_ PACCESS_TOKEN  Token)

Determines if a token is write restricted, that is, nobody can write anything to it.

Parameters
[in]TokenA valid access token to determine if such token is write restricted.
Returns
Returns TRUE if the token is write restricted, FALSE otherwise.
Remarks
First introduced in NT 5.1 SP2 x86 (5.1.2600.2622), absent in NT 5.2, then finally re-introduced in Vista+.

Definition at line 2151 of file token.c.

2153{
2154 PAGED_CODE();
2155
2156 // NOTE: NT 5.1 SP2 x86 checks the SE_BACKUP_PRIVILEGES_CHECKED flag
2157 // while Vista+ checks the TOKEN_WRITE_RESTRICTED flag as one expects.
2158 return (((PTOKEN)Token)->TokenFlags & SE_BACKUP_PRIVILEGES_CHECKED) != 0;
2159}
#define SE_BACKUP_PRIVILEGES_CHECKED
Definition: setypes.h:1187

◆ SeTokenType()

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.

Parameters
[in]TokenA valid access token where the token type has to be gathered.
Returns
Returns the token type from a valid token.

Definition at line 2080 of file token.c.

2082{
2083 PAGED_CODE();
2084
2085 return ((PTOKEN)Token)->TokenType;
2086}

Variable Documentation

◆ SeAnonymousAuthenticationId

◆ SepTokenMapping

GENERIC_MAPPING SepTokenMapping
static
Initial value:
= {
}
#define TOKEN_WRITE
Definition: setypes.h:953
#define TOKEN_READ
Definition: setypes.h:951
#define TOKEN_EXECUTE
Definition: setypes.h:958

Definition at line 23 of file token.c.

Referenced by SepInitializeTokenImplementation().

◆ SeSystemAuthenticationId

LUID SeSystemAuthenticationId = SYSTEM_LUID

Definition at line 20 of file token.c.

Referenced by SepCreateSystemProcessToken(), SepRmDeleteLogonSession(), and SeRmInitPhase0().

◆ SeSystemTokenSource

TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}}

◆ SeTokenObjectType