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 /* FUNCTIONS *****************************************************************/
23 NtOpenProcessToken(IN HANDLE ProcessHandle
,
24 IN ACCESS_MASK DesiredAccess
,
25 OUT PHANDLE TokenHandle
)
27 return NtOpenProcessTokenEx(ProcessHandle
,
38 NtOpenProcessTokenEx(IN HANDLE ProcessHandle
,
39 IN ACCESS_MASK DesiredAccess
,
40 IN ULONG HandleAttributes
,
41 OUT PHANDLE TokenHandle
)
45 KPROCESSOR_MODE PreviousMode
;
46 NTSTATUS Status
= STATUS_SUCCESS
;
50 PreviousMode
= ExGetPreviousMode();
52 if(PreviousMode
== UserMode
)
56 ProbeForWrite(TokenHandle
,
62 Status
= _SEH_GetExceptionCode();
66 if(!NT_SUCCESS(Status
))
72 Status
= PsOpenTokenOfProcess(ProcessHandle
,
74 if(NT_SUCCESS(Status
))
76 Status
= ObCreateHandle(PsGetCurrentProcess(),
81 ObDereferenceObject(Token
);
83 if(NT_SUCCESS(Status
))
87 *TokenHandle
= hToken
;
91 Status
= _SEH_GetExceptionCode();
105 PsReferencePrimaryToken(PEPROCESS Process
)
107 /* Reference and return the Token */
108 ObReferenceObjectByPointer(Process
->Token
,
112 return(Process
->Token
);
120 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
121 PACCESS_TOKEN
* Token
)
127 Status
= ObReferenceObjectByHandle(ProcessHandle
,
128 PROCESS_QUERY_INFORMATION
,
135 if(NT_SUCCESS(Status
)) {
137 *Token
= PsReferencePrimaryToken(Process
);
138 ObDereferenceObject(Process
);
147 PspInitializeProcessSecurity(PEPROCESS Process
,
148 PEPROCESS Parent OPTIONAL
)
150 NTSTATUS Status
= STATUS_SUCCESS
;
152 /* If we have a parent, then duplicate the Token */
157 OBJECT_ATTRIBUTES ObjectAttributes
;
159 pParentToken
= (PACCESS_TOKEN
)Parent
->Token
;
161 /* Initialize the Object Attributes */
162 InitializeObjectAttributes(&ObjectAttributes
,
168 /* Duplicate the Token */
169 Status
= SepDuplicateToken(pParentToken
,
173 pParentToken
->ImpersonationLevel
,
177 if(!NT_SUCCESS(Status
)) {
179 DPRINT1("Failed to Duplicate Token\n");
183 Process
->Token
= pNewToken
;
190 /* No parent, this is the Initial System Process. Assign Boot Token */
191 BootToken
= SepCreateSystemProcessToken();
192 BootToken
->TokenInUse
= TRUE
;
193 Process
->Token
= BootToken
;
194 ObReferenceObject(BootToken
);
196 DPRINT1("PspInitializeProcessSecurity called with no parent.\n");
200 /* Return to caller */
207 PspAssignPrimaryToken(PEPROCESS Process
,
211 PACCESS_TOKEN OldToken
;
214 /* Reference the Token */
215 Status
= ObReferenceObjectByHandle(TokenHandle
,
221 if (!NT_SUCCESS(Status
)) {
227 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
229 /* Derefernece Tokens and Return */
230 if (NT_SUCCESS(Status
)) ObDereferenceObject(OldToken
);
231 ObDereferenceObject(Token
);
240 PsAssignImpersonationToken(PETHREAD Thread
,
244 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
247 if (TokenHandle
!= NULL
) {
249 Status
= ObReferenceObjectByHandle(TokenHandle
,
256 if (!NT_SUCCESS(Status
)) {
261 ImpersonationLevel
= SeTokenImpersonationLevel(Token
);
266 ImpersonationLevel
= 0;
269 PsImpersonateClient(Thread
,
275 if (Token
!= NULL
) ObDereferenceObject(Token
);
276 return(STATUS_SUCCESS
);
283 PsRevertToSelf (VOID
)
285 PsRevertThreadToSelf(PsGetCurrentThread());
293 PsRevertThreadToSelf(IN PETHREAD Thread
)
295 if (Thread
->ActiveImpersonationInfo
== TRUE
) {
297 ObDereferenceObject (Thread
->ImpersonationInfo
->Token
);
298 Thread
->ActiveImpersonationInfo
= FALSE
;
307 PsImpersonateClient(IN PETHREAD Thread
,
308 IN PACCESS_TOKEN Token
,
309 IN BOOLEAN CopyOnOpen
,
310 IN BOOLEAN EffectiveOnly
,
311 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
316 if (Thread
->ActiveImpersonationInfo
== TRUE
) {
318 Thread
->ActiveImpersonationInfo
= FALSE
;
320 if (Thread
->ImpersonationInfo
->Token
!= NULL
) {
322 ObDereferenceObject (Thread
->ImpersonationInfo
->Token
);
329 if (Thread
->ImpersonationInfo
== NULL
) {
331 Thread
->ImpersonationInfo
= ExAllocatePool(NonPagedPool
,
332 sizeof(PS_IMPERSONATION_INFORMATION
));
335 Thread
->ImpersonationInfo
->ImpersonationLevel
= ImpersonationLevel
;
336 Thread
->ImpersonationInfo
->CopyOnOpen
= CopyOnOpen
;
337 Thread
->ImpersonationInfo
->EffectiveOnly
= EffectiveOnly
;
338 Thread
->ImpersonationInfo
->Token
= Token
;
340 ObReferenceObjectByPointer(Token
,
345 Thread
->ActiveImpersonationInfo
= TRUE
;
351 PsReferenceEffectiveToken(PETHREAD Thread
,
352 PTOKEN_TYPE TokenType
,
353 PBOOLEAN EffectiveOnly
,
354 PSECURITY_IMPERSONATION_LEVEL Level
)
359 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
361 Process
= Thread
->ThreadsProcess
;
362 *TokenType
= TokenPrimary
;
363 *EffectiveOnly
= FALSE
;
364 Token
= Process
->Token
;
368 Token
= Thread
->ImpersonationInfo
->Token
;
369 *TokenType
= TokenImpersonation
;
370 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
371 *Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
379 NtImpersonateThread(IN HANDLE ThreadHandle
,
380 IN HANDLE ThreadToImpersonateHandle
,
381 IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
)
383 SECURITY_QUALITY_OF_SERVICE SafeServiceQoS
;
384 SECURITY_CLIENT_CONTEXT ClientContext
;
386 PETHREAD ThreadToImpersonate
;
387 KPROCESSOR_MODE PreviousMode
;
388 NTSTATUS Status
= STATUS_SUCCESS
;
392 PreviousMode
= ExGetPreviousMode();
394 if(PreviousMode
!= KernelMode
)
398 ProbeForRead(SecurityQualityOfService
,
399 sizeof(SECURITY_QUALITY_OF_SERVICE
),
401 SafeServiceQoS
= *SecurityQualityOfService
;
402 SecurityQualityOfService
= &SafeServiceQoS
;
406 Status
= _SEH_GetExceptionCode();
410 if(!NT_SUCCESS(Status
))
416 Status
= ObReferenceObjectByHandle(ThreadHandle
,
422 if(NT_SUCCESS(Status
))
424 Status
= ObReferenceObjectByHandle(ThreadToImpersonateHandle
,
425 THREAD_DIRECT_IMPERSONATION
,
428 (PVOID
*)&ThreadToImpersonate
,
430 if(NT_SUCCESS(Status
))
432 Status
= SeCreateClientSecurity(ThreadToImpersonate
,
433 SecurityQualityOfService
,
436 if(NT_SUCCESS(Status
))
438 SeImpersonateClient(&ClientContext
,
440 if(ClientContext
.ClientToken
!= NULL
)
442 ObDereferenceObject (ClientContext
.ClientToken
);
446 ObDereferenceObject(ThreadToImpersonate
);
448 ObDereferenceObject(Thread
);
459 PsReferenceImpersonationToken(IN PETHREAD Thread
,
460 OUT PBOOLEAN CopyOnOpen
,
461 OUT PBOOLEAN EffectiveOnly
,
462 OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
465 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
470 *ImpersonationLevel
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
471 *CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
472 *EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
474 ObReferenceObjectByPointer(Thread
->ImpersonationInfo
->Token
,
479 return Thread
->ImpersonationInfo
->Token
;
482 #ifdef PsDereferencePrimaryToken
483 #undef PsDereferenceImpersonationToken
490 PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken
)
492 if (ImpersonationToken
) {
494 ObDereferenceObject(ImpersonationToken
);
498 #ifdef PsDereferencePrimaryToken
499 #undef PsDereferencePrimaryToken
506 PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken
)
508 ObDereferenceObject(PrimaryToken
);
516 PsDisableImpersonation(IN PETHREAD Thread
,
517 IN PSE_IMPERSONATION_STATE ImpersonationState
)
519 if (Thread
->ActiveImpersonationInfo
== FALSE
) {
520 ImpersonationState
->Token
= NULL
;
521 ImpersonationState
->CopyOnOpen
= FALSE
;
522 ImpersonationState
->EffectiveOnly
= FALSE
;
523 ImpersonationState
->Level
= 0;
528 /* ExfAcquirePushLockExclusive(&Thread->ThreadLock); */
530 Thread
->ActiveImpersonationInfo
= FALSE
;
531 ImpersonationState
->Token
= Thread
->ImpersonationInfo
->Token
;
532 ImpersonationState
->CopyOnOpen
= Thread
->ImpersonationInfo
->CopyOnOpen
;
533 ImpersonationState
->EffectiveOnly
= Thread
->ImpersonationInfo
->EffectiveOnly
;
534 ImpersonationState
->Level
= Thread
->ImpersonationInfo
->ImpersonationLevel
;
537 /* ExfReleasePushLock(&Thread->ThreadLock); */
547 PsRestoreImpersonation(IN PETHREAD Thread
,
548 IN PSE_IMPERSONATION_STATE ImpersonationState
)
551 PsImpersonateClient(Thread
,
552 ImpersonationState
->Token
,
553 ImpersonationState
->CopyOnOpen
,
554 ImpersonationState
->EffectiveOnly
,
555 ImpersonationState
->Level
);
557 ObfDereferenceObject(ImpersonationState
->Token
);