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(Token
,
104 ObDereferenceObject(Token
);
106 if(NT_SUCCESS(Status
))
110 *TokenHandle
= hToken
;
114 Status
= _SEH_GetExceptionCode();
128 PsReferencePrimaryToken(PEPROCESS Process
)
132 /* Fast Reference the Token */
133 Token
= ObFastReferenceObject(&Process
->Token
);
135 /* Check if we got the Token or if we got locked */
138 /* Lock the Process */
139 PspLockProcessSecurityShared(Process
);
141 /* Do a Locked Fast Reference */
142 //Token = ObFastReferenceObjectLocked(&Process->Token);
144 /* Unlock the Process */
145 PspUnlockProcessSecurityShared(Process
);
148 /* Return the Token */
157 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
158 PACCESS_TOKEN
* Token
)
164 Status
= ObReferenceObjectByHandle(ProcessHandle
,
165 PROCESS_QUERY_INFORMATION
,
172 if(NT_SUCCESS(Status
)) {
174 *Token
= PsReferencePrimaryToken(Process
);
175 ObDereferenceObject(Process
);
184 PspInitializeProcessSecurity(PEPROCESS Process
,
185 PEPROCESS Parent OPTIONAL
)
187 NTSTATUS Status
= STATUS_SUCCESS
;
189 /* If we have a parent, then duplicate the Token */
194 OBJECT_ATTRIBUTES ObjectAttributes
;
196 /* Get the Parent Token */
197 pParentToken
= PsReferencePrimaryToken(Parent
);
199 /* Initialize the Object Attributes */
200 InitializeObjectAttributes(&ObjectAttributes
,
206 /* Duplicate the Token */
207 Status
= SepDuplicateToken(pParentToken
,
211 pParentToken
->ImpersonationLevel
,
215 if(!NT_SUCCESS(Status
)) {
217 DPRINT1("Failed to Duplicate Token\n");
221 /* Dereference the Token */
222 ObFastDereferenceObject(&Parent
->Token
, pParentToken
);
224 /* Set the new Token */
225 ObInitializeFastReference(&Process
->Token
, pNewToken
);
232 /* No parent, this is the Initial System Process. Assign Boot Token */
233 BootToken
= SepCreateSystemProcessToken();
234 BootToken
->TokenInUse
= TRUE
;
235 Process
->Token
= BootToken
;
236 ObReferenceObject(BootToken
);
238 DPRINT1("PspInitializeProcessSecurity called with no parent.\n");
242 /* Return to caller */
249 PspAssignPrimaryToken(PEPROCESS Process
,
253 PACCESS_TOKEN OldToken
;
256 /* Reference the Token */
257 Status
= ObReferenceObjectByHandle(TokenHandle
,
263 if (!NT_SUCCESS(Status
)) {
269 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
271 /* Derefernece Tokens and Return */
272 ObDereferenceObject(Token
);
281 PsAssignImpersonationToken(PETHREAD Thread
,
285 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
288 if (TokenHandle
!= NULL
) {
290 Status
= ObReferenceObjectByHandle(TokenHandle
,
297 if (!NT_SUCCESS(Status
)) {
302 ImpersonationLevel
= SeTokenImpersonationLevel(Token
);
307 ImpersonationLevel
= 0;
310 Status
= PsImpersonateClient(Thread
,
316 if (Token
!= NULL
) ObDereferenceObject(Token
);
324 PsRevertToSelf (VOID
)
326 PsRevertThreadToSelf(PsGetCurrentThread());
334 PsRevertThreadToSelf(IN PETHREAD Thread
)
336 if (Thread
->ActiveImpersonationInfo
== TRUE
) {
338 ObDereferenceObject (Thread
->ImpersonationInfo
->Token
);
339 Thread
->ActiveImpersonationInfo
= FALSE
;
348 PsImpersonateClient(IN PETHREAD Thread
,
349 IN PACCESS_TOKEN Token
,
350 IN BOOLEAN CopyOnOpen
,
351 IN BOOLEAN EffectiveOnly
,
352 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
357 if (Thread
->ActiveImpersonationInfo
== TRUE
) {
359 Thread
->ActiveImpersonationInfo
= FALSE
;
361 if (Thread
->ImpersonationInfo
->Token
!= NULL
) {
363 ObDereferenceObject (Thread
->ImpersonationInfo
->Token
);
367 return STATUS_UNSUCCESSFUL
;
370 if (Thread
->ImpersonationInfo
== NULL
) {
372 Thread
->ImpersonationInfo
= ExAllocatePool(NonPagedPool
,
373 sizeof(PS_IMPERSONATION_INFORMATION
));
376 Thread
->ImpersonationInfo
->ImpersonationLevel
= ImpersonationLevel
;
377 Thread
->ImpersonationInfo
->CopyOnOpen
= CopyOnOpen
;
378 Thread
->ImpersonationInfo
->EffectiveOnly
= EffectiveOnly
;
379 Thread
->ImpersonationInfo
->Token
= Token
;
381 ObReferenceObject(Token
);
383 Thread
->ActiveImpersonationInfo
= TRUE
;
385 return STATUS_SUCCESS
;
391 PsReferenceEffectiveToken(PETHREAD Thread
,
392 PTOKEN_TYPE TokenType
,
393 PBOOLEAN EffectiveOnly
,
394 PSECURITY_IMPERSONATION_LEVEL Level
)
399 if (Thread
->ActiveImpersonationInfo
== FALSE
)
401 Process
= Thread
->ThreadsProcess
;
402 *TokenType
= TokenPrimary
;
403 *EffectiveOnly
= FALSE
;
405 /* Fast Reference the Token */
406 Token
= ObFastReferenceObject(&Process
->Token
);
408 /* Check if we got the Token or if we got locked */
411 /* Lock the Process */
412 PspLockProcessSecurityShared(Process
);
414 /* Do a Locked Fast Reference */
415 //Token = ObFastReferenceObjectLocked(&Process->Token);
417 /* Unlock the Process */
418 PspUnlockProcessSecurityShared(Process
);
423 Token
= Thread
->ImpersonationInfo
->Token
;
424 *TokenType
= TokenImpersonation
;
425 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
426 *Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
434 NtImpersonateThread(IN HANDLE ThreadHandle
,
435 IN HANDLE ThreadToImpersonateHandle
,
436 IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
)
438 SECURITY_QUALITY_OF_SERVICE SafeServiceQoS
;
439 SECURITY_CLIENT_CONTEXT ClientContext
;
441 PETHREAD ThreadToImpersonate
;
442 KPROCESSOR_MODE PreviousMode
;
443 NTSTATUS Status
= STATUS_SUCCESS
;
447 PreviousMode
= ExGetPreviousMode();
449 if(PreviousMode
!= KernelMode
)
453 ProbeForRead(SecurityQualityOfService
,
454 sizeof(SECURITY_QUALITY_OF_SERVICE
),
456 SafeServiceQoS
= *SecurityQualityOfService
;
457 SecurityQualityOfService
= &SafeServiceQoS
;
461 Status
= _SEH_GetExceptionCode();
465 if(!NT_SUCCESS(Status
))
471 Status
= ObReferenceObjectByHandle(ThreadHandle
,
477 if(NT_SUCCESS(Status
))
479 Status
= ObReferenceObjectByHandle(ThreadToImpersonateHandle
,
480 THREAD_DIRECT_IMPERSONATION
,
483 (PVOID
*)&ThreadToImpersonate
,
485 if(NT_SUCCESS(Status
))
487 Status
= SeCreateClientSecurity(ThreadToImpersonate
,
488 SecurityQualityOfService
,
491 if(NT_SUCCESS(Status
))
493 SeImpersonateClient(&ClientContext
,
495 if(ClientContext
.ClientToken
!= NULL
)
497 ObDereferenceObject (ClientContext
.ClientToken
);
501 ObDereferenceObject(ThreadToImpersonate
);
503 ObDereferenceObject(Thread
);
514 PsReferenceImpersonationToken(IN PETHREAD Thread
,
515 OUT PBOOLEAN CopyOnOpen
,
516 OUT PBOOLEAN EffectiveOnly
,
517 OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
520 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
525 *ImpersonationLevel
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
526 *CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
527 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
529 ObReferenceObjectByPointer(Thread
->ImpersonationInfo
->Token
,
534 return Thread
->ImpersonationInfo
->Token
;
537 #ifdef PsDereferencePrimaryToken
538 #undef PsDereferenceImpersonationToken
545 PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken
)
547 if (ImpersonationToken
) {
549 ObDereferenceObject(ImpersonationToken
);
553 #ifdef PsDereferencePrimaryToken
554 #undef PsDereferencePrimaryToken
561 PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken
)
563 ObDereferenceObject(PrimaryToken
);
571 PsDisableImpersonation(IN PETHREAD Thread
,
572 IN PSE_IMPERSONATION_STATE ImpersonationState
)
574 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
575 ImpersonationState
->Token
= NULL
;
576 ImpersonationState
->CopyOnOpen
= FALSE
;
577 ImpersonationState
->EffectiveOnly
= FALSE
;
578 ImpersonationState
->Level
= 0;
583 /* ExfAcquirePushLockExclusive(&Thread->ThreadLock); */
585 Thread
->ActiveImpersonationInfo
= FALSE
;
586 ImpersonationState
->Token
= Thread
->ImpersonationInfo
->Token
;
587 ImpersonationState
->CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
588 ImpersonationState
->EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
589 ImpersonationState
->Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
592 /* ExfReleasePushLock(&Thread->ThreadLock); */
602 PsRestoreImpersonation(IN PETHREAD Thread
,
603 IN PSE_IMPERSONATION_STATE ImpersonationState
)
606 PsImpersonateClient(Thread
,
607 ImpersonationState
->Token
,
608 ImpersonationState
->CopyOnOpen
,
609 ImpersonationState
->EffectiveOnly
,
610 ImpersonationState
->Level
);
612 ObfDereferenceObject(ImpersonationState
->Token
);