2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ps/security.c
5 * PURPOSE: Process Manager: Process/Thread Security
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Thomas Weidenmueller (w3seek@reactos.org)
11 /* INCLUDES ******************************************************************/
15 #include <internal/debug.h>
17 PTOKEN PspBootAccessToken
;
26 /* PRIVATE FUNCTIONS *********************************************************/
30 PspDeleteProcessSecurity(IN PEPROCESS Process
)
33 PSTRACE(PS_SECURITY_DEBUG
, "Process: %p\n", Process
);
35 /* Check if we have a token */
36 if (Process
->Token
.Object
)
39 SeDeassignPrimaryToken(Process
);
40 Process
->Token
.Object
= NULL
;
46 PspDeleteThreadSecurity(IN PETHREAD Thread
)
48 PPS_IMPERSONATION_INFORMATION ImpersonationInfo
= Thread
->ImpersonationInfo
;
50 PSTRACE(PS_SECURITY_DEBUG
, "Thread: %p\n", Thread
);
52 /* Check if we have active impersonation info */
53 if (Thread
->ActiveImpersonationInfo
)
55 /* Dereference its token */
56 ObDereferenceObject(ImpersonationInfo
->Token
);
59 /* Check if we have impersonation info */
60 if (ImpersonationInfo
)
63 ExFreePool(ImpersonationInfo
);
64 PspClearCrossThreadFlag(Thread
, CT_ACTIVE_IMPERSONATION_INFO_BIT
);
65 Thread
->ImpersonationInfo
= NULL
;
71 PspInitializeProcessSecurity(IN PEPROCESS Process
,
72 IN PEPROCESS Parent OPTIONAL
)
74 NTSTATUS Status
= STATUS_SUCCESS
;
75 PTOKEN NewToken
, ParentToken
;
77 PSTRACE(PS_SECURITY_DEBUG
, "Process: %p\n", Process
);
79 /* If we have a parent, then duplicate the Token */
82 /* Get the Parent Token */
83 ParentToken
= PsReferencePrimaryToken(Parent
);
86 Status
= SeSubProcessToken(ParentToken
,
89 0);//MmGetSessionId(Process));
91 /* Dereference the Parent */
92 ObFastDereferenceObject(&Parent
->Token
, ParentToken
);
94 /* Set the new Token */
95 if (NT_SUCCESS(Status
))
97 /* Initailize the fast reference */
98 ObInitializeFastReference(&Process
->Token
, NewToken
);
103 /* No parent, assign the Boot Token */
104 ObInitializeFastReference(&Process
->Token
, NULL
);
105 SeAssignPrimaryToken(Process
, PspBootAccessToken
);
108 /* Return to caller */
114 PspWriteTebImpersonationInfo(IN PETHREAD Thread
,
115 IN PETHREAD CurrentThread
)
119 BOOLEAN Attached
= FALSE
;
120 BOOLEAN IsImpersonating
;
123 PSTRACE(PS_SECURITY_DEBUG
, "Thread: %p\n", Thread
);
126 ASSERT(CurrentThread
== PsGetCurrentThread());
128 /* Get process and TEB */
129 Process
= Thread
->ThreadsProcess
;
130 Teb
= Thread
->Tcb
.Teb
;
133 /* Check if we're not in the right process */
134 if (Thread
->Tcb
.ApcState
.Process
!= &Process
->Pcb
)
136 /* Attach to the process */
137 KeStackAttachProcess(&Process
->Pcb
, &ApcState
);
141 /* Check if we're in a different thread or acquire rundown */
142 if ((Thread
== CurrentThread
) ||
143 (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
145 /* Check if the thread is impersonating */
146 IsImpersonating
= (BOOLEAN
)Thread
->ActiveImpersonationInfo
;
150 Teb
->ImpersonationLocale
= -1;
151 Teb
->IsImpersonating
= 1;
156 Teb
->ImpersonationLocale
= 0;
157 Teb
->IsImpersonating
= 0;
161 /* Check if we're in a different thread */
162 if (Thread
!= CurrentThread
)
164 /* Release protection */
165 ExReleaseRundownProtection(&Thread
->RundownProtect
);
169 if (Attached
) KeUnstackDetachProcess(&ApcState
);
172 /* Return to caller */
173 return STATUS_SUCCESS
;
178 PspAssignPrimaryToken(IN PEPROCESS Process
,
180 IN PACCESS_TOKEN AccessToken OPTIONAL
)
182 PACCESS_TOKEN NewToken
= AccessToken
, OldToken
;
185 PSTRACE(PS_SECURITY_DEBUG
, "Process: %p Token: %p\n", Process
, Token
);
187 /* Check if we don't have a pointer */
190 /* Reference it from the handle */
191 Status
= ObReferenceObjectByHandle(Token
,
192 TOKEN_ASSIGN_PRIMARY
,
197 if (!NT_SUCCESS(Status
)) return Status
;
200 /* Exchange tokens */
201 Status
= SeExchangePrimaryToken(Process
, NewToken
, &OldToken
);
203 /* Acquire and release the lock */
204 PspLockProcessSecurityExclusive(Process
);
205 PspUnlockProcessSecurityExclusive(Process
);
207 /* Dereference Tokens and Return */
208 if (NT_SUCCESS(Status
)) ObDereferenceObject(OldToken
);
209 if (AccessToken
) ObDereferenceObject(NewToken
);
215 PspSetPrimaryToken(IN PEPROCESS Process
,
216 IN HANDLE TokenHandle OPTIONAL
,
217 IN PACCESS_TOKEN Token OPTIONAL
)
219 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
221 PACCESS_TOKEN NewToken
= Token
;
222 NTSTATUS Status
, AccessStatus
;
223 BOOLEAN Result
, SdAllocated
;
224 PSECURITY_DESCRIPTOR SecurityDescriptor
;
225 SECURITY_SUBJECT_CONTEXT SubjectContext
;
226 PSTRACE(PS_SECURITY_DEBUG
, "Process: %p Token: %p\n", Process
, Token
);
228 /* Make sure we got a handle */
232 Status
= ObReferenceObjectByHandle(TokenHandle
,
233 TOKEN_ASSIGN_PRIMARY
,
238 if (!NT_SUCCESS(Status
)) return Status
;
241 /* Check if this is a child */
242 Status
= SeIsTokenChild(NewToken
, &IsChild
);
243 if (!NT_SUCCESS(Status
))
245 /* Failed, dereference */
246 if (TokenHandle
) ObDereferenceObject(NewToken
);
250 /* Check if this was an independent token */
253 /* Make sure we have the privilege to assign a new one */
254 if (!SeSinglePrivilegeCheck(SeAssignPrimaryTokenPrivilege
,
257 /* Failed, dereference */
258 if (TokenHandle
) ObDereferenceObject(Token
);
259 return STATUS_PRIVILEGE_NOT_HELD
;
263 /* Assign the token */
264 Status
= PspAssignPrimaryToken(Process
, NULL
, NewToken
);
265 if (NT_SUCCESS(Status
))
268 * We need to completely reverify if the process still has access to
269 * itself under this new token.
271 Status
= ObGetObjectSecurity(Process
,
274 if (NT_SUCCESS(Status
))
276 /* Setup the security context */
277 SubjectContext
.ProcessAuditId
= Process
;
278 SubjectContext
.PrimaryToken
= PsReferencePrimaryToken(Process
);
279 SubjectContext
.ClientToken
= NULL
;
281 /* Do the access check */
282 Result
= SeAccessCheck(SecurityDescriptor
,
288 &PsProcessType
->TypeInfo
.GenericMapping
,
290 &Process
->GrantedAccess
,
293 /* Dereference the token and let go the SD */
294 ObFastDereferenceObject(&Process
->Token
,
295 SubjectContext
.PrimaryToken
);
296 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
298 /* Remove access if it failed */
299 if (!Result
) Process
->GrantedAccess
= 0;
301 /* Setup granted access */
302 Process
->GrantedAccess
|= (PROCESS_VM_OPERATION
|
305 PROCESS_QUERY_INFORMATION
|
307 PROCESS_CREATE_THREAD
|
309 PROCESS_CREATE_PROCESS
|
310 PROCESS_SET_INFORMATION
|
311 STANDARD_RIGHTS_ALL
|
315 /* Dereference the process */
316 ObDereferenceObject(Process
);
319 /* Dereference the token */
320 if (Token
) ObDereferenceObject(NewToken
);
324 /* FUNCTIONS *****************************************************************/
331 NtOpenProcessToken(IN HANDLE ProcessHandle
,
332 IN ACCESS_MASK DesiredAccess
,
333 OUT PHANDLE TokenHandle
)
335 /* Call the newer API */
336 return NtOpenProcessTokenEx(ProcessHandle
,
347 NtOpenProcessTokenEx(IN HANDLE ProcessHandle
,
348 IN ACCESS_MASK DesiredAccess
,
349 IN ULONG HandleAttributes
,
350 OUT PHANDLE TokenHandle
)
354 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
355 NTSTATUS Status
= STATUS_SUCCESS
;
357 PSTRACE(PS_SECURITY_DEBUG
,
358 "Process: %p DesiredAccess: %lx\n", ProcessHandle
, DesiredAccess
);
360 /* Check if caller was user-mode */
361 if (PreviousMode
!= KernelMode
)
363 /* Enter SEH for probing */
366 /* Probe the token handle */
367 ProbeForWriteHandle(TokenHandle
);
371 /* Get the exception code */
372 Status
= _SEH_GetExceptionCode();
376 /* Fail on exception */
377 if (!NT_SUCCESS(Status
)) return Status
;
380 /* Open the process token */
381 Status
= PsOpenTokenOfProcess(ProcessHandle
, &Token
);
382 if (NT_SUCCESS(Status
))
384 /* Reference it by handle and dereference the pointer */
385 Status
= ObOpenObjectByPointer(Token
,
392 ObDereferenceObject(Token
);
394 /* Make sure we got a handle */
395 if (NT_SUCCESS(Status
))
397 /* Enter SEH for write */
400 /* Return the handle */
401 *TokenHandle
= hToken
;
405 /* Get exception code */
406 Status
= _SEH_GetExceptionCode();
421 PsReferencePrimaryToken(PEPROCESS Process
)
425 PSTRACE(PS_SECURITY_DEBUG
, "Process: %p\n", Process
);
427 /* Fast Reference the Token */
428 Token
= ObFastReferenceObject(&Process
->Token
);
430 /* Check if we got the Token or if we got locked */
433 /* Lock the Process */
434 PspLockProcessSecurityShared(Process
);
436 /* Do a Locked Fast Reference */
437 Token
= ObFastReferenceObjectLocked(&Process
->Token
);
439 /* Unlock the Process */
440 PspUnlockProcessSecurityShared(Process
);
443 /* Return the Token */
452 PsOpenTokenOfProcess(IN HANDLE ProcessHandle
,
453 OUT PACCESS_TOKEN
* Token
)
458 PSTRACE(PS_SECURITY_DEBUG
, "Process: %p\n", ProcessHandle
);
461 Status
= ObReferenceObjectByHandle(ProcessHandle
,
462 PROCESS_QUERY_INFORMATION
,
467 if (NT_SUCCESS(Status
))
469 /* Reference the token and dereference the process */
470 *Token
= PsReferencePrimaryToken(Process
);
471 ObDereferenceObject(Process
);
483 PsAssignImpersonationToken(IN PETHREAD Thread
,
484 IN HANDLE TokenHandle
)
487 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
490 PSTRACE(PS_SECURITY_DEBUG
, "Thread: %p Token: %p\n", Thread
, TokenHandle
);
492 /* Check if we were given a handle */
495 /* Undo impersonation */
496 PsRevertThreadToSelf(Thread
);
497 return STATUS_SUCCESS
;
500 /* Get the token object */
501 Status
= ObReferenceObjectByHandle(TokenHandle
,
507 if (!NT_SUCCESS(Status
)) return(Status
);
509 /* Make sure it's an impersonation token */
510 if (SeTokenType(Token
) != TokenImpersonation
)
513 ObDereferenceObject(Token
);
514 return STATUS_BAD_TOKEN_TYPE
;
517 /* Get the impersonation level */
518 ImpersonationLevel
= SeTokenImpersonationLevel(Token
);
520 /* Call the impersonation API */
521 Status
= PsImpersonateClient(Thread
,
527 /* Dereference the token and return status */
528 ObDereferenceObject(Token
);
539 /* Call the per-thread API */
541 PsRevertThreadToSelf(PsGetCurrentThread());
549 PsRevertThreadToSelf(IN PETHREAD Thread
)
553 PSTRACE(PS_SECURITY_DEBUG
, "Thread: %p\n", Thread
);
555 /* Make sure we had impersonation information */
556 if (Thread
->ActiveImpersonationInfo
)
558 /* Lock the thread security */
559 PspLockThreadSecurityExclusive(Thread
);
561 /* Make sure it's still active */
562 if (Thread
->ActiveImpersonationInfo
)
564 /* Disable impersonation */
565 PspClearCrossThreadFlag(Thread
, CT_ACTIVE_IMPERSONATION_INFO_BIT
);
568 Token
= Thread
->ImpersonationInfo
->Token
;
571 /* Release thread security */
572 PspUnlockThreadSecurityExclusive(Thread
);
574 /* Check if we had a token */
577 /* Dereference the impersonation token */
578 ObDereferenceObject(Token
);
580 /* Write impersonation info to the TEB */
581 PspWriteTebImpersonationInfo(Thread
, PsGetCurrentThread());
591 PsImpersonateClient(IN PETHREAD Thread
,
592 IN PACCESS_TOKEN Token
,
593 IN BOOLEAN CopyOnOpen
,
594 IN BOOLEAN EffectiveOnly
,
595 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
597 PPS_IMPERSONATION_INFORMATION Impersonation
, OldData
;
598 PTOKEN OldToken
= NULL
;
600 PSTRACE(PS_SECURITY_DEBUG
, "Thread: %p, Token: %p\n", Thread
, Token
);
602 /* Check if we don't have a token */
605 /* Make sure we're impersonating */
606 if (Thread
->ActiveImpersonationInfo
)
608 /* We seem to be, lock the thread */
609 PspLockThreadSecurityExclusive(Thread
);
611 /* Make sure we're still impersonating */
612 if (Thread
->ActiveImpersonationInfo
)
614 /* Disable impersonation */
615 PspClearCrossThreadFlag(Thread
,
616 CT_ACTIVE_IMPERSONATION_INFO_BIT
);
619 OldToken
= Thread
->ImpersonationInfo
->Token
;
622 /* Unlock the process and write TEB information */
623 PspUnlockThreadSecurityExclusive(Thread
);
624 PspWriteTebImpersonationInfo(Thread
, PsGetCurrentThread());
629 /* Check if we have impersonation info */
630 Impersonation
= Thread
->ImpersonationInfo
;
633 /* We need to allocate a new one */
634 Impersonation
= ExAllocatePoolWithTag(PagedPool
,
635 sizeof(*Impersonation
),
636 TAG_PS_IMPERSONATION
);
637 if (!Impersonation
) return STATUS_INSUFFICIENT_RESOURCES
;
639 /* Update the pointer */
640 OldData
= InterlockedCompareExchangePointer(&Thread
->
646 /* Someone beat us to it, free our copy */
647 ExFreePool(Impersonation
);
648 Impersonation
= OldData
;
652 /* Check if this is a job, which we don't support yet */
653 if (Thread
->ThreadsProcess
->Job
) KEBUGCHECK(0);
655 /* Lock thread security */
656 PspLockThreadSecurityExclusive(Thread
);
658 /* Check if we're impersonating */
659 if (Thread
->ActiveImpersonationInfo
)
662 OldToken
= Impersonation
->Token
;
666 /* Otherwise, enable impersonation */
667 PspSetCrossThreadFlag(Thread
, CT_ACTIVE_IMPERSONATION_INFO_BIT
);
670 /* Now fill it out */
671 Impersonation
->ImpersonationLevel
= ImpersonationLevel
;
672 Impersonation
->CopyOnOpen
= CopyOnOpen
;
673 Impersonation
->EffectiveOnly
= EffectiveOnly
;
674 Impersonation
->Token
= Token
;
675 ObReferenceObject(Token
);
677 /* Unlock the thread */
678 PspUnlockThreadSecurityExclusive(Thread
);
680 /* Write impersonation info to the TEB */
681 PspWriteTebImpersonationInfo(Thread
, PsGetCurrentThread());
684 /* Dereference the token and return success */
685 if (OldToken
) PsDereferenceImpersonationToken(OldToken
);
686 return STATUS_SUCCESS
;
694 PsReferenceEffectiveToken(IN PETHREAD Thread
,
695 OUT IN PTOKEN_TYPE TokenType
,
696 OUT PBOOLEAN EffectiveOnly
,
697 OUT PSECURITY_IMPERSONATION_LEVEL Level
)
700 PACCESS_TOKEN Token
= NULL
;
702 PSTRACE(PS_SECURITY_DEBUG
,
703 "Thread: %p, TokenType: %p\n", Thread
, TokenType
);
705 /* Check if we don't have impersonation info */
706 Process
= Thread
->ThreadsProcess
;
707 if (!Thread
->ActiveImpersonationInfo
)
709 /* Fast Reference the Token */
710 Token
= ObFastReferenceObject(&Process
->Token
);
712 /* Check if we got the Token or if we got locked */
715 /* Lock the Process */
716 PspLockProcessSecurityShared(Process
);
718 /* Do a Locked Fast Reference */
719 Token
= ObFastReferenceObjectLocked(&Process
->Token
);
721 /* Unlock the Process */
722 PspUnlockProcessSecurityShared(Process
);
727 /* Lock the Process */
728 PspLockProcessSecurityShared(Process
);
730 /* Make sure impersonation is still active */
731 if (Thread
->ActiveImpersonationInfo
)
734 Token
= Thread
->ImpersonationInfo
->Token
;
735 ObReferenceObject(Token
);
737 /* Return data to caller */
738 *TokenType
= TokenImpersonation
;
739 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
740 *Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
742 /* Unlock the Process */
743 PspUnlockProcessSecurityShared(Process
);
747 /* Unlock the Process */
748 PspUnlockProcessSecurityShared(Process
);
751 /* Return the token */
752 *TokenType
= TokenPrimary
;
753 *EffectiveOnly
= FALSE
;
762 PsReferenceImpersonationToken(IN PETHREAD Thread
,
763 OUT PBOOLEAN CopyOnOpen
,
764 OUT PBOOLEAN EffectiveOnly
,
765 OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
769 PSTRACE(PS_SECURITY_DEBUG
, "Thread: %p\n", Thread
);
771 /* If we don't have impersonation info, just quit */
772 if (!Thread
->ActiveImpersonationInfo
) return NULL
;
774 /* Lock the thread */
775 PspLockThreadSecurityShared(Thread
);
777 /* Make sure we still have active impersonation */
778 if (Thread
->ActiveImpersonationInfo
)
780 /* Return data from caller */
781 ObReferenceObject(Thread
->ImpersonationInfo
->Token
);
782 *ImpersonationLevel
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
783 *CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
784 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
787 Token
= Thread
->ImpersonationInfo
->Token
;
790 /* Unlock thread and return impersonation token */
791 PspUnlockThreadSecurityShared(Thread
);
795 #undef PsDereferenceImpersonationToken
801 PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken
)
805 /* If we got a token, dereference it */
806 if (ImpersonationToken
) ObDereferenceObject(ImpersonationToken
);
809 #undef PsDereferencePrimaryToken
815 PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken
)
819 /* Dereference the token*/
820 ObDereferenceObject(PrimaryToken
);
828 PsDisableImpersonation(IN PETHREAD Thread
,
829 IN PSE_IMPERSONATION_STATE ImpersonationState
)
831 PPS_IMPERSONATION_INFORMATION Impersonation
= NULL
;
832 LONG NewValue
, OldValue
;
834 PSTRACE(PS_SECURITY_DEBUG
,
835 "Thread: %p State: %p\n", Thread
, ImpersonationState
);
837 /* Check if we don't have impersonation */
838 if (Thread
->ActiveImpersonationInfo
)
840 /* Lock thread security */
841 PspLockThreadSecurityExclusive(Thread
);
843 /* Disable impersonation */
844 OldValue
= Thread
->CrossThreadFlags
;
847 /* Attempt to change the flag */
849 InterlockedCompareExchange((PLONG
)&Thread
->CrossThreadFlags
,
851 CT_ACTIVE_IMPERSONATION_INFO_BIT
,
853 } while (NewValue
!= OldValue
);
855 /* Make sure nobody disabled it behind our back */
856 if (NewValue
& CT_ACTIVE_IMPERSONATION_INFO_BIT
)
858 /* Copy the old state */
859 Impersonation
= Thread
->ImpersonationInfo
;
860 ImpersonationState
->Token
= Impersonation
->Token
;
861 ImpersonationState
->CopyOnOpen
= Impersonation
->CopyOnOpen
;
862 ImpersonationState
->EffectiveOnly
= Impersonation
->EffectiveOnly
;
863 ImpersonationState
->Level
= Impersonation
->ImpersonationLevel
;
866 /* Unlock thread security */
867 PspUnlockThreadSecurityExclusive(Thread
);
869 /* If we had impersonation info, return true */
870 if (Impersonation
) return TRUE
;
873 /* Clear everything */
874 ImpersonationState
->Token
= NULL
;
875 ImpersonationState
->CopyOnOpen
= FALSE
;
876 ImpersonationState
->EffectiveOnly
= FALSE
;
877 ImpersonationState
->Level
= SecurityAnonymous
;
886 PsRestoreImpersonation(IN PETHREAD Thread
,
887 IN PSE_IMPERSONATION_STATE ImpersonationState
)
890 PPS_IMPERSONATION_INFORMATION Impersonation
;
892 PSTRACE(PS_SECURITY_DEBUG
,
893 "Thread: %p State: %p\n", Thread
, ImpersonationState
);
895 /* Lock thread security */
896 PspLockThreadSecurityExclusive(Thread
);
898 /* Get the impersonation info */
899 Impersonation
= Thread
->ImpersonationInfo
;
901 /* Check if we're impersonating */
902 if (Thread
->ActiveImpersonationInfo
)
905 Token
= Impersonation
->Token
;
908 /* Check if we have an impersonation state */
909 if (ImpersonationState
)
911 /* Fill out the impersonation info */
912 Impersonation
->ImpersonationLevel
= ImpersonationState
->Level
;
913 Impersonation
->CopyOnOpen
= ImpersonationState
->CopyOnOpen
;
914 Impersonation
->EffectiveOnly
= ImpersonationState
->EffectiveOnly
;
915 Impersonation
->Token
= ImpersonationState
->Token
;
917 /* Enable impersonation */
918 PspSetCrossThreadFlag(Thread
, CT_ACTIVE_IMPERSONATION_INFO_BIT
);
922 /* Disable impersonation */
923 PspClearCrossThreadFlag(Thread
, CT_ACTIVE_IMPERSONATION_INFO_BIT
);
926 /* Unlock the thread */
927 PspUnlockThreadSecurityExclusive(Thread
);
929 /* Dereference the token */
930 if (Token
) ObDereferenceObject(Token
);
935 NtImpersonateThread(IN HANDLE ThreadHandle
,
936 IN HANDLE ThreadToImpersonateHandle
,
937 IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
)
939 SECURITY_QUALITY_OF_SERVICE SafeServiceQoS
;
940 SECURITY_CLIENT_CONTEXT ClientContext
;
942 PETHREAD ThreadToImpersonate
;
943 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
944 NTSTATUS Status
= STATUS_SUCCESS
;
946 PSTRACE(PS_SECURITY_DEBUG
,
947 "Threads: %p %p\n", ThreadHandle
, ThreadToImpersonateHandle
);
949 /* Check if call came from user mode */
950 if (PreviousMode
!= KernelMode
)
952 /* Enter SEH for probing */
956 ProbeForRead(SecurityQualityOfService
,
957 sizeof(SECURITY_QUALITY_OF_SERVICE
),
961 SafeServiceQoS
= *SecurityQualityOfService
;
962 SecurityQualityOfService
= &SafeServiceQoS
;
966 /* Get exception status */
967 Status
= _SEH_GetExceptionCode();
971 /* Fail on exception */
972 if (!NT_SUCCESS(Status
)) return Status
;
975 /* Reference the thread */
976 Status
= ObReferenceObjectByHandle(ThreadHandle
,
982 if(NT_SUCCESS(Status
))
984 /* Reference the impersonating thead */
985 Status
= ObReferenceObjectByHandle(ThreadToImpersonateHandle
,
986 THREAD_DIRECT_IMPERSONATION
,
989 (PVOID
*)&ThreadToImpersonate
,
991 if(NT_SUCCESS(Status
))
993 /* Create a client security context */
994 Status
= SeCreateClientSecurity(ThreadToImpersonate
,
995 SecurityQualityOfService
,
998 if(NT_SUCCESS(Status
))
1000 /* Do the impersonation */
1001 SeImpersonateClient(&ClientContext
, Thread
);
1002 if(ClientContext
.ClientToken
)
1004 /* Dereference the client token if we had one */
1005 ObDereferenceObject(ClientContext
.ClientToken
);
1009 /* Dereference the thread to impersonate */
1010 ObDereferenceObject(ThreadToImpersonate
);
1013 /* Dereference the main thread */
1014 ObDereferenceObject(Thread
);