2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/security.c
5 * PURPOSE: Process Manager Security (Tokens, Impersionation)
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
10 /* INCLUDES ******************************************************************/
14 #include <internal/debug.h>
16 /* INTERNAL ******************************************************************/
18 /* FIXME: Turn into Macro */
21 PspLockProcessSecurityShared(PEPROCESS Process
)
23 /* Enter a Guarded Region */
24 KeEnterGuardedRegion();
26 /* Lock the Process */
27 //ExAcquirePushLockShared(&Process->ProcessLock);
30 /* FIXME: Turn into Macro */
33 PspUnlockProcessSecurityShared(PEPROCESS Process
)
35 /* Unlock the Process */
36 //ExReleasePushLockShared(&Process->ProcessLock);
38 /* Leave Guarded Region */
39 KeLeaveGuardedRegion();
42 /* FUNCTIONS *****************************************************************/
49 NtOpenProcessToken(IN HANDLE ProcessHandle
,
50 IN ACCESS_MASK DesiredAccess
,
51 OUT PHANDLE TokenHandle
)
53 return NtOpenProcessTokenEx(ProcessHandle
,
64 NtOpenProcessTokenEx(IN HANDLE ProcessHandle
,
65 IN ACCESS_MASK DesiredAccess
,
66 IN ULONG HandleAttributes
,
67 OUT PHANDLE TokenHandle
)
71 KPROCESSOR_MODE PreviousMode
;
72 NTSTATUS Status
= STATUS_SUCCESS
;
76 PreviousMode
= ExGetPreviousMode();
78 if(PreviousMode
!= KernelMode
)
82 ProbeForWriteHandle(TokenHandle
);
86 Status
= _SEH_GetExceptionCode();
90 if(!NT_SUCCESS(Status
))
96 Status
= PsOpenTokenOfProcess(ProcessHandle
,
98 if(NT_SUCCESS(Status
))
100 Status
= ObpCreateHandle(PsGetCurrentProcess(),
105 ObDereferenceObject(Token
);
107 if(NT_SUCCESS(Status
))
111 *TokenHandle
= hToken
;
115 Status
= _SEH_GetExceptionCode();
129 PsReferencePrimaryToken(PEPROCESS Process
)
133 /* Fast Reference the Token */
134 Token
= ObFastReferenceObject(&Process
->Token
);
136 /* Check if we got the Token or if we got locked */
139 /* Lock the Process */
140 PspLockProcessSecurityShared(Process
);
142 /* Do a Locked Fast Reference */
143 //Token = ObFastReferenceObjectLocked(&Process->Token);
145 /* Unlock the Process */
146 PspUnlockProcessSecurityShared(Process
);
149 /* Return the Token */
158 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
159 PACCESS_TOKEN
* Token
)
165 Status
= ObReferenceObjectByHandle(ProcessHandle
,
166 PROCESS_QUERY_INFORMATION
,
173 if(NT_SUCCESS(Status
)) {
175 *Token
= PsReferencePrimaryToken(Process
);
176 ObDereferenceObject(Process
);
185 PspInitializeProcessSecurity(PEPROCESS Process
,
186 PEPROCESS Parent OPTIONAL
)
188 NTSTATUS Status
= STATUS_SUCCESS
;
190 /* If we have a parent, then duplicate the Token */
195 OBJECT_ATTRIBUTES ObjectAttributes
;
197 /* Get the Parent Token */
198 pParentToken
= PsReferencePrimaryToken(Parent
);
200 /* Initialize the Object Attributes */
201 InitializeObjectAttributes(&ObjectAttributes
,
207 /* Duplicate the Token */
208 Status
= SepDuplicateToken(pParentToken
,
212 pParentToken
->ImpersonationLevel
,
216 if(!NT_SUCCESS(Status
)) {
218 DPRINT1("Failed to Duplicate Token\n");
222 /* Dereference the Token */
223 ObFastDereferenceObject(&Parent
->Token
, pParentToken
);
225 /* Set the new Token */
226 ObInitializeFastReference(&Process
->Token
, pNewToken
);
233 /* No parent, this is the Initial System Process. Assign Boot Token */
234 BootToken
= SepCreateSystemProcessToken();
235 BootToken
->TokenInUse
= TRUE
;
236 Process
->Token
= BootToken
;
237 ObReferenceObject(BootToken
);
239 DPRINT1("PspInitializeProcessSecurity called with no parent.\n");
243 /* Return to caller */
250 PspAssignPrimaryToken(PEPROCESS Process
,
254 PACCESS_TOKEN OldToken
;
257 /* Reference the Token */
258 Status
= ObReferenceObjectByHandle(TokenHandle
,
264 if (!NT_SUCCESS(Status
)) {
270 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
272 /* Derefernece Tokens and Return */
273 ObDereferenceObject(Token
);
282 PsAssignImpersonationToken(PETHREAD Thread
,
286 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
289 if (TokenHandle
!= NULL
) {
291 Status
= ObReferenceObjectByHandle(TokenHandle
,
298 if (!NT_SUCCESS(Status
)) {
303 ImpersonationLevel
= SeTokenImpersonationLevel(Token
);
308 ImpersonationLevel
= 0;
311 Status
= PsImpersonateClient(Thread
,
317 if (Token
!= NULL
) ObDereferenceObject(Token
);
325 PsRevertToSelf (VOID
)
327 PsRevertThreadToSelf(PsGetCurrentThread());
335 PsRevertThreadToSelf(IN PETHREAD Thread
)
337 if (Thread
->ActiveImpersonationInfo
== TRUE
) {
339 ObDereferenceObject (Thread
->ImpersonationInfo
->Token
);
340 Thread
->ActiveImpersonationInfo
= FALSE
;
349 PsImpersonateClient(IN PETHREAD Thread
,
350 IN PACCESS_TOKEN Token
,
351 IN BOOLEAN CopyOnOpen
,
352 IN BOOLEAN EffectiveOnly
,
353 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
358 if (Thread
->ActiveImpersonationInfo
== TRUE
) {
360 Thread
->ActiveImpersonationInfo
= FALSE
;
362 if (Thread
->ImpersonationInfo
->Token
!= NULL
) {
364 ObDereferenceObject (Thread
->ImpersonationInfo
->Token
);
368 return STATUS_UNSUCCESSFUL
;
371 if (Thread
->ImpersonationInfo
== NULL
) {
373 Thread
->ImpersonationInfo
= ExAllocatePool(NonPagedPool
,
374 sizeof(PS_IMPERSONATION_INFORMATION
));
377 Thread
->ImpersonationInfo
->ImpersonationLevel
= ImpersonationLevel
;
378 Thread
->ImpersonationInfo
->CopyOnOpen
= CopyOnOpen
;
379 Thread
->ImpersonationInfo
->EffectiveOnly
= EffectiveOnly
;
380 Thread
->ImpersonationInfo
->Token
= Token
;
382 ObReferenceObject(Token
);
384 Thread
->ActiveImpersonationInfo
= TRUE
;
386 return STATUS_SUCCESS
;
392 PsReferenceEffectiveToken(PETHREAD Thread
,
393 PTOKEN_TYPE TokenType
,
394 PBOOLEAN EffectiveOnly
,
395 PSECURITY_IMPERSONATION_LEVEL Level
)
400 if (Thread
->ActiveImpersonationInfo
== FALSE
)
402 Process
= Thread
->ThreadsProcess
;
403 *TokenType
= TokenPrimary
;
404 *EffectiveOnly
= FALSE
;
406 /* Fast Reference the Token */
407 Token
= ObFastReferenceObject(&Process
->Token
);
409 /* Check if we got the Token or if we got locked */
412 /* Lock the Process */
413 PspLockProcessSecurityShared(Process
);
415 /* Do a Locked Fast Reference */
416 //Token = ObFastReferenceObjectLocked(&Process->Token);
418 /* Unlock the Process */
419 PspUnlockProcessSecurityShared(Process
);
424 Token
= Thread
->ImpersonationInfo
->Token
;
425 *TokenType
= TokenImpersonation
;
426 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
427 *Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
435 NtImpersonateThread(IN HANDLE ThreadHandle
,
436 IN HANDLE ThreadToImpersonateHandle
,
437 IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
)
439 SECURITY_QUALITY_OF_SERVICE SafeServiceQoS
;
440 SECURITY_CLIENT_CONTEXT ClientContext
;
442 PETHREAD ThreadToImpersonate
;
443 KPROCESSOR_MODE PreviousMode
;
444 NTSTATUS Status
= STATUS_SUCCESS
;
448 PreviousMode
= ExGetPreviousMode();
450 if(PreviousMode
!= KernelMode
)
454 ProbeForRead(SecurityQualityOfService
,
455 sizeof(SECURITY_QUALITY_OF_SERVICE
),
457 SafeServiceQoS
= *SecurityQualityOfService
;
458 SecurityQualityOfService
= &SafeServiceQoS
;
462 Status
= _SEH_GetExceptionCode();
466 if(!NT_SUCCESS(Status
))
472 Status
= ObReferenceObjectByHandle(ThreadHandle
,
478 if(NT_SUCCESS(Status
))
480 Status
= ObReferenceObjectByHandle(ThreadToImpersonateHandle
,
481 THREAD_DIRECT_IMPERSONATION
,
484 (PVOID
*)&ThreadToImpersonate
,
486 if(NT_SUCCESS(Status
))
488 Status
= SeCreateClientSecurity(ThreadToImpersonate
,
489 SecurityQualityOfService
,
492 if(NT_SUCCESS(Status
))
494 SeImpersonateClient(&ClientContext
,
496 if(ClientContext
.ClientToken
!= NULL
)
498 ObDereferenceObject (ClientContext
.ClientToken
);
502 ObDereferenceObject(ThreadToImpersonate
);
504 ObDereferenceObject(Thread
);
515 PsReferenceImpersonationToken(IN PETHREAD Thread
,
516 OUT PBOOLEAN CopyOnOpen
,
517 OUT PBOOLEAN EffectiveOnly
,
518 OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
521 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
526 *ImpersonationLevel
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
527 *CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
528 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
530 ObReferenceObjectByPointer(Thread
->ImpersonationInfo
->Token
,
535 return Thread
->ImpersonationInfo
->Token
;
538 #ifdef PsDereferencePrimaryToken
539 #undef PsDereferenceImpersonationToken
546 PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken
)
548 if (ImpersonationToken
) {
550 ObDereferenceObject(ImpersonationToken
);
554 #ifdef PsDereferencePrimaryToken
555 #undef PsDereferencePrimaryToken
562 PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken
)
564 ObDereferenceObject(PrimaryToken
);
572 PsDisableImpersonation(IN PETHREAD Thread
,
573 IN PSE_IMPERSONATION_STATE ImpersonationState
)
575 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
576 ImpersonationState
->Token
= NULL
;
577 ImpersonationState
->CopyOnOpen
= FALSE
;
578 ImpersonationState
->EffectiveOnly
= FALSE
;
579 ImpersonationState
->Level
= 0;
584 /* ExfAcquirePushLockExclusive(&Thread->ThreadLock); */
586 Thread
->ActiveImpersonationInfo
= FALSE
;
587 ImpersonationState
->Token
= Thread
->ImpersonationInfo
->Token
;
588 ImpersonationState
->CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
589 ImpersonationState
->EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
590 ImpersonationState
->Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
593 /* ExfReleasePushLock(&Thread->ThreadLock); */
603 PsRestoreImpersonation(IN PETHREAD Thread
,
604 IN PSE_IMPERSONATION_STATE ImpersonationState
)
607 PsImpersonateClient(Thread
,
608 ImpersonationState
->Token
,
609 ImpersonationState
->CopyOnOpen
,
610 ImpersonationState
->EffectiveOnly
,
611 ImpersonationState
->Level
);
613 ObfDereferenceObject(ImpersonationState
->Token
);