ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

security.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.