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 PsImpersonateClient(Thread
,
317 if (Token
!= NULL
) ObDereferenceObject(Token
);
318 return(STATUS_SUCCESS
);
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 ObReferenceObjectByPointer(Token
,
387 Thread
->ActiveImpersonationInfo
= TRUE
;
389 return STATUS_SUCCESS
;
395 PsReferenceEffectiveToken(PETHREAD Thread
,
396 PTOKEN_TYPE TokenType
,
397 PBOOLEAN EffectiveOnly
,
398 PSECURITY_IMPERSONATION_LEVEL Level
)
403 if (Thread
->ActiveImpersonationInfo
== FALSE
)
405 Process
= Thread
->ThreadsProcess
;
406 *TokenType
= TokenPrimary
;
407 *EffectiveOnly
= FALSE
;
409 /* Fast Reference the Token */
410 Token
= ObFastReferenceObject(&Process
->Token
);
412 /* Check if we got the Token or if we got locked */
415 /* Lock the Process */
416 PspLockProcessSecurityShared(Process
);
418 /* Do a Locked Fast Reference */
419 //Token = ObFastReferenceObjectLocked(&Process->Token);
421 /* Unlock the Process */
422 PspUnlockProcessSecurityShared(Process
);
427 Token
= Thread
->ImpersonationInfo
->Token
;
428 *TokenType
= TokenImpersonation
;
429 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
430 *Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
438 NtImpersonateThread(IN HANDLE ThreadHandle
,
439 IN HANDLE ThreadToImpersonateHandle
,
440 IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
)
442 SECURITY_QUALITY_OF_SERVICE SafeServiceQoS
;
443 SECURITY_CLIENT_CONTEXT ClientContext
;
445 PETHREAD ThreadToImpersonate
;
446 KPROCESSOR_MODE PreviousMode
;
447 NTSTATUS Status
= STATUS_SUCCESS
;
451 PreviousMode
= ExGetPreviousMode();
453 if(PreviousMode
!= KernelMode
)
457 ProbeForRead(SecurityQualityOfService
,
458 sizeof(SECURITY_QUALITY_OF_SERVICE
),
460 SafeServiceQoS
= *SecurityQualityOfService
;
461 SecurityQualityOfService
= &SafeServiceQoS
;
465 Status
= _SEH_GetExceptionCode();
469 if(!NT_SUCCESS(Status
))
475 Status
= ObReferenceObjectByHandle(ThreadHandle
,
481 if(NT_SUCCESS(Status
))
483 Status
= ObReferenceObjectByHandle(ThreadToImpersonateHandle
,
484 THREAD_DIRECT_IMPERSONATION
,
487 (PVOID
*)&ThreadToImpersonate
,
489 if(NT_SUCCESS(Status
))
491 Status
= SeCreateClientSecurity(ThreadToImpersonate
,
492 SecurityQualityOfService
,
495 if(NT_SUCCESS(Status
))
497 SeImpersonateClient(&ClientContext
,
499 if(ClientContext
.ClientToken
!= NULL
)
501 ObDereferenceObject (ClientContext
.ClientToken
);
505 ObDereferenceObject(ThreadToImpersonate
);
507 ObDereferenceObject(Thread
);
518 PsReferenceImpersonationToken(IN PETHREAD Thread
,
519 OUT PBOOLEAN CopyOnOpen
,
520 OUT PBOOLEAN EffectiveOnly
,
521 OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
524 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
529 *ImpersonationLevel
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
530 *CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
531 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
533 ObReferenceObjectByPointer(Thread
->ImpersonationInfo
->Token
,
538 return Thread
->ImpersonationInfo
->Token
;
541 #ifdef PsDereferencePrimaryToken
542 #undef PsDereferenceImpersonationToken
549 PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken
)
551 if (ImpersonationToken
) {
553 ObDereferenceObject(ImpersonationToken
);
557 #ifdef PsDereferencePrimaryToken
558 #undef PsDereferencePrimaryToken
565 PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken
)
567 ObDereferenceObject(PrimaryToken
);
575 PsDisableImpersonation(IN PETHREAD Thread
,
576 IN PSE_IMPERSONATION_STATE ImpersonationState
)
578 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
579 ImpersonationState
->Token
= NULL
;
580 ImpersonationState
->CopyOnOpen
= FALSE
;
581 ImpersonationState
->EffectiveOnly
= FALSE
;
582 ImpersonationState
->Level
= 0;
587 /* ExfAcquirePushLockExclusive(&Thread->ThreadLock); */
589 Thread
->ActiveImpersonationInfo
= FALSE
;
590 ImpersonationState
->Token
= Thread
->ImpersonationInfo
->Token
;
591 ImpersonationState
->CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
592 ImpersonationState
->EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
593 ImpersonationState
->Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
596 /* ExfReleasePushLock(&Thread->ThreadLock); */
606 PsRestoreImpersonation(IN PETHREAD Thread
,
607 IN PSE_IMPERSONATION_STATE ImpersonationState
)
610 PsImpersonateClient(Thread
,
611 ImpersonationState
->Token
,
612 ImpersonationState
->CopyOnOpen
,
613 ImpersonationState
->EffectiveOnly
,
614 ImpersonationState
->Level
);
616 ObfDereferenceObject(ImpersonationState
->Token
);