mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
- CT_ACTIVE_IMPERSTIONATION_INFO_BIT -> CT_ACTIVE_IMPERSONATION_INFO_BIT
- Added Process and Thread locking inlined functions for Ps Security functions. - Thread safety is your friend! Huge rework of almost all the functions in ps/security.c to use the process/thread pushlocks and use interlocked operations when dealing with the ActiveImpersonationInfo thread flag. - Added PAGED_CODE(). - Added checks for Processes with Jobs for the day that will happen. - PsAssignImpersoonationToken with a NULL token handle means simply to revert to self. - Don't ignore the HandleAttributes in NtOpenProcessTokenEx. - Use SeTokenType to make sure the token passed is an impersonation token. - Remove some fixed bugs in krnlfun.c, add more TODOs. svn path=/trunk/; revision=23231
This commit is contained in:
parent
0cc0655c20
commit
59c6a927a2
|
@ -163,7 +163,7 @@ extern NTSYSAPI POBJECT_TYPE PsProcessType;
|
||||||
#define CT_TERMINATED_BIT 0x1
|
#define CT_TERMINATED_BIT 0x1
|
||||||
#define CT_DEAD_THREAD_BIT 0x2
|
#define CT_DEAD_THREAD_BIT 0x2
|
||||||
#define CT_HIDE_FROM_DEBUGGER_BIT 0x4
|
#define CT_HIDE_FROM_DEBUGGER_BIT 0x4
|
||||||
#define CT_ACTIVE_IMPERSTIONATION_INFO_BIT 0x8
|
#define CT_ACTIVE_IMPERSONATION_INFO_BIT 0x8
|
||||||
#define CT_SYSTEM_THREAD_BIT 0x10
|
#define CT_SYSTEM_THREAD_BIT 0x10
|
||||||
#define CT_HARD_ERRORS_ARE_DISABLED_BIT 0x20
|
#define CT_HARD_ERRORS_ARE_DISABLED_BIT 0x20
|
||||||
#define CT_BREAK_ON_TERMINATION_BIT 0x40
|
#define CT_BREAK_ON_TERMINATION_BIT 0x40
|
||||||
|
|
|
@ -25,14 +25,13 @@
|
||||||
// - Add tracing to iofunc.c
|
// - Add tracing to iofunc.c
|
||||||
//
|
//
|
||||||
// Ps:
|
// Ps:
|
||||||
// - Use Process/Thread Rundown.
|
|
||||||
// - Use Process Pushlock Locks.
|
|
||||||
// - Use Security Locks in security.c
|
|
||||||
// - Figure out why processes don't die.
|
// - Figure out why processes don't die.
|
||||||
// - Generate process cookie for user-more thread.
|
// - Generate process cookie for user-more thread.
|
||||||
// - Add security calls where necessary.
|
// - Add security calls where necessary.
|
||||||
// - Add tracing.
|
// - Add tracing.
|
||||||
// - Add failure/race checks for thread creation.
|
// - Add failure/race checks for thread creation.
|
||||||
|
// - Complete PspSetPrimaryToken.
|
||||||
|
// - Update TEB Security information when impersonating.
|
||||||
//
|
//
|
||||||
// Ob:
|
// Ob:
|
||||||
// - Possible bug in deferred deletion under Cc Rewrite branch.
|
// - Possible bug in deferred deletion under Cc Rewrite branch.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "i386/v86m.h"
|
#include "i386/v86m.h"
|
||||||
#include "ob.h"
|
#include "ob.h"
|
||||||
#include "mm.h"
|
#include "mm.h"
|
||||||
|
#include "ex.h"
|
||||||
#include "ps.h"
|
#include "ps.h"
|
||||||
#include "cc.h"
|
#include "cc.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
@ -24,7 +25,6 @@
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "ldr.h"
|
#include "ldr.h"
|
||||||
#include "kd.h"
|
#include "kd.h"
|
||||||
#include "ex.h"
|
|
||||||
#include "fsrtl.h"
|
#include "fsrtl.h"
|
||||||
#include "lpc.h"
|
#include "lpc.h"
|
||||||
#include "rtl.h"
|
#include "rtl.h"
|
||||||
|
|
|
@ -84,3 +84,90 @@ PspRunLegoRoutine(IN PKTHREAD Thread)
|
||||||
if (PspLegoNotifyRoutine) PspLegoNotifyRoutine(Thread);
|
if (PspLegoNotifyRoutine) PspLegoNotifyRoutine(Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
PspLockProcessSecurityShared(IN PEPROCESS Process)
|
||||||
|
{
|
||||||
|
/* Enter a Critical Region */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
|
||||||
|
/* Lock the Process */
|
||||||
|
ExAcquirePushLockShared(&Process->ProcessLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
PspUnlockProcessSecurityShared(IN PEPROCESS Process)
|
||||||
|
{
|
||||||
|
/* Unlock the Process */
|
||||||
|
ExReleasePushLockShared(&Process->ProcessLock);
|
||||||
|
|
||||||
|
/* Leave Critical Region */
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
PspLockProcessSecurityExclusive(IN PEPROCESS Process)
|
||||||
|
{
|
||||||
|
/* Enter a Critical Region */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
|
||||||
|
/* Lock the Process */
|
||||||
|
ExAcquirePushLockExclusive(&Process->ProcessLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
PspUnlockProcessSecurityExclusive(IN PEPROCESS Process)
|
||||||
|
{
|
||||||
|
/* Unlock the Process */
|
||||||
|
ExReleasePushLockExclusive(&Process->ProcessLock);
|
||||||
|
|
||||||
|
/* Leave Critical Region */
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
PspLockThreadSecurityShared(IN PETHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Enter a Critical Region */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
|
||||||
|
/* Lock the Thread */
|
||||||
|
ExAcquirePushLockShared(&Thread->ThreadLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
PspUnlockThreadSecurityShared(IN PETHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Unlock the Thread */
|
||||||
|
ExReleasePushLockShared(&Thread->ThreadLock);
|
||||||
|
|
||||||
|
/* Leave Critical Region */
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
PspLockThreadSecurityExclusive(IN PETHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Enter a Critical Region */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
|
||||||
|
/* Lock the Thread */
|
||||||
|
ExAcquirePushLockExclusive(&Thread->ThreadLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
PspUnlockThreadSecurityExclusive(IN PETHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Unlock the Process */
|
||||||
|
ExReleasePushLockExclusive(&Thread->ThreadLock);
|
||||||
|
|
||||||
|
/* Leave Critical Thread */
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
}
|
||||||
|
|
|
@ -16,58 +16,12 @@
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
/* FIXME: Turn into Macro */
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
PspLockProcessSecurityShared(IN PEPROCESS Process)
|
|
||||||
{
|
|
||||||
/* Enter a Critical Region */
|
|
||||||
KeEnterCriticalRegion();
|
|
||||||
|
|
||||||
/* Lock the Process */
|
|
||||||
ExAcquirePushLockShared(&Process->ProcessLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Turn into Macro */
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
PspUnlockProcessSecurityShared(IN PEPROCESS Process)
|
|
||||||
{
|
|
||||||
/* Unlock the Process */
|
|
||||||
ExReleasePushLockShared(&Process->ProcessLock);
|
|
||||||
|
|
||||||
/* Leave Critical Region */
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Turn into Macro */
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
PspLockProcessSecurityExclusive(IN PEPROCESS Process)
|
|
||||||
{
|
|
||||||
/* Enter a Critical Region */
|
|
||||||
KeEnterCriticalRegion();
|
|
||||||
|
|
||||||
/* Lock the Process */
|
|
||||||
ExAcquirePushLockExclusive(&Process->ProcessLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Turn into Macro */
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
PspUnlockProcessSecurityExclusive(IN PEPROCESS Process)
|
|
||||||
{
|
|
||||||
/* Unlock the Process */
|
|
||||||
ExReleasePushLockExclusive(&Process->ProcessLock);
|
|
||||||
|
|
||||||
/* Leave Critical Region */
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
PspDeleteProcessSecurity(IN PEPROCESS Process)
|
PspDeleteProcessSecurity(IN PEPROCESS Process)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check if we have a token */
|
/* Check if we have a token */
|
||||||
if (Process->Token.Object)
|
if (Process->Token.Object)
|
||||||
{
|
{
|
||||||
|
@ -81,6 +35,8 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
PspDeleteThreadSecurity(IN PETHREAD Thread)
|
PspDeleteThreadSecurity(IN PETHREAD Thread)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check if we have active impersonation info */
|
/* Check if we have active impersonation info */
|
||||||
if (Thread->ActiveImpersonationInfo)
|
if (Thread->ActiveImpersonationInfo)
|
||||||
{
|
{
|
||||||
|
@ -93,7 +49,8 @@ PspDeleteThreadSecurity(IN PETHREAD Thread)
|
||||||
{
|
{
|
||||||
/* Free it */
|
/* Free it */
|
||||||
ExFreePool(Thread->ImpersonationInfo);
|
ExFreePool(Thread->ImpersonationInfo);
|
||||||
Thread->ActiveImpersonationInfo = FALSE;
|
InterlockedAnd(&Thread->CrossThreadFlags,
|
||||||
|
~CT_ACTIVE_IMPERSONATION_INFO_BIT);
|
||||||
Thread->ImpersonationInfo = NULL;
|
Thread->ImpersonationInfo = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,6 +60,7 @@ NTAPI
|
||||||
PspInitializeProcessSecurity(IN PEPROCESS Process,
|
PspInitializeProcessSecurity(IN PEPROCESS Process,
|
||||||
IN PEPROCESS Parent OPTIONAL)
|
IN PEPROCESS Parent OPTIONAL)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PTOKEN NewToken, ParentToken;
|
PTOKEN NewToken, ParentToken;
|
||||||
|
|
||||||
|
@ -113,7 +71,10 @@ PspInitializeProcessSecurity(IN PEPROCESS Process,
|
||||||
ParentToken = PsReferencePrimaryToken(Parent);
|
ParentToken = PsReferencePrimaryToken(Parent);
|
||||||
|
|
||||||
/* Duplicate it */
|
/* Duplicate it */
|
||||||
Status = SeSubProcessToken(ParentToken, &NewToken, TRUE, 0);
|
Status = SeSubProcessToken(ParentToken,
|
||||||
|
&NewToken,
|
||||||
|
TRUE,
|
||||||
|
0);//MmGetSessionId(Process));
|
||||||
|
|
||||||
/* Dereference the Parent */
|
/* Dereference the Parent */
|
||||||
ObFastDereferenceObject(&Parent->Token, ParentToken);
|
ObFastDereferenceObject(&Parent->Token, ParentToken);
|
||||||
|
@ -124,13 +85,9 @@ PspInitializeProcessSecurity(IN PEPROCESS Process,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef SCHED_REWRITE
|
#ifdef SCHED_REWRITE
|
||||||
PTOKEN BootToken;
|
/* No parent, assign the Boot Token */
|
||||||
|
ObInitializeFastReference(&Process->Token, NULL);
|
||||||
/* No parent, this is the Initial System Process. Assign Boot Token */
|
SeAssignPrimaryToken(Process, PspBootAccessToken);
|
||||||
BootToken = SepCreateSystemProcessToken();
|
|
||||||
BootToken->TokenInUse = TRUE;
|
|
||||||
Process->Token = BootToken;
|
|
||||||
ObReferenceObject(BootToken);
|
|
||||||
#else
|
#else
|
||||||
DPRINT1("PspInitializeProcessSecurity called with no parent.\n");
|
DPRINT1("PspInitializeProcessSecurity called with no parent.\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -289,7 +246,7 @@ NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
|
||||||
{
|
{
|
||||||
/* Reference it by handle and dereference the pointer */
|
/* Reference it by handle and dereference the pointer */
|
||||||
Status = ObOpenObjectByPointer(Token,
|
Status = ObOpenObjectByPointer(Token,
|
||||||
0,
|
HandleAttributes,
|
||||||
NULL,
|
NULL,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
SepTokenObjectType,
|
SepTokenObjectType,
|
||||||
|
@ -327,6 +284,7 @@ NTAPI
|
||||||
PsReferencePrimaryToken(PEPROCESS Process)
|
PsReferencePrimaryToken(PEPROCESS Process)
|
||||||
{
|
{
|
||||||
PACCESS_TOKEN Token;
|
PACCESS_TOKEN Token;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Fast Reference the Token */
|
/* Fast Reference the Token */
|
||||||
Token = ObFastReferenceObject(&Process->Token);
|
Token = ObFastReferenceObject(&Process->Token);
|
||||||
|
@ -358,6 +316,7 @@ PsOpenTokenOfProcess(IN HANDLE ProcessHandle,
|
||||||
{
|
{
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Get the Token */
|
/* Get the Token */
|
||||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||||
|
@ -366,7 +325,7 @@ PsOpenTokenOfProcess(IN HANDLE ProcessHandle,
|
||||||
ExGetPreviousMode(),
|
ExGetPreviousMode(),
|
||||||
(PVOID*)&Process,
|
(PVOID*)&Process,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Reference the token and dereference the process */
|
/* Reference the token and dereference the process */
|
||||||
*Token = PsReferencePrimaryToken(Process);
|
*Token = PsReferencePrimaryToken(Process);
|
||||||
|
@ -388,29 +347,39 @@ PsAssignImpersonationToken(IN PETHREAD Thread,
|
||||||
PACCESS_TOKEN Token;
|
PACCESS_TOKEN Token;
|
||||||
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check if we were given a handle */
|
/* Check if we were given a handle */
|
||||||
if (TokenHandle)
|
if (!TokenHandle)
|
||||||
{
|
{
|
||||||
/* Get the token object */
|
/* Undo impersonation */
|
||||||
Status = ObReferenceObjectByHandle(TokenHandle,
|
PsRevertThreadToSelf(Thread);
|
||||||
TOKEN_IMPERSONATE,
|
return STATUS_SUCCESS;
|
||||||
SepTokenObjectType,
|
}
|
||||||
KeGetPreviousMode(),
|
|
||||||
(PVOID*)&Token,
|
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status)) return(Status);
|
|
||||||
|
|
||||||
/* Get the impersionation level */
|
/* Get the token object */
|
||||||
ImpersonationLevel = SeTokenImpersonationLevel(Token);
|
Status = ObReferenceObjectByHandle(TokenHandle,
|
||||||
}
|
TOKEN_IMPERSONATE,
|
||||||
else
|
SepTokenObjectType,
|
||||||
|
KeGetPreviousMode(),
|
||||||
|
(PVOID*)&Token,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status)) return(Status);
|
||||||
|
|
||||||
|
/* Make sure it's an impersonation token */
|
||||||
|
if (SeTokenType(Token) != TokenImpersonation)
|
||||||
{
|
{
|
||||||
/* Otherwise, clear values */
|
/* Fail */
|
||||||
Token = NULL;
|
ObDereferenceObject(Token);
|
||||||
ImpersonationLevel = 0;
|
return STATUS_BAD_TOKEN_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if this is a job, which we don't support yet */
|
||||||
|
if (Thread->ThreadsProcess->Job) KEBUGCHECK(0);
|
||||||
|
|
||||||
|
/* Get the impersionation level */
|
||||||
|
ImpersonationLevel = SeTokenImpersonationLevel(Token);
|
||||||
|
|
||||||
/* Call the impersonation API */
|
/* Call the impersonation API */
|
||||||
Status = PsImpersonateClient(Thread,
|
Status = PsImpersonateClient(Thread,
|
||||||
Token,
|
Token,
|
||||||
|
@ -431,6 +400,7 @@ NTAPI
|
||||||
PsRevertToSelf(VOID)
|
PsRevertToSelf(VOID)
|
||||||
{
|
{
|
||||||
/* Call the per-thread API */
|
/* Call the per-thread API */
|
||||||
|
PAGED_CODE();
|
||||||
PsRevertThreadToSelf(PsGetCurrentThread());
|
PsRevertThreadToSelf(PsGetCurrentThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,13 +411,32 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
PsRevertThreadToSelf(IN PETHREAD Thread)
|
PsRevertThreadToSelf(IN PETHREAD Thread)
|
||||||
{
|
{
|
||||||
|
PTOKEN Token = NULL;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Make sure we had impersonation information */
|
/* Make sure we had impersonation information */
|
||||||
if (Thread->ActiveImpersonationInfo)
|
if (Thread->ActiveImpersonationInfo)
|
||||||
{
|
{
|
||||||
/* Dereference the impersonation token and set it as false */
|
/* Lock the thread security */
|
||||||
ObDereferenceObject (Thread->ImpersonationInfo->Token);
|
PspLockThreadSecurityExclusive(Thread);
|
||||||
Thread->ActiveImpersonationInfo = FALSE;
|
|
||||||
|
/* Make sure it's still active */
|
||||||
|
if (Thread->ActiveImpersonationInfo)
|
||||||
|
{
|
||||||
|
/* Disable impersonation */
|
||||||
|
InterlockedAnd(&Thread->CrossThreadFlags,
|
||||||
|
~CT_ACTIVE_IMPERSONATION_INFO_BIT);
|
||||||
|
|
||||||
|
/* Get the token */
|
||||||
|
Token = Thread->ImpersonationInfo->Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release thread security */
|
||||||
|
PspUnlockThreadSecurityExclusive(Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dereference the impersonation token */
|
||||||
|
if (Token) ObDereferenceObject(Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -462,6 +451,8 @@ PsImpersonateClient(IN PETHREAD Thread,
|
||||||
IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
|
IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
|
||||||
{
|
{
|
||||||
PPS_IMPERSONATION_INFORMATION Impersonation;
|
PPS_IMPERSONATION_INFORMATION Impersonation;
|
||||||
|
PTOKEN OldToken = NULL;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check if we don't have a token */
|
/* Check if we don't have a token */
|
||||||
if (!Token)
|
if (!Token)
|
||||||
|
@ -469,52 +460,78 @@ PsImpersonateClient(IN PETHREAD Thread,
|
||||||
/* Make sure we're impersonating */
|
/* Make sure we're impersonating */
|
||||||
if (Thread->ActiveImpersonationInfo)
|
if (Thread->ActiveImpersonationInfo)
|
||||||
{
|
{
|
||||||
/* Disable impersonation and check for token */
|
/* We seem to be, lock the thread */
|
||||||
Thread->ActiveImpersonationInfo = FALSE;
|
PspLockThreadSecurityExclusive(Thread);
|
||||||
if (Thread->ImpersonationInfo->Token)
|
|
||||||
|
/* Make sure we're still impersonating */
|
||||||
|
if (Thread->ActiveImpersonationInfo)
|
||||||
{
|
{
|
||||||
/* Dereference it */
|
/* Disable impersonation */
|
||||||
ObDereferenceObject(Thread->ImpersonationInfo->Token);
|
InterlockedAnd(&Thread->CrossThreadFlags,
|
||||||
|
~CT_ACTIVE_IMPERSONATION_INFO_BIT);
|
||||||
|
|
||||||
|
/* Get the token */
|
||||||
|
OldToken = Thread->ImpersonationInfo->Token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unlock the process */
|
||||||
|
PspUnlockThreadSecurityExclusive(Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we have active impersonation */
|
|
||||||
if (Thread->ActiveImpersonationInfo)
|
|
||||||
{
|
|
||||||
/* Reuse the block and reference the token */
|
|
||||||
Impersonation = Thread->ImpersonationInfo;
|
|
||||||
if (Impersonation->Token) ObDereferenceObject(Impersonation->Token);
|
|
||||||
}
|
|
||||||
else if (Thread->ImpersonationInfo)
|
|
||||||
{
|
|
||||||
/* It's not active, but we can still reuse the block */
|
|
||||||
Impersonation = Thread->ImpersonationInfo;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We need to allocate a new one */
|
/* Check if we have impersonation info */
|
||||||
Impersonation = ExAllocatePoolWithTag(PagedPool,
|
Impersonation = Thread->ImpersonationInfo;
|
||||||
sizeof(*Impersonation),
|
if (!Impersonation)
|
||||||
TAG_PS_IMPERSONATION);
|
{
|
||||||
if (!Impersonation) return STATUS_INSUFFICIENT_RESOURCES;
|
/* We need to allocate a new one */
|
||||||
|
Impersonation = ExAllocatePoolWithTag(PagedPool,
|
||||||
|
sizeof(*Impersonation),
|
||||||
|
TAG_PS_IMPERSONATION);
|
||||||
|
if (!Impersonation) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
/* Update the pointer */
|
/* Update the pointer */
|
||||||
Thread->ImpersonationInfo = Impersonation;
|
if (InterlockedCompareExchangePointer(&Thread->ImpersonationInfo,
|
||||||
|
Impersonation,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
/* Someone beat us to it, free our copy */
|
||||||
|
ExFreePool(Impersonation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if this is a job, which we don't support yet */
|
||||||
|
if (Thread->ThreadsProcess->Job) KEBUGCHECK(0);
|
||||||
|
|
||||||
|
/* Lock thread security */
|
||||||
|
PspLockThreadSecurityExclusive(Thread);
|
||||||
|
|
||||||
|
/* Check if we're impersonating */
|
||||||
|
if (Thread->ActiveImpersonationInfo)
|
||||||
|
{
|
||||||
|
/* Get the token */
|
||||||
|
OldToken = Impersonation->Token;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, enable impersonation */
|
||||||
|
InterlockedOr(&Thread->CrossThreadFlags,
|
||||||
|
CT_ACTIVE_IMPERSONATION_INFO_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now fill it out */
|
||||||
|
Impersonation->ImpersonationLevel = ImpersonationLevel;
|
||||||
|
Impersonation->CopyOnOpen = CopyOnOpen;
|
||||||
|
Impersonation->EffectiveOnly = EffectiveOnly;
|
||||||
|
Impersonation->Token = Token;
|
||||||
|
|
||||||
|
/* Unlock the thread */
|
||||||
|
PspUnlockThreadSecurityExclusive(Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now fill it out */
|
/* Dereference the token and return success */
|
||||||
Impersonation->ImpersonationLevel = ImpersonationLevel;
|
ObReferenceObject(Token);
|
||||||
Impersonation->CopyOnOpen = CopyOnOpen;
|
if (OldToken) ObDereferenceObject(OldToken);
|
||||||
Impersonation->EffectiveOnly = EffectiveOnly;
|
|
||||||
Impersonation->Token = Token;
|
|
||||||
Thread->ActiveImpersonationInfo = TRUE;
|
|
||||||
|
|
||||||
/* Reference the token and return success */
|
|
||||||
ObReferenceObject(Impersonation->Token);
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,12 +546,13 @@ PsReferenceEffectiveToken(IN PETHREAD Thread,
|
||||||
OUT PSECURITY_IMPERSONATION_LEVEL Level)
|
OUT PSECURITY_IMPERSONATION_LEVEL Level)
|
||||||
{
|
{
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
PACCESS_TOKEN Token;
|
PACCESS_TOKEN Token = NULL;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check if we don't have impersonation info */
|
/* Check if we don't have impersonation info */
|
||||||
|
Process = Thread->ThreadsProcess;
|
||||||
if (!Thread->ActiveImpersonationInfo)
|
if (!Thread->ActiveImpersonationInfo)
|
||||||
{
|
{
|
||||||
Process = Thread->ThreadsProcess;
|
|
||||||
*TokenType = TokenPrimary;
|
*TokenType = TokenPrimary;
|
||||||
*EffectiveOnly = FALSE;
|
*EffectiveOnly = FALSE;
|
||||||
|
|
||||||
|
@ -556,14 +574,24 @@ PsReferenceEffectiveToken(IN PETHREAD Thread,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Get the token */
|
/* Lock the Process */
|
||||||
Token = Thread->ImpersonationInfo->Token;
|
PspLockProcessSecurityShared(Process);
|
||||||
ObReferenceObject(Token);
|
|
||||||
|
|
||||||
/* Return data to caller */
|
/* Make sure impersonation is still active */
|
||||||
*TokenType = TokenImpersonation;
|
if (Thread->ActiveImpersonationInfo)
|
||||||
*EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
|
{
|
||||||
*Level = Thread->ImpersonationInfo->ImpersonationLevel;
|
/* Get the token */
|
||||||
|
Token = Thread->ImpersonationInfo->Token;
|
||||||
|
ObReferenceObject(Token);
|
||||||
|
|
||||||
|
/* Return data to caller */
|
||||||
|
*TokenType = TokenImpersonation;
|
||||||
|
*EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
|
||||||
|
*Level = Thread->ImpersonationInfo->ImpersonationLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the Process */
|
||||||
|
PspUnlockProcessSecurityShared(Process);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the token */
|
/* Return the token */
|
||||||
|
@ -580,17 +608,31 @@ PsReferenceImpersonationToken(IN PETHREAD Thread,
|
||||||
OUT PBOOLEAN EffectiveOnly,
|
OUT PBOOLEAN EffectiveOnly,
|
||||||
OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
|
OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
|
||||||
{
|
{
|
||||||
|
PTOKEN Token = NULL;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* If we don't have impersonation info, just quit */
|
/* If we don't have impersonation info, just quit */
|
||||||
if (!Thread->ActiveImpersonationInfo) return NULL;
|
if (!Thread->ActiveImpersonationInfo) return NULL;
|
||||||
|
|
||||||
/* Return data from caller */
|
/* Lock the thread */
|
||||||
*ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel;
|
PspLockThreadSecurityShared(Thread);
|
||||||
*CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
|
|
||||||
*EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
|
|
||||||
|
|
||||||
/* Reference the token and return it */
|
/* Make sure we still have active impersonation */
|
||||||
ObReferenceObject(Thread->ImpersonationInfo->Token);
|
if (Thread->ActiveImpersonationInfo)
|
||||||
return Thread->ImpersonationInfo->Token;
|
{
|
||||||
|
/* Return data from caller */
|
||||||
|
ObReferenceObject(Thread->ImpersonationInfo->Token);
|
||||||
|
*ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel;
|
||||||
|
*CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
|
||||||
|
*EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
|
||||||
|
|
||||||
|
/* Set the token */
|
||||||
|
Token = Thread->ImpersonationInfo->Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock thread and return impersonation token */
|
||||||
|
PspUnlockThreadSecurityShared(Thread);
|
||||||
|
return Token;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef PsDereferenceImpersonationToken
|
#undef PsDereferenceImpersonationToken
|
||||||
|
@ -601,6 +643,8 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken)
|
PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* If we got a token, dereference it */
|
/* If we got a token, dereference it */
|
||||||
if (ImpersonationToken) ObDereferenceObject(ImpersonationToken);
|
if (ImpersonationToken) ObDereferenceObject(ImpersonationToken);
|
||||||
}
|
}
|
||||||
|
@ -613,6 +657,8 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
|
PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Dereference the token*/
|
/* Dereference the token*/
|
||||||
ObDereferenceObject(PrimaryToken);
|
ObDereferenceObject(PrimaryToken);
|
||||||
}
|
}
|
||||||
|
@ -625,29 +671,52 @@ NTAPI
|
||||||
PsDisableImpersonation(IN PETHREAD Thread,
|
PsDisableImpersonation(IN PETHREAD Thread,
|
||||||
IN PSE_IMPERSONATION_STATE ImpersonationState)
|
IN PSE_IMPERSONATION_STATE ImpersonationState)
|
||||||
{
|
{
|
||||||
PPS_IMPERSONATION_INFORMATION Impersonation;
|
PPS_IMPERSONATION_INFORMATION Impersonation = NULL;
|
||||||
|
LONG NewValue, OldValue;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check if we don't have impersonation */
|
/* Check if we don't have impersonation */
|
||||||
if (!Thread->ActiveImpersonationInfo)
|
if (Thread->ActiveImpersonationInfo)
|
||||||
{
|
{
|
||||||
/* Clear everything */
|
/* Lock thread security */
|
||||||
ImpersonationState->Token = NULL;
|
PspLockThreadSecurityExclusive(Thread);
|
||||||
ImpersonationState->CopyOnOpen = FALSE;
|
|
||||||
ImpersonationState->EffectiveOnly = FALSE;
|
/* Disable impersonation */
|
||||||
ImpersonationState->Level = SecurityAnonymous;
|
OldValue = Thread->CrossThreadFlags;
|
||||||
return FALSE;
|
do
|
||||||
|
{
|
||||||
|
/* Attempt to change the flag */
|
||||||
|
NewValue =
|
||||||
|
InterlockedCompareExchange(&Thread->CrossThreadFlags,
|
||||||
|
OldValue &~
|
||||||
|
CT_ACTIVE_IMPERSONATION_INFO_BIT,
|
||||||
|
OldValue);
|
||||||
|
} while (NewValue != OldValue);
|
||||||
|
|
||||||
|
/* Did someone disable behind our back? */
|
||||||
|
if (!(NewValue & CT_ACTIVE_IMPERSONATION_INFO_BIT))
|
||||||
|
{
|
||||||
|
/* Copy the old state */
|
||||||
|
Impersonation = Thread->ImpersonationInfo;
|
||||||
|
ImpersonationState->Token = Impersonation->Token;
|
||||||
|
ImpersonationState->CopyOnOpen = Impersonation->CopyOnOpen;
|
||||||
|
ImpersonationState->EffectiveOnly = Impersonation->EffectiveOnly;
|
||||||
|
ImpersonationState->Level = Impersonation->ImpersonationLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock thread security */
|
||||||
|
PspUnlockThreadSecurityExclusive(Thread);
|
||||||
|
|
||||||
|
/* If we had impersonation info, return true */
|
||||||
|
if (Impersonation) return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the old state */
|
/* Clear everything */
|
||||||
Impersonation = Thread->ImpersonationInfo;
|
ImpersonationState->Token = NULL;
|
||||||
ImpersonationState->Token = Impersonation->Token;
|
ImpersonationState->CopyOnOpen = FALSE;
|
||||||
ImpersonationState->CopyOnOpen = Impersonation->CopyOnOpen;
|
ImpersonationState->EffectiveOnly = FALSE;
|
||||||
ImpersonationState->EffectiveOnly = Impersonation->EffectiveOnly;
|
ImpersonationState->Level = SecurityAnonymous;
|
||||||
ImpersonationState->Level = Impersonation->ImpersonationLevel;
|
return FALSE;
|
||||||
|
|
||||||
/* Disable impersonation and return true */
|
|
||||||
Thread->ActiveImpersonationInfo = FALSE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -658,15 +727,47 @@ NTAPI
|
||||||
PsRestoreImpersonation(IN PETHREAD Thread,
|
PsRestoreImpersonation(IN PETHREAD Thread,
|
||||||
IN PSE_IMPERSONATION_STATE ImpersonationState)
|
IN PSE_IMPERSONATION_STATE ImpersonationState)
|
||||||
{
|
{
|
||||||
/* Call the impersonation API */
|
PTOKEN Token = NULL;
|
||||||
PsImpersonateClient(Thread,
|
PPS_IMPERSONATION_INFORMATION Impersonation;
|
||||||
ImpersonationState->Token,
|
PAGED_CODE();
|
||||||
ImpersonationState->CopyOnOpen,
|
|
||||||
ImpersonationState->EffectiveOnly,
|
/* Lock thread security */
|
||||||
ImpersonationState->Level);
|
PspLockThreadSecurityExclusive(Thread);
|
||||||
|
|
||||||
|
/* Get the impersonation info */
|
||||||
|
Impersonation = Thread->ImpersonationInfo;
|
||||||
|
|
||||||
|
/* Check if we're impersonating */
|
||||||
|
if (Thread->ActiveImpersonationInfo)
|
||||||
|
{
|
||||||
|
/* Get the token */
|
||||||
|
Token = Impersonation->Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we have an impersonation state */
|
||||||
|
if (ImpersonationState)
|
||||||
|
{
|
||||||
|
/* Fill out the impersonation info */
|
||||||
|
Impersonation->ImpersonationLevel = ImpersonationState->Level;
|
||||||
|
Impersonation->CopyOnOpen = ImpersonationState->CopyOnOpen;
|
||||||
|
Impersonation->EffectiveOnly = ImpersonationState->EffectiveOnly;
|
||||||
|
Impersonation->Token = ImpersonationState->Token;
|
||||||
|
|
||||||
|
/* Enable impersonation */
|
||||||
|
InterlockedOr(&Thread->CrossThreadFlags, CT_ACTIVE_IMPERSONATION_INFO_BIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Disable impersonation */
|
||||||
|
InterlockedAnd(&Thread->CrossThreadFlags,
|
||||||
|
~CT_ACTIVE_IMPERSONATION_INFO_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the thread */
|
||||||
|
PspUnlockThreadSecurityExclusive(Thread);
|
||||||
|
|
||||||
/* Dereference the token */
|
/* Dereference the token */
|
||||||
ObDereferenceObject(ImpersonationState->Token);
|
if (Token) ObDereferenceObject(Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
Loading…
Reference in a new issue