Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensecurity.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/ps/security.c 00005 * PURPOSE: Process Manager: Process/Thread Security 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Eric Kohl 00008 * Thomas Weidenmueller (w3seek@reactos.org) 00009 */ 00010 00011 /* INCLUDES ******************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 #define NDEBUG 00015 #include <debug.h> 00016 00017 PTOKEN PspBootAccessToken; 00018 00019 VOID 00020 NTAPI 00021 SeAssignPrimaryToken( 00022 IN PEPROCESS Process, 00023 IN PTOKEN Token 00024 ); 00025 00026 /* PRIVATE FUNCTIONS *********************************************************/ 00027 00028 VOID 00029 NTAPI 00030 PspDeleteProcessSecurity(IN PEPROCESS Process) 00031 { 00032 PAGED_CODE(); 00033 PSTRACE(PS_SECURITY_DEBUG, "Process: %p\n", Process); 00034 00035 /* Check if we have a token */ 00036 if (Process->Token.Object) 00037 { 00038 /* Deassign it */ 00039 SeDeassignPrimaryToken(Process); 00040 Process->Token.Object = NULL; 00041 } 00042 } 00043 00044 VOID 00045 NTAPI 00046 PspDeleteThreadSecurity(IN PETHREAD Thread) 00047 { 00048 PPS_IMPERSONATION_INFORMATION ImpersonationInfo = Thread->ImpersonationInfo; 00049 PAGED_CODE(); 00050 PSTRACE(PS_SECURITY_DEBUG, "Thread: %p\n", Thread); 00051 00052 /* Check if we have active impersonation info */ 00053 if (Thread->ActiveImpersonationInfo) 00054 { 00055 /* Dereference its token */ 00056 ObDereferenceObject(ImpersonationInfo->Token); 00057 } 00058 00059 /* Check if we have impersonation info */ 00060 if (ImpersonationInfo) 00061 { 00062 /* Free it */ 00063 ExFreePool(ImpersonationInfo); 00064 PspClearCrossThreadFlag(Thread, CT_ACTIVE_IMPERSONATION_INFO_BIT); 00065 Thread->ImpersonationInfo = NULL; 00066 } 00067 } 00068 00069 NTSTATUS 00070 NTAPI 00071 PspInitializeProcessSecurity(IN PEPROCESS Process, 00072 IN PEPROCESS Parent OPTIONAL) 00073 { 00074 NTSTATUS Status = STATUS_SUCCESS; 00075 PTOKEN NewToken, ParentToken; 00076 PAGED_CODE(); 00077 PSTRACE(PS_SECURITY_DEBUG, "Process: %p\n", Process); 00078 00079 /* If we have a parent, then duplicate the Token */ 00080 if (Parent) 00081 { 00082 /* Get the Parent Token */ 00083 ParentToken = PsReferencePrimaryToken(Parent); 00084 00085 /* Duplicate it */ 00086 Status = SeSubProcessToken(ParentToken, 00087 &NewToken, 00088 TRUE, 00089 0);//MmGetSessionId(Process)); 00090 00091 /* Dereference the Parent */ 00092 ObFastDereferenceObject(&Parent->Token, ParentToken); 00093 00094 /* Set the new Token */ 00095 if (NT_SUCCESS(Status)) 00096 { 00097 /* Initailize the fast reference */ 00098 ObInitializeFastReference(&Process->Token, NewToken); 00099 } 00100 } 00101 else 00102 { 00103 /* No parent, assign the Boot Token */ 00104 ObInitializeFastReference(&Process->Token, NULL); 00105 SeAssignPrimaryToken(Process, PspBootAccessToken); 00106 } 00107 00108 /* Return to caller */ 00109 return Status; 00110 } 00111 00112 NTSTATUS 00113 NTAPI 00114 PspWriteTebImpersonationInfo(IN PETHREAD Thread, 00115 IN PETHREAD CurrentThread) 00116 { 00117 PEPROCESS Process; 00118 PTEB Teb; 00119 BOOLEAN Attached = FALSE; 00120 BOOLEAN IsImpersonating; 00121 KAPC_STATE ApcState; 00122 PAGED_CODE(); 00123 PSTRACE(PS_SECURITY_DEBUG, "Thread: %p\n", Thread); 00124 00125 /* Sanity check */ 00126 ASSERT(CurrentThread == PsGetCurrentThread()); 00127 00128 /* Get process and TEB */ 00129 Process = Thread->ThreadsProcess; 00130 Teb = Thread->Tcb.Teb; 00131 if (Teb) 00132 { 00133 /* Check if we're not in the right process */ 00134 if (Thread->Tcb.ApcState.Process != &Process->Pcb) 00135 { 00136 /* Attach to the process */ 00137 KeStackAttachProcess(&Process->Pcb, &ApcState); 00138 Attached = TRUE; 00139 } 00140 00141 /* Check if we're in a different thread or acquire rundown */ 00142 if ((Thread == CurrentThread) || 00143 (ExAcquireRundownProtection(&Thread->RundownProtect))) 00144 { 00145 /* Check if the thread is impersonating */ 00146 IsImpersonating = (BOOLEAN)Thread->ActiveImpersonationInfo; 00147 if (IsImpersonating) 00148 { 00149 /* Set TEB data */ 00150 Teb->ImpersonationLocale = -1; 00151 Teb->IsImpersonating = 1; 00152 } 00153 else 00154 { 00155 /* Set TEB data */ 00156 Teb->ImpersonationLocale = 0; 00157 Teb->IsImpersonating = 0; 00158 } 00159 } 00160 00161 /* Check if we're in a different thread */ 00162 if (Thread != CurrentThread) 00163 { 00164 /* Release protection */ 00165 ExReleaseRundownProtection(&Thread->RundownProtect); 00166 } 00167 00168 /* Detach */ 00169 if (Attached) KeUnstackDetachProcess(&ApcState); 00170 } 00171 00172 /* Return to caller */ 00173 return STATUS_SUCCESS; 00174 } 00175 00176 NTSTATUS 00177 NTAPI 00178 PspAssignPrimaryToken(IN PEPROCESS Process, 00179 IN HANDLE Token, 00180 IN PACCESS_TOKEN AccessToken OPTIONAL) 00181 { 00182 PACCESS_TOKEN NewToken = AccessToken, OldToken; 00183 NTSTATUS Status; 00184 PAGED_CODE(); 00185 PSTRACE(PS_SECURITY_DEBUG, "Process: %p Token: %p\n", Process, Token); 00186 00187 /* Check if we don't have a pointer */ 00188 if (!AccessToken) 00189 { 00190 /* Reference it from the handle */ 00191 Status = ObReferenceObjectByHandle(Token, 00192 TOKEN_ASSIGN_PRIMARY, 00193 SeTokenObjectType, 00194 ExGetPreviousMode(), 00195 &NewToken, 00196 NULL); 00197 if (!NT_SUCCESS(Status)) return Status; 00198 } 00199 00200 /* Exchange tokens */ 00201 Status = SeExchangePrimaryToken(Process, NewToken, &OldToken); 00202 00203 /* Acquire and release the lock */ 00204 PspLockProcessSecurityExclusive(Process); 00205 PspUnlockProcessSecurityExclusive(Process); 00206 00207 /* Dereference Tokens and Return */ 00208 if (NT_SUCCESS(Status)) ObDereferenceObject(OldToken); 00209 if (!AccessToken) ObDereferenceObject(NewToken); 00210 return Status; 00211 } 00212 00213 NTSTATUS 00214 NTAPI 00215 PspSetPrimaryToken(IN PEPROCESS Process, 00216 IN HANDLE TokenHandle OPTIONAL, 00217 IN PACCESS_TOKEN Token OPTIONAL) 00218 { 00219 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00220 BOOLEAN IsChild; 00221 PACCESS_TOKEN NewToken = Token; 00222 NTSTATUS Status, AccessStatus; 00223 BOOLEAN Result, SdAllocated; 00224 PSECURITY_DESCRIPTOR SecurityDescriptor; 00225 SECURITY_SUBJECT_CONTEXT SubjectContext; 00226 PSTRACE(PS_SECURITY_DEBUG, "Process: %p Token: %p\n", Process, Token); 00227 00228 /* Make sure we got a handle */ 00229 if (TokenHandle) 00230 { 00231 /* Reference it */ 00232 Status = ObReferenceObjectByHandle(TokenHandle, 00233 TOKEN_ASSIGN_PRIMARY, 00234 SeTokenObjectType, 00235 PreviousMode, 00236 (PVOID*)&NewToken, 00237 NULL); 00238 if (!NT_SUCCESS(Status)) return Status; 00239 } 00240 00241 /* Check if this is a child */ 00242 Status = SeIsTokenChild(NewToken, &IsChild); 00243 if (!NT_SUCCESS(Status)) 00244 { 00245 /* Failed, dereference */ 00246 if (TokenHandle) ObDereferenceObject(NewToken); 00247 return Status; 00248 } 00249 00250 /* Check if this was an independent token */ 00251 if (!IsChild) 00252 { 00253 /* Make sure we have the privilege to assign a new one */ 00254 if (!SeSinglePrivilegeCheck(SeAssignPrimaryTokenPrivilege, 00255 PreviousMode)) 00256 { 00257 /* Failed, dereference */ 00258 if (TokenHandle) ObDereferenceObject(NewToken); 00259 return STATUS_PRIVILEGE_NOT_HELD; 00260 } 00261 } 00262 00263 /* Assign the token */ 00264 Status = PspAssignPrimaryToken(Process, NULL, NewToken); 00265 if (NT_SUCCESS(Status)) 00266 { 00267 /* 00268 * We need to completely reverify if the process still has access to 00269 * itself under this new token. 00270 */ 00271 Status = ObGetObjectSecurity(Process, 00272 &SecurityDescriptor, 00273 &SdAllocated); 00274 if (NT_SUCCESS(Status)) 00275 { 00276 /* Setup the security context */ 00277 SubjectContext.ProcessAuditId = Process; 00278 SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process); 00279 SubjectContext.ClientToken = NULL; 00280 00281 /* Do the access check */ 00282 Result = SeAccessCheck(SecurityDescriptor, 00283 &SubjectContext, 00284 FALSE, 00285 MAXIMUM_ALLOWED, 00286 0, 00287 NULL, 00288 &PsProcessType->TypeInfo.GenericMapping, 00289 PreviousMode, 00290 &Process->GrantedAccess, 00291 &AccessStatus); 00292 00293 /* Dereference the token and let go the SD */ 00294 ObFastDereferenceObject(&Process->Token, 00295 SubjectContext.PrimaryToken); 00296 ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 00297 00298 /* Remove access if it failed */ 00299 if (!Result) Process->GrantedAccess = 0; 00300 00301 /* Setup granted access */ 00302 Process->GrantedAccess |= (PROCESS_VM_OPERATION | 00303 PROCESS_VM_READ | 00304 PROCESS_VM_WRITE | 00305 PROCESS_QUERY_INFORMATION | 00306 PROCESS_TERMINATE | 00307 PROCESS_CREATE_THREAD | 00308 PROCESS_DUP_HANDLE | 00309 PROCESS_CREATE_PROCESS | 00310 PROCESS_SET_INFORMATION | 00311 STANDARD_RIGHTS_ALL | 00312 PROCESS_SET_QUOTA); 00313 } 00314 } 00315 00316 /* Dereference the token */ 00317 if (TokenHandle) ObDereferenceObject(NewToken); 00318 return Status; 00319 } 00320 00321 /* FUNCTIONS *****************************************************************/ 00322 00323 /* 00324 * @implemented 00325 */ 00326 NTSTATUS 00327 NTAPI 00328 NtOpenProcessToken(IN HANDLE ProcessHandle, 00329 IN ACCESS_MASK DesiredAccess, 00330 OUT PHANDLE TokenHandle) 00331 { 00332 /* Call the newer API */ 00333 return NtOpenProcessTokenEx(ProcessHandle, 00334 DesiredAccess, 00335 0, 00336 TokenHandle); 00337 } 00338 00339 /* 00340 * @implemented 00341 */ 00342 NTSTATUS 00343 NTAPI 00344 NtOpenProcessTokenEx(IN HANDLE ProcessHandle, 00345 IN ACCESS_MASK DesiredAccess, 00346 IN ULONG HandleAttributes, 00347 OUT PHANDLE TokenHandle) 00348 { 00349 PACCESS_TOKEN Token; 00350 HANDLE hToken; 00351 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00352 NTSTATUS Status; 00353 PAGED_CODE(); 00354 PSTRACE(PS_SECURITY_DEBUG, 00355 "Process: %p DesiredAccess: %lx\n", ProcessHandle, DesiredAccess); 00356 00357 /* Check if caller was user-mode */ 00358 if (PreviousMode != KernelMode) 00359 { 00360 /* Enter SEH for probing */ 00361 _SEH2_TRY 00362 { 00363 /* Probe the token handle */ 00364 ProbeForWriteHandle(TokenHandle); 00365 } 00366 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00367 { 00368 /* Return the exception code */ 00369 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00370 } 00371 _SEH2_END; 00372 } 00373 00374 /* Open the process token */ 00375 Status = PsOpenTokenOfProcess(ProcessHandle, &Token); 00376 if (NT_SUCCESS(Status)) 00377 { 00378 /* Reference it by handle and dereference the pointer */ 00379 Status = ObOpenObjectByPointer(Token, 00380 HandleAttributes, 00381 NULL, 00382 DesiredAccess, 00383 SeTokenObjectType, 00384 PreviousMode, 00385 &hToken); 00386 ObDereferenceObject(Token); 00387 00388 /* Make sure we got a handle */ 00389 if (NT_SUCCESS(Status)) 00390 { 00391 /* Enter SEH for write */ 00392 _SEH2_TRY 00393 { 00394 /* Return the handle */ 00395 *TokenHandle = hToken; 00396 } 00397 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00398 { 00399 /* Get exception code */ 00400 Status = _SEH2_GetExceptionCode(); 00401 } 00402 _SEH2_END; 00403 } 00404 } 00405 00406 /* Return status */ 00407 return Status; 00408 } 00409 00410 /* 00411 * @implemented 00412 */ 00413 PACCESS_TOKEN 00414 NTAPI 00415 PsReferencePrimaryToken(PEPROCESS Process) 00416 { 00417 PACCESS_TOKEN Token; 00418 PAGED_CODE(); 00419 PSTRACE(PS_SECURITY_DEBUG, "Process: %p\n", Process); 00420 00421 /* Fast Reference the Token */ 00422 Token = ObFastReferenceObject(&Process->Token); 00423 00424 /* Check if we got the Token or if we got locked */ 00425 if (!Token) 00426 { 00427 /* Lock the Process */ 00428 PspLockProcessSecurityShared(Process); 00429 00430 /* Do a Locked Fast Reference */ 00431 Token = ObFastReferenceObjectLocked(&Process->Token); 00432 00433 /* Unlock the Process */ 00434 PspUnlockProcessSecurityShared(Process); 00435 } 00436 00437 /* Return the Token */ 00438 return Token; 00439 } 00440 00441 /* 00442 * @implemented 00443 */ 00444 NTSTATUS 00445 NTAPI 00446 PsOpenTokenOfProcess(IN HANDLE ProcessHandle, 00447 OUT PACCESS_TOKEN* Token) 00448 { 00449 PEPROCESS Process; 00450 NTSTATUS Status; 00451 PAGED_CODE(); 00452 PSTRACE(PS_SECURITY_DEBUG, "Process: %p\n", ProcessHandle); 00453 00454 /* Get the Token */ 00455 Status = ObReferenceObjectByHandle(ProcessHandle, 00456 PROCESS_QUERY_INFORMATION, 00457 PsProcessType, 00458 ExGetPreviousMode(), 00459 (PVOID*)&Process, 00460 NULL); 00461 if (NT_SUCCESS(Status)) 00462 { 00463 /* Reference the token and dereference the process */ 00464 *Token = PsReferencePrimaryToken(Process); 00465 ObDereferenceObject(Process); 00466 } 00467 00468 /* Return */ 00469 return Status; 00470 } 00471 00472 /* 00473 * @implemented 00474 */ 00475 NTSTATUS 00476 NTAPI 00477 PsAssignImpersonationToken(IN PETHREAD Thread, 00478 IN HANDLE TokenHandle) 00479 { 00480 PACCESS_TOKEN Token; 00481 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; 00482 NTSTATUS Status; 00483 PAGED_CODE(); 00484 PSTRACE(PS_SECURITY_DEBUG, "Thread: %p Token: %p\n", Thread, TokenHandle); 00485 00486 /* Check if we were given a handle */ 00487 if (!TokenHandle) 00488 { 00489 /* Undo impersonation */ 00490 PsRevertThreadToSelf(Thread); 00491 return STATUS_SUCCESS; 00492 } 00493 00494 /* Get the token object */ 00495 Status = ObReferenceObjectByHandle(TokenHandle, 00496 TOKEN_IMPERSONATE, 00497 SeTokenObjectType, 00498 KeGetPreviousMode(), 00499 (PVOID*)&Token, 00500 NULL); 00501 if (!NT_SUCCESS(Status)) return(Status); 00502 00503 /* Make sure it's an impersonation token */ 00504 if (SeTokenType(Token) != TokenImpersonation) 00505 { 00506 /* Fail */ 00507 ObDereferenceObject(Token); 00508 return STATUS_BAD_TOKEN_TYPE; 00509 } 00510 00511 /* Get the impersonation level */ 00512 ImpersonationLevel = SeTokenImpersonationLevel(Token); 00513 00514 /* Call the impersonation API */ 00515 Status = PsImpersonateClient(Thread, 00516 Token, 00517 FALSE, 00518 FALSE, 00519 ImpersonationLevel); 00520 00521 /* Dereference the token and return status */ 00522 ObDereferenceObject(Token); 00523 return Status; 00524 } 00525 00526 /* 00527 * @implemented 00528 */ 00529 VOID 00530 NTAPI 00531 PsRevertToSelf(VOID) 00532 { 00533 /* Call the per-thread API */ 00534 PAGED_CODE(); 00535 PsRevertThreadToSelf(PsGetCurrentThread()); 00536 } 00537 00538 /* 00539 * @implemented 00540 */ 00541 VOID 00542 NTAPI 00543 PsRevertThreadToSelf(IN PETHREAD Thread) 00544 { 00545 PTOKEN Token = NULL; 00546 PAGED_CODE(); 00547 PSTRACE(PS_SECURITY_DEBUG, "Thread: %p\n", Thread); 00548 00549 /* Make sure we had impersonation information */ 00550 if (Thread->ActiveImpersonationInfo) 00551 { 00552 /* Lock the thread security */ 00553 PspLockThreadSecurityExclusive(Thread); 00554 00555 /* Make sure it's still active */ 00556 if (Thread->ActiveImpersonationInfo) 00557 { 00558 /* Disable impersonation */ 00559 PspClearCrossThreadFlag(Thread, CT_ACTIVE_IMPERSONATION_INFO_BIT); 00560 00561 /* Get the token */ 00562 Token = Thread->ImpersonationInfo->Token; 00563 } 00564 00565 /* Release thread security */ 00566 PspUnlockThreadSecurityExclusive(Thread); 00567 00568 /* Check if we had a token */ 00569 if (Token) 00570 { 00571 /* Dereference the impersonation token */ 00572 ObDereferenceObject(Token); 00573 00574 /* Write impersonation info to the TEB */ 00575 PspWriteTebImpersonationInfo(Thread, PsGetCurrentThread()); 00576 } 00577 } 00578 } 00579 00580 /* 00581 * @implemented 00582 */ 00583 NTSTATUS 00584 NTAPI 00585 PsImpersonateClient(IN PETHREAD Thread, 00586 IN PACCESS_TOKEN Token, 00587 IN BOOLEAN CopyOnOpen, 00588 IN BOOLEAN EffectiveOnly, 00589 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel) 00590 { 00591 PPS_IMPERSONATION_INFORMATION Impersonation, OldData; 00592 PTOKEN OldToken = NULL; 00593 PAGED_CODE(); 00594 PSTRACE(PS_SECURITY_DEBUG, "Thread: %p, Token: %p\n", Thread, Token); 00595 00596 /* Check if we don't have a token */ 00597 if (!Token) 00598 { 00599 /* Make sure we're impersonating */ 00600 if (Thread->ActiveImpersonationInfo) 00601 { 00602 /* We seem to be, lock the thread */ 00603 PspLockThreadSecurityExclusive(Thread); 00604 00605 /* Make sure we're still impersonating */ 00606 if (Thread->ActiveImpersonationInfo) 00607 { 00608 /* Disable impersonation */ 00609 PspClearCrossThreadFlag(Thread, 00610 CT_ACTIVE_IMPERSONATION_INFO_BIT); 00611 00612 /* Get the token */ 00613 OldToken = Thread->ImpersonationInfo->Token; 00614 } 00615 00616 /* Unlock the process and write TEB information */ 00617 PspUnlockThreadSecurityExclusive(Thread); 00618 PspWriteTebImpersonationInfo(Thread, PsGetCurrentThread()); 00619 } 00620 } 00621 else 00622 { 00623 /* Check if we have impersonation info */ 00624 Impersonation = Thread->ImpersonationInfo; 00625 if (!Impersonation) 00626 { 00627 /* We need to allocate a new one */ 00628 Impersonation = ExAllocatePoolWithTag(PagedPool, 00629 sizeof(*Impersonation), 00630 TAG_PS_IMPERSONATION); 00631 if (!Impersonation) return STATUS_INSUFFICIENT_RESOURCES; 00632 00633 /* Update the pointer */ 00634 OldData = InterlockedCompareExchangePointer((PVOID*)&Thread-> 00635 ImpersonationInfo, 00636 Impersonation, 00637 NULL); 00638 if (OldData) 00639 { 00640 /* Someone beat us to it, free our copy */ 00641 ExFreePool(Impersonation); 00642 Impersonation = OldData; 00643 } 00644 } 00645 00646 /* Check if this is a job, which we don't support yet */ 00647 if (Thread->ThreadsProcess->Job) ASSERT(FALSE); 00648 00649 /* Lock thread security */ 00650 PspLockThreadSecurityExclusive(Thread); 00651 00652 /* Check if we're impersonating */ 00653 if (Thread->ActiveImpersonationInfo) 00654 { 00655 /* Get the token */ 00656 OldToken = Impersonation->Token; 00657 } 00658 else 00659 { 00660 /* Otherwise, enable impersonation */ 00661 PspSetCrossThreadFlag(Thread, CT_ACTIVE_IMPERSONATION_INFO_BIT); 00662 } 00663 00664 /* Now fill it out */ 00665 Impersonation->ImpersonationLevel = ImpersonationLevel; 00666 Impersonation->CopyOnOpen = CopyOnOpen; 00667 Impersonation->EffectiveOnly = EffectiveOnly; 00668 Impersonation->Token = Token; 00669 ObReferenceObject(Token); 00670 00671 /* Unlock the thread */ 00672 PspUnlockThreadSecurityExclusive(Thread); 00673 00674 /* Write impersonation info to the TEB */ 00675 PspWriteTebImpersonationInfo(Thread, PsGetCurrentThread()); 00676 } 00677 00678 /* Dereference the token and return success */ 00679 if (OldToken) PsDereferenceImpersonationToken(OldToken); 00680 return STATUS_SUCCESS; 00681 } 00682 00683 /* 00684 * @implemented 00685 */ 00686 PACCESS_TOKEN 00687 NTAPI 00688 PsReferenceEffectiveToken(IN PETHREAD Thread, 00689 OUT IN PTOKEN_TYPE TokenType, 00690 OUT PBOOLEAN EffectiveOnly, 00691 OUT PSECURITY_IMPERSONATION_LEVEL Level) 00692 { 00693 PEPROCESS Process; 00694 PACCESS_TOKEN Token = NULL; 00695 PAGED_CODE(); 00696 PSTRACE(PS_SECURITY_DEBUG, 00697 "Thread: %p, TokenType: %p\n", Thread, TokenType); 00698 00699 /* Check if we don't have impersonation info */ 00700 Process = Thread->ThreadsProcess; 00701 if (!Thread->ActiveImpersonationInfo) 00702 { 00703 /* Fast Reference the Token */ 00704 Token = ObFastReferenceObject(&Process->Token); 00705 00706 /* Check if we got the Token or if we got locked */ 00707 if (!Token) 00708 { 00709 /* Lock the Process */ 00710 PspLockProcessSecurityShared(Process); 00711 00712 /* Do a Locked Fast Reference */ 00713 Token = ObFastReferenceObjectLocked(&Process->Token); 00714 00715 /* Unlock the Process */ 00716 PspUnlockProcessSecurityShared(Process); 00717 } 00718 } 00719 else 00720 { 00721 /* Lock the Process */ 00722 PspLockProcessSecurityShared(Process); 00723 00724 /* Make sure impersonation is still active */ 00725 if (Thread->ActiveImpersonationInfo) 00726 { 00727 /* Get the token */ 00728 Token = Thread->ImpersonationInfo->Token; 00729 ObReferenceObject(Token); 00730 00731 /* Return data to caller */ 00732 *TokenType = TokenImpersonation; 00733 *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly; 00734 *Level = Thread->ImpersonationInfo->ImpersonationLevel; 00735 00736 /* Unlock the Process */ 00737 PspUnlockProcessSecurityShared(Process); 00738 return Token; 00739 } 00740 00741 /* Unlock the Process */ 00742 PspUnlockProcessSecurityShared(Process); 00743 } 00744 00745 /* Return the token */ 00746 *TokenType = TokenPrimary; 00747 *EffectiveOnly = FALSE; 00748 return Token; 00749 } 00750 00751 /* 00752 * @implemented 00753 */ 00754 PACCESS_TOKEN 00755 NTAPI 00756 PsReferenceImpersonationToken(IN PETHREAD Thread, 00757 OUT PBOOLEAN CopyOnOpen, 00758 OUT PBOOLEAN EffectiveOnly, 00759 OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel) 00760 { 00761 PTOKEN Token = NULL; 00762 PAGED_CODE(); 00763 PSTRACE(PS_SECURITY_DEBUG, "Thread: %p\n", Thread); 00764 00765 /* If we don't have impersonation info, just quit */ 00766 if (!Thread->ActiveImpersonationInfo) return NULL; 00767 00768 /* Lock the thread */ 00769 PspLockThreadSecurityShared(Thread); 00770 00771 /* Make sure we still have active impersonation */ 00772 if (Thread->ActiveImpersonationInfo) 00773 { 00774 /* Return data from caller */ 00775 ObReferenceObject(Thread->ImpersonationInfo->Token); 00776 *ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel; 00777 *CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen; 00778 *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly; 00779 00780 /* Set the token */ 00781 Token = Thread->ImpersonationInfo->Token; 00782 } 00783 00784 /* Unlock thread and return impersonation token */ 00785 PspUnlockThreadSecurityShared(Thread); 00786 return Token; 00787 } 00788 00789 #undef PsDereferenceImpersonationToken 00790 /* 00791 * @implemented 00792 */ 00793 VOID 00794 NTAPI 00795 PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken) 00796 { 00797 PAGED_CODE(); 00798 00799 /* If we got a token, dereference it */ 00800 if (ImpersonationToken) ObDereferenceObject(ImpersonationToken); 00801 } 00802 00803 #undef PsDereferencePrimaryToken 00804 /* 00805 * @implemented 00806 */ 00807 VOID 00808 NTAPI 00809 PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken) 00810 { 00811 PAGED_CODE(); 00812 00813 /* Dereference the token*/ 00814 ObDereferenceObject(PrimaryToken); 00815 } 00816 00817 /* 00818 * @implemented 00819 */ 00820 BOOLEAN 00821 NTAPI 00822 PsDisableImpersonation(IN PETHREAD Thread, 00823 IN PSE_IMPERSONATION_STATE ImpersonationState) 00824 { 00825 PPS_IMPERSONATION_INFORMATION Impersonation = NULL; 00826 LONG NewValue, OldValue; 00827 PAGED_CODE(); 00828 PSTRACE(PS_SECURITY_DEBUG, 00829 "Thread: %p State: %p\n", Thread, ImpersonationState); 00830 00831 /* Check if we don't have impersonation */ 00832 if (Thread->ActiveImpersonationInfo) 00833 { 00834 /* Lock thread security */ 00835 PspLockThreadSecurityExclusive(Thread); 00836 00837 /* Disable impersonation */ 00838 OldValue = Thread->CrossThreadFlags; 00839 do 00840 { 00841 /* Attempt to change the flag */ 00842 NewValue = 00843 InterlockedCompareExchange((PLONG)&Thread->CrossThreadFlags, 00844 OldValue &~ 00845 CT_ACTIVE_IMPERSONATION_INFO_BIT, 00846 OldValue); 00847 } while (NewValue != OldValue); 00848 00849 /* Make sure nobody disabled it behind our back */ 00850 if (NewValue & CT_ACTIVE_IMPERSONATION_INFO_BIT) 00851 { 00852 /* Copy the old state */ 00853 Impersonation = Thread->ImpersonationInfo; 00854 ImpersonationState->Token = Impersonation->Token; 00855 ImpersonationState->CopyOnOpen = Impersonation->CopyOnOpen; 00856 ImpersonationState->EffectiveOnly = Impersonation->EffectiveOnly; 00857 ImpersonationState->Level = Impersonation->ImpersonationLevel; 00858 } 00859 00860 /* Unlock thread security */ 00861 PspUnlockThreadSecurityExclusive(Thread); 00862 00863 /* If we had impersonation info, return true */ 00864 if (Impersonation) return TRUE; 00865 } 00866 00867 /* Clear everything */ 00868 ImpersonationState->Token = NULL; 00869 ImpersonationState->CopyOnOpen = FALSE; 00870 ImpersonationState->EffectiveOnly = FALSE; 00871 ImpersonationState->Level = SecurityAnonymous; 00872 return FALSE; 00873 } 00874 00875 /* 00876 * @implemented 00877 */ 00878 VOID 00879 NTAPI 00880 PsRestoreImpersonation(IN PETHREAD Thread, 00881 IN PSE_IMPERSONATION_STATE ImpersonationState) 00882 { 00883 PTOKEN Token = NULL; 00884 PPS_IMPERSONATION_INFORMATION Impersonation; 00885 PAGED_CODE(); 00886 PSTRACE(PS_SECURITY_DEBUG, 00887 "Thread: %p State: %p\n", Thread, ImpersonationState); 00888 00889 /* Lock thread security */ 00890 PspLockThreadSecurityExclusive(Thread); 00891 00892 /* Get the impersonation info */ 00893 Impersonation = Thread->ImpersonationInfo; 00894 00895 /* Check if we're impersonating */ 00896 if (Thread->ActiveImpersonationInfo) 00897 { 00898 /* Get the token */ 00899 Token = Impersonation->Token; 00900 } 00901 00902 /* Check if we have an impersonation state */ 00903 if (ImpersonationState) 00904 { 00905 /* Fill out the impersonation info */ 00906 Impersonation->ImpersonationLevel = ImpersonationState->Level; 00907 Impersonation->CopyOnOpen = ImpersonationState->CopyOnOpen; 00908 Impersonation->EffectiveOnly = ImpersonationState->EffectiveOnly; 00909 Impersonation->Token = ImpersonationState->Token; 00910 00911 /* Enable impersonation */ 00912 PspSetCrossThreadFlag(Thread, CT_ACTIVE_IMPERSONATION_INFO_BIT); 00913 } 00914 else 00915 { 00916 /* Disable impersonation */ 00917 PspClearCrossThreadFlag(Thread, CT_ACTIVE_IMPERSONATION_INFO_BIT); 00918 } 00919 00920 /* Unlock the thread */ 00921 PspUnlockThreadSecurityExclusive(Thread); 00922 00923 /* Dereference the token */ 00924 if (Token) ObDereferenceObject(Token); 00925 } 00926 00927 NTSTATUS 00928 NTAPI 00929 NtImpersonateThread(IN HANDLE ThreadHandle, 00930 IN HANDLE ThreadToImpersonateHandle, 00931 IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService) 00932 { 00933 SECURITY_QUALITY_OF_SERVICE SafeServiceQoS; 00934 SECURITY_CLIENT_CONTEXT ClientContext; 00935 PETHREAD Thread; 00936 PETHREAD ThreadToImpersonate; 00937 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00938 NTSTATUS Status; 00939 PAGED_CODE(); 00940 PSTRACE(PS_SECURITY_DEBUG, 00941 "Threads: %p %p\n", ThreadHandle, ThreadToImpersonateHandle); 00942 00943 /* Check if call came from user mode */ 00944 if (PreviousMode != KernelMode) 00945 { 00946 /* Enter SEH for probing */ 00947 _SEH2_TRY 00948 { 00949 /* Probe QoS */ 00950 ProbeForRead(SecurityQualityOfService, 00951 sizeof(SECURITY_QUALITY_OF_SERVICE), 00952 sizeof(ULONG)); 00953 00954 /* Capture it */ 00955 SafeServiceQoS = *SecurityQualityOfService; 00956 SecurityQualityOfService = &SafeServiceQoS; 00957 } 00958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00959 { 00960 /* Return the exception code */ 00961 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00962 } 00963 _SEH2_END; 00964 } 00965 00966 /* Reference the thread */ 00967 Status = ObReferenceObjectByHandle(ThreadHandle, 00968 THREAD_DIRECT_IMPERSONATION, 00969 PsThreadType, 00970 PreviousMode, 00971 (PVOID*)&Thread, 00972 NULL); 00973 if (NT_SUCCESS(Status)) 00974 { 00975 /* Reference the impersonating thead */ 00976 Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle, 00977 THREAD_IMPERSONATE, 00978 PsThreadType, 00979 PreviousMode, 00980 (PVOID*)&ThreadToImpersonate, 00981 NULL); 00982 if (NT_SUCCESS(Status)) 00983 { 00984 /* Create a client security context */ 00985 Status = SeCreateClientSecurity(ThreadToImpersonate, 00986 SecurityQualityOfService, 00987 0, 00988 &ClientContext); 00989 if (NT_SUCCESS(Status)) 00990 { 00991 /* Do the impersonation */ 00992 SeImpersonateClient(&ClientContext, Thread); 00993 if (ClientContext.ClientToken) 00994 { 00995 /* Dereference the client token if we had one */ 00996 ObDereferenceObject(ClientContext.ClientToken); 00997 } 00998 } 00999 01000 /* Dereference the thread to impersonate */ 01001 ObDereferenceObject(ThreadToImpersonate); 01002 } 01003 01004 /* Dereference the main thread */ 01005 ObDereferenceObject(Thread); 01006 } 01007 01008 /* Return status */ 01009 return Status; 01010 } 01011 /* EOF */ Generated on Sun May 27 2012 04:17:42 for ReactOS by
1.7.6.1
|