[ros-diffs] [ion] 23152: [AUDIT] security.c is mostly composed of trivial implementations of APIs that transfer one set of data from another, or simply wrap around complex Se* functions which do the actual work. There are one or two slightly more complex APIs (~15-20 lines), but they were written by Eric/Thomas, which are well-known for always writing clean code. [FORMATTING] Re-formatted file properly, ordered functions and annotated them, added proper programmer credits, etc. - Pushlocks need to be acquired in a -critical-, not -guarded- region. - PsDisableImpersonation should return FALSE if it was already disbled. - Don't forget to reference the token in PsReferenceEffectiveToken. - PsImpersonateClient should still return success if it was given no token. - PsImperstonateClient should de-reference the token if there is already active impersonation info.

ion at svn.reactos.org ion at svn.reactos.org
Tue Jul 18 17:13:56 CEST 2006


Author: ion
Date: Tue Jul 18 19:13:55 2006
New Revision: 23152

URL: http://svn.reactos.org/svn/reactos?rev=23152&view=rev
Log:
[AUDIT] security.c is mostly composed of trivial implementations of APIs that transfer one set of data from another, or simply wrap around complex Se* functions which do the actual work. There are one or two slightly more complex APIs (~15-20 lines), but they were written by Eric/Thomas, which are well-known for always writing clean code.
[FORMATTING] Re-formatted file properly, ordered functions and annotated them, added proper programmer credits, etc.
- Pushlocks need to be acquired in a -critical-, not -guarded- region.
- PsDisableImpersonation should return FALSE if it was already disbled.
- Don't forget to reference the token in PsReferenceEffectiveToken.
- PsImpersonateClient should still return success if it was given no token.
- PsImperstonateClient should de-reference the token if there is already active impersonation info.

Modified:
    trunk/reactos/ntoskrnl/KrnlFun.c
    trunk/reactos/ntoskrnl/include/internal/tag.h
    trunk/reactos/ntoskrnl/ps/security.c   (contents, props changed)

Modified: trunk/reactos/ntoskrnl/KrnlFun.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=23152&r1=23151&r2=23152&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/KrnlFun.c (original)
+++ trunk/reactos/ntoskrnl/KrnlFun.c Tue Jul 18 19:13:55 2006
@@ -29,6 +29,7 @@
 //  - Use Process Pushlock Locks.
 //  - Use Safe Referencing in PsGetNextProcess/Thread.
 //  - Use Guarded Mutex instead of Fast Mutex for Active Process Locks.
+//  - Use Security Locks in security.c
 //  - Fix referencing problem.
 //  - Generate process cookie for user-more thread.
 //  - Add security calls where necessary.

Modified: trunk/reactos/ntoskrnl/include/internal/tag.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/tag.h?rev=23152&r1=23151&r2=23152&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/tag.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/tag.h Tue Jul 18 19:13:55 2006
@@ -130,6 +130,7 @@
 
 /* formerly located in ps/cid.c */
 #define TAG_CIDOBJECT TAG('C', 'I', 'D', 'O')
+#define TAG_PS_IMPERSONATION    TAG('P', 's', 'I', 'm')
 
 /* formerly located in ps/job.c */
 #define TAG_EJOB TAG('E', 'J', 'O', 'B') /* EJOB */

Modified: trunk/reactos/ntoskrnl/ps/security.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/security.c?rev=23152&r1=23151&r2=23152&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ps/security.c (original)
+++ trunk/reactos/ntoskrnl/ps/security.c Tue Jul 18 19:13:55 2006
@@ -1,10 +1,11 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/ps/security.c
- * PURPOSE:         Process Manager Security (Tokens, Impersionation)
- *
- * PROGRAMMERS:     David Welch (welch at cwcom.net)
+ * PURPOSE:         Process Manager: Process/Thread Security
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu at reactos.org)
+ *                  Eric Kohl
+ *                  Thomas Weidenmueller (w3seek at reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
@@ -13,15 +14,15 @@
 #define NDEBUG
 #include <internal/debug.h>
 
-/* INTERNAL ******************************************************************/
+/* PRIVATE FUNCTIONS *********************************************************/
 
 /* FIXME: Turn into Macro */
 VOID
-STDCALL
-PspLockProcessSecurityShared(PEPROCESS Process)
-{
-    /* Enter a Guarded Region */
-    KeEnterGuardedRegion();
+NTAPI
+PspLockProcessSecurityShared(IN PEPROCESS Process)
+{
+    /* Enter a Critical Region */
+    KeEnterCriticalRegion();
 
     /* Lock the Process */
     //ExAcquirePushLockShared(&Process->ProcessLock);
@@ -29,14 +30,14 @@
 
 /* FIXME: Turn into Macro */
 VOID
-STDCALL
-PspUnlockProcessSecurityShared(PEPROCESS Process)
+NTAPI
+PspUnlockProcessSecurityShared(IN PEPROCESS Process)
 {
     /* Unlock the Process */
     //ExReleasePushLockShared(&Process->ProcessLock);
 
-    /* Leave Guarded Region */
-    KeLeaveGuardedRegion();
+    /* Leave Critical Region */
+    KeLeaveCriticalRegion();
 }
 
 VOID
@@ -73,153 +74,10 @@
     }
 }
 
-/* FUNCTIONS *****************************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS
-STDCALL
-NtOpenProcessToken(IN HANDLE ProcessHandle,
-                   IN ACCESS_MASK DesiredAccess,
-                   OUT PHANDLE TokenHandle)
-{
-    return NtOpenProcessTokenEx(ProcessHandle,
-                                DesiredAccess,
-                                0,
-                                TokenHandle);
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-STDCALL
-NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
-                     IN ACCESS_MASK DesiredAccess,
-                     IN ULONG HandleAttributes,
-                     OUT PHANDLE TokenHandle)
-{
-   PACCESS_TOKEN Token;
-   HANDLE hToken;
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-
-   PAGED_CODE();
-
-   PreviousMode = ExGetPreviousMode();
-
-   if(PreviousMode != KernelMode)
-   {
-     _SEH_TRY
-     {
-       ProbeForWriteHandle(TokenHandle);
-     }
-     _SEH_HANDLE
-     {
-       Status = _SEH_GetExceptionCode();
-     }
-     _SEH_END;
-
-     if(!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-   }
-
-   Status = PsOpenTokenOfProcess(ProcessHandle,
-				 &Token);
-   if(NT_SUCCESS(Status))
-   {
-       Status = ObOpenObjectByPointer(Token,
-                                      0,
-                                      NULL,
-                                      DesiredAccess,
-                                      SepTokenObjectType,
-                                      PreviousMode,
-                                      &hToken);
-     ObDereferenceObject(Token);
-
-     if(NT_SUCCESS(Status))
-     {
-       _SEH_TRY
-       {
-         *TokenHandle = hToken;
-       }
-       _SEH_HANDLE
-       {
-         Status = _SEH_GetExceptionCode();
-       }
-       _SEH_END;
-     }
-   }
-
-   return Status;
-}
-
-/*
- * @implemented
- */
-PACCESS_TOKEN
-STDCALL
-PsReferencePrimaryToken(PEPROCESS Process)
-{
-    PACCESS_TOKEN Token;
-
-    /* Fast Reference the Token */
-    Token = ObFastReferenceObject(&Process->Token);
-
-    /* Check if we got the Token or if we got locked */
-    if (!Token)
-    {
-        /* Lock the Process */
-        PspLockProcessSecurityShared(Process);
-
-        /* Do a Locked Fast Reference */
-        Token = ObFastReferenceObjectLocked(&Process->Token);
-
-        /* Unlock the Process */
-        PspUnlockProcessSecurityShared(Process);
-    }
-
-    /* Return the Token */
-    return Token;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-STDCALL
-PsOpenTokenOfProcess(HANDLE ProcessHandle,
-                     PACCESS_TOKEN* Token)
-{
-    PEPROCESS Process;
-    NTSTATUS Status;
-
-    /* Get the Token */
-    Status = ObReferenceObjectByHandle(ProcessHandle,
-                                       PROCESS_QUERY_INFORMATION,
-                                       PsProcessType,
-                                       ExGetPreviousMode(),
-                                       (PVOID*)&Process,
-                                       NULL);
-
-    /* Reference it */
-    if(NT_SUCCESS(Status)) {
-
-        *Token = PsReferencePrimaryToken(Process);
-        ObDereferenceObject(Process);
-    }
-
-    /* Return */
-    return Status;
-}
-
-NTSTATUS
-STDCALL
-PspInitializeProcessSecurity(PEPROCESS Process,
-                             PEPROCESS Parent OPTIONAL)
+NTSTATUS
+NTAPI
+PspInitializeProcessSecurity(IN PEPROCESS Process,
+                             IN PEPROCESS Parent OPTIONAL)
 {
     NTSTATUS Status = STATUS_SUCCESS;
     PTOKEN NewToken, ParentToken;
@@ -258,86 +116,233 @@
     return Status;
 }
 
-
-NTSTATUS
-STDCALL
-PspAssignPrimaryToken(PEPROCESS Process,
-                      HANDLE TokenHandle)
-{
-    PACCESS_TOKEN Token;
-    PACCESS_TOKEN OldToken;
+NTSTATUS
+NTAPI
+PspAssignPrimaryToken(IN PEPROCESS Process,
+                      IN HANDLE TokenHandle)
+{
+    PACCESS_TOKEN Token, OldToken;
     NTSTATUS Status;
 
     /* Reference the Token */
     Status = ObReferenceObjectByHandle(TokenHandle,
-                                       0,
+                                       TOKEN_ASSIGN_PRIMARY,
                                        SepTokenObjectType,
                                        KeGetPreviousMode(),
                                        (PVOID*)&Token,
                                        NULL);
-    if (!NT_SUCCESS(Status)) {
-
-        return(Status);
-    }
+    if (!NT_SUCCESS(Status)) return Status;
 
     /* Exchange them */
     Status = SeExchangePrimaryToken(Process, Token, &OldToken);
 
     /* Derefernece Tokens and Return */
     ObDereferenceObject(Token);
-    return(Status);
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-STDCALL
-PsAssignImpersonationToken(PETHREAD Thread,
-                           HANDLE TokenHandle)
+    return Status;
+}
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtOpenProcessToken(IN HANDLE ProcessHandle,
+                   IN ACCESS_MASK DesiredAccess,
+                   OUT PHANDLE TokenHandle)
+{
+    /* Call the newer API */
+    return NtOpenProcessTokenEx(ProcessHandle,
+                                DesiredAccess,
+                                0,
+                                TokenHandle);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
+                     IN ACCESS_MASK DesiredAccess,
+                     IN ULONG HandleAttributes,
+                     OUT PHANDLE TokenHandle)
+{
+    PACCESS_TOKEN Token;
+    HANDLE hToken;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    PAGED_CODE();
+
+    /* Check if caller was user-mode */
+    if (PreviousMode != KernelMode)
+    {
+        /* Enter SEH for probing */
+        _SEH_TRY
+        {
+            /* Probe the token handle */
+            ProbeForWriteHandle(TokenHandle);
+        }
+        _SEH_HANDLE
+        {
+            /* Get the exception code */
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        /* Fail on exception */
+        if (!NT_SUCCESS(Status)) return Status;
+    }
+
+    /* Open the process token */
+    Status = PsOpenTokenOfProcess(ProcessHandle, &Token);
+    if(NT_SUCCESS(Status))
+    {
+        /* Reference it by handle and dereference the pointer */
+        Status = ObOpenObjectByPointer(Token,
+                                       0,
+                                       NULL,
+                                       DesiredAccess,
+                                       SepTokenObjectType,
+                                       PreviousMode,
+                                       &hToken);
+        ObDereferenceObject(Token);
+
+        /* Make sure we got a handle */
+        if(NT_SUCCESS(Status))
+        {
+            /* Enter SEH for write */
+            _SEH_TRY
+            {
+                /* Return the handle */
+                *TokenHandle = hToken;
+            }
+            _SEH_HANDLE
+            {
+                /* Get exception code */
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
+        }
+    }
+
+    /* Return status */
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+PACCESS_TOKEN
+NTAPI
+PsReferencePrimaryToken(PEPROCESS Process)
+{
+    PACCESS_TOKEN Token;
+
+    /* Fast Reference the Token */
+    Token = ObFastReferenceObject(&Process->Token);
+
+    /* Check if we got the Token or if we got locked */
+    if (!Token)
+    {
+        /* Lock the Process */
+        PspLockProcessSecurityShared(Process);
+
+        /* Do a Locked Fast Reference */
+        Token = ObFastReferenceObjectLocked(&Process->Token);
+
+        /* Unlock the Process */
+        PspUnlockProcessSecurityShared(Process);
+    }
+
+    /* Return the Token */
+    return Token;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+PsOpenTokenOfProcess(IN HANDLE ProcessHandle,
+                     OUT PACCESS_TOKEN* Token)
+{
+    PEPROCESS Process;
+    NTSTATUS Status;
+
+    /* Get the Token */
+    Status = ObReferenceObjectByHandle(ProcessHandle,
+                                       PROCESS_QUERY_INFORMATION,
+                                       PsProcessType,
+                                       ExGetPreviousMode(),
+                                       (PVOID*)&Process,
+                                       NULL);
+    if(NT_SUCCESS(Status))
+    {
+        /* Reference the token and dereference the process */
+        *Token = PsReferencePrimaryToken(Process);
+        ObDereferenceObject(Process);
+    }
+
+    /* Return */
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+PsAssignImpersonationToken(IN PETHREAD Thread,
+                           IN HANDLE TokenHandle)
 {
     PACCESS_TOKEN Token;
     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
     NTSTATUS Status;
 
-    if (TokenHandle != NULL) {
-
+    /* Check if we were given a handle */
+    if (TokenHandle)
+    {
+        /* Get the token object */
         Status = ObReferenceObjectByHandle(TokenHandle,
                                            TOKEN_IMPERSONATE,
                                            SepTokenObjectType,
                                            KeGetPreviousMode(),
                                            (PVOID*)&Token,
                                            NULL);
-
-        if (!NT_SUCCESS(Status)) {
-
-            return(Status);
-        }
-
+        if (!NT_SUCCESS(Status)) return(Status);
+
+        /* Get the impersionation level */
         ImpersonationLevel = SeTokenImpersonationLevel(Token);
-
-    } else {
-
+    }
+    else
+    {
+        /* Otherwise, clear values */
         Token = NULL;
         ImpersonationLevel = 0;
     }
 
+    /* Call the impersonation API */
     Status = PsImpersonateClient(Thread,
                                  Token,
                                  FALSE,
                                  FALSE,
                                  ImpersonationLevel);
 
-    if (Token != NULL) ObDereferenceObject(Token);
+    /* Dereference the token and return status */
+    if (Token) ObDereferenceObject(Token);
     return Status;
 }
 
 /*
  * @implemented
  */
-VOID STDCALL
-PsRevertToSelf (VOID)
-{
+VOID
+NTAPI
+PsRevertToSelf(VOID)
+{
+    /* Call the per-thread API */
     PsRevertThreadToSelf(PsGetCurrentThread());
 }
 
@@ -345,11 +350,13 @@
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 PsRevertThreadToSelf(IN PETHREAD Thread)
 {
-    if (Thread->ActiveImpersonationInfo == TRUE) {
-
+    /* Make sure we had impersonation information */
+    if (Thread->ActiveImpersonationInfo)
+    {
+        /* Dereference the impersonation token and set it as false */
         ObDereferenceObject (Thread->ImpersonationInfo->Token);
         Thread->ActiveImpersonationInfo = FALSE;
     }
@@ -359,59 +366,85 @@
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 PsImpersonateClient(IN PETHREAD Thread,
                     IN PACCESS_TOKEN Token,
                     IN BOOLEAN CopyOnOpen,
                     IN BOOLEAN EffectiveOnly,
                     IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
 {
-
-    if (Token == NULL) {
-
-        if (Thread->ActiveImpersonationInfo == TRUE) {
-
+    PPS_IMPERSONATION_INFORMATION Impersonation;
+
+    /* Check if we don't have a token */
+    if (!Token)
+    {
+        /* Make sure we're impersonating */
+        if (Thread->ActiveImpersonationInfo)
+        {
+            /* Disable impersonation and check for token */
             Thread->ActiveImpersonationInfo = FALSE;
-
-            if (Thread->ImpersonationInfo->Token != NULL) {
-
-                ObDereferenceObject (Thread->ImpersonationInfo->Token);
+            if (Thread->ImpersonationInfo->Token)
+            {
+                /* Dereference it */
+                ObDereferenceObject(Thread->ImpersonationInfo->Token);
             }
         }
 
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    if (Thread->ImpersonationInfo == NULL) {
-
-        Thread->ImpersonationInfo = ExAllocatePool(NonPagedPool,
-                                                   sizeof(PS_IMPERSONATION_INFORMATION));
-    }
-
-    Thread->ImpersonationInfo->ImpersonationLevel = ImpersonationLevel;
-    Thread->ImpersonationInfo->CopyOnOpen = CopyOnOpen;
-    Thread->ImpersonationInfo->EffectiveOnly = EffectiveOnly;
-    Thread->ImpersonationInfo->Token = Token;
-
-    ObReferenceObject(Token);
-
+        /* Return success */
+        return STATUS_SUCCESS;
+    }
+
+    /* Check if we have active impersonation */
+    if (Thread->ActiveImpersonationInfo)
+    {
+        /* Reuse the block and reference the token */
+        Impersonation = Thread->ImpersonationInfo;
+        if (Impersonation->Token) ObDereferenceObject(Impersonation->Token);
+    }
+    else if (Thread->ImpersonationInfo)
+    {
+        /* It's not active, but we can still reuse the block */
+        Impersonation = Thread->ImpersonationInfo;
+    }
+    else
+    {
+        /* We need to allocate a new one */
+        Impersonation = ExAllocatePoolWithTag(PagedPool,
+                                              sizeof(*Impersonation),
+                                              TAG_PS_IMPERSONATION);
+        if (!Impersonation) return STATUS_INSUFFICIENT_RESOURCES;
+
+        /* Update the pointer */
+        Thread->ImpersonationInfo = Impersonation;
+    }
+
+    /* Now fill it out */
+    Impersonation->ImpersonationLevel = ImpersonationLevel;
+    Impersonation->CopyOnOpen = CopyOnOpen;
+    Impersonation->EffectiveOnly = EffectiveOnly;
+    Impersonation->Token = Token;
     Thread->ActiveImpersonationInfo = TRUE;
 
+    /* Reference the token and return success */
+    ObReferenceObject(Impersonation->Token);
     return STATUS_SUCCESS;
 }
 
-
+/*
+ * @implemented
+ */
 PACCESS_TOKEN
-STDCALL
-PsReferenceEffectiveToken(PETHREAD Thread,
-                          PTOKEN_TYPE TokenType,
-                          PBOOLEAN EffectiveOnly,
-                          PSECURITY_IMPERSONATION_LEVEL Level)
+NTAPI
+PsReferenceEffectiveToken(IN PETHREAD Thread,
+                          OUT IN PTOKEN_TYPE TokenType,
+                          OUT PBOOLEAN EffectiveOnly,
+                          OUT PSECURITY_IMPERSONATION_LEVEL Level)
 {
     PEPROCESS Process;
     PACCESS_TOKEN Token;
 
-    if (Thread->ActiveImpersonationInfo == FALSE)
+    /* Check if we don't have impersonation info */
+    if (!Thread->ActiveImpersonationInfo)
     {
         Process = Thread->ThreadsProcess;
         *TokenType = TokenPrimary;
@@ -435,146 +468,64 @@
     }
     else
     {
+        /* Get the token */
         Token = Thread->ImpersonationInfo->Token;
+        ObReferenceObject(Token);
+
+        /* Return data to caller */
         *TokenType = TokenImpersonation;
         *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
         *Level = Thread->ImpersonationInfo->ImpersonationLevel;
     }
 
+    /* Return the token */
     return Token;
 }
 
-NTSTATUS
-STDCALL
-NtImpersonateThread(IN HANDLE ThreadHandle,
-                    IN HANDLE ThreadToImpersonateHandle,
-                    IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService)
-{
-  SECURITY_QUALITY_OF_SERVICE SafeServiceQoS;
-  SECURITY_CLIENT_CONTEXT ClientContext;
-  PETHREAD Thread;
-  PETHREAD ThreadToImpersonate;
-  KPROCESSOR_MODE PreviousMode;
-  NTSTATUS Status = STATUS_SUCCESS;
-
-  PAGED_CODE();
-
-  PreviousMode = ExGetPreviousMode();
-
-  if(PreviousMode != KernelMode)
-  {
-    _SEH_TRY
-    {
-      ProbeForRead(SecurityQualityOfService,
-                   sizeof(SECURITY_QUALITY_OF_SERVICE),
-                   sizeof(ULONG));
-      SafeServiceQoS = *SecurityQualityOfService;
-      SecurityQualityOfService = &SafeServiceQoS;
-    }
-    _SEH_HANDLE
-    {
-      Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
-
-    if(!NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-  }
-
-  Status = ObReferenceObjectByHandle(ThreadHandle,
-				     THREAD_IMPERSONATE,
-				     PsThreadType,
-				     PreviousMode,
-				     (PVOID*)&Thread,
-				     NULL);
-  if(NT_SUCCESS(Status))
-  {
-    Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle,
-				       THREAD_DIRECT_IMPERSONATION,
-				       PsThreadType,
-				       PreviousMode,
-				       (PVOID*)&ThreadToImpersonate,
-				       NULL);
-    if(NT_SUCCESS(Status))
-    {
-      Status = SeCreateClientSecurity(ThreadToImpersonate,
-				      SecurityQualityOfService,
-				      0,
-				     &ClientContext);
-      if(NT_SUCCESS(Status))
-      {
-        SeImpersonateClient(&ClientContext,
-		            Thread);
-        if(ClientContext.ClientToken != NULL)
-        {
-          ObDereferenceObject (ClientContext.ClientToken);
-        }
-      }
-
-      ObDereferenceObject(ThreadToImpersonate);
-    }
-    ObDereferenceObject(Thread);
-  }
-
-  return Status;
-}
-
 /*
  * @implemented
  */
 PACCESS_TOKEN
-STDCALL
+NTAPI
 PsReferenceImpersonationToken(IN PETHREAD Thread,
                               OUT PBOOLEAN CopyOnOpen,
                               OUT PBOOLEAN EffectiveOnly,
                               OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
 {
-
-    if (Thread->ActiveImpersonationInfo == FALSE) {
-
-        return NULL;
-    }
-
+    /* If we don't have impersonation info, just quit */
+    if (!Thread->ActiveImpersonationInfo) return NULL;
+
+    /* Return data from caller */
     *ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel;
     *CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
     *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
 
-    ObReferenceObjectByPointer(Thread->ImpersonationInfo->Token,
-                               TOKEN_ALL_ACCESS,
-                               SepTokenObjectType,
-                               KernelMode);
-
+    /* Reference the token and return it */
+    ObReferenceObject(Thread->ImpersonationInfo->Token);
     return Thread->ImpersonationInfo->Token;
 }
 
-#ifdef PsDereferencePrimaryToken
 #undef PsDereferenceImpersonationToken
-#endif
-/*
- * @implemented
- */
-VOID
-STDCALL
+/*
+ * @implemented
+ */
+VOID
+NTAPI
 PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken)
 {
-    if (ImpersonationToken) {
-
-        ObDereferenceObject(ImpersonationToken);
-    }
-}
-
-#ifdef PsDereferencePrimaryToken
+    /* If we got a token, dereference it */
+    if (ImpersonationToken) ObDereferenceObject(ImpersonationToken);
+}
+
 #undef PsDereferencePrimaryToken
-#endif
-/*
- * @implemented
- */
-VOID
-STDCALL
+/*
+ * @implemented
+ */
+VOID
+NTAPI
 PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
 {
+    /* Dereference the token*/
     ObDereferenceObject(PrimaryToken);
 }
 
@@ -582,30 +533,32 @@
  * @implemented
  */
 BOOLEAN
-STDCALL
+NTAPI
 PsDisableImpersonation(IN PETHREAD Thread,
                        IN PSE_IMPERSONATION_STATE ImpersonationState)
 {
-    if (Thread->ActiveImpersonationInfo == FALSE) {
+    PPS_IMPERSONATION_INFORMATION Impersonation;
+
+    /* Check if we don't have impersonation */
+    if (!Thread->ActiveImpersonationInfo)
+    {
+        /* Clear everything */
         ImpersonationState->Token = NULL;
         ImpersonationState->CopyOnOpen = FALSE;
         ImpersonationState->EffectiveOnly = FALSE;
-        ImpersonationState->Level = 0;
-        return TRUE;
-    }
-
-/* FIXME */
-/*   ExfAcquirePushLockExclusive(&Thread->ThreadLock); */
-
+        ImpersonationState->Level = SecurityAnonymous;
+        return FALSE;
+    }
+
+    /* Copy the old state */
+    Impersonation = Thread->ImpersonationInfo;
+    ImpersonationState->Token = Impersonation->Token;
+    ImpersonationState->CopyOnOpen = Impersonation->CopyOnOpen;
+    ImpersonationState->EffectiveOnly = Impersonation->EffectiveOnly;
+    ImpersonationState->Level = Impersonation->ImpersonationLevel;
+
+    /* Disable impersonation and return true */
     Thread->ActiveImpersonationInfo = FALSE;
-    ImpersonationState->Token = Thread->ImpersonationInfo->Token;
-    ImpersonationState->CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
-    ImpersonationState->EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
-    ImpersonationState->Level = Thread->ImpersonationInfo->ImpersonationLevel;
-
-/* FIXME */
-/*   ExfReleasePushLock(&Thread->ThreadLock); */
-
     return TRUE;
 }
 
@@ -613,18 +566,104 @@
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 PsRestoreImpersonation(IN PETHREAD Thread,
                        IN PSE_IMPERSONATION_STATE ImpersonationState)
 {
-
+    /* Call the impersonation API */
     PsImpersonateClient(Thread,
                         ImpersonationState->Token,
                         ImpersonationState->CopyOnOpen,
                         ImpersonationState->EffectiveOnly,
                         ImpersonationState->Level);
 
-    ObfDereferenceObject(ImpersonationState->Token);
-}
-
+    /* Dereference the token */
+    ObDereferenceObject(ImpersonationState->Token);
+}
+
+NTSTATUS
+NTAPI
+NtImpersonateThread(IN HANDLE ThreadHandle,
+                    IN HANDLE ThreadToImpersonateHandle,
+                    IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService)
+{
+    SECURITY_QUALITY_OF_SERVICE SafeServiceQoS;
+    SECURITY_CLIENT_CONTEXT ClientContext;
+    PETHREAD Thread;
+    PETHREAD ThreadToImpersonate;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    PAGED_CODE();
+
+    /* Check if call came from user mode */
+    if (PreviousMode != KernelMode)
+    {
+        /* Enter SEH for probing */
+        _SEH_TRY
+        {
+            /* Probe QoS */
+            ProbeForRead(SecurityQualityOfService,
+                         sizeof(SECURITY_QUALITY_OF_SERVICE),
+                         sizeof(ULONG));
+
+            /* Capture it */
+            SafeServiceQoS = *SecurityQualityOfService;
+            SecurityQualityOfService = &SafeServiceQoS;
+        }
+        _SEH_HANDLE
+        {
+            /* Get exception status */
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        /* Fail on exception */
+        if (!NT_SUCCESS(Status)) return Status;
+    }
+
+    /* Reference the thread */
+    Status = ObReferenceObjectByHandle(ThreadHandle,
+                                       THREAD_IMPERSONATE,
+                                       PsThreadType,
+                                       PreviousMode,
+                                       (PVOID*)&Thread,
+                                       NULL);
+    if(NT_SUCCESS(Status))
+    {
+        /* Reference the impersonating thead */
+        Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle,
+                                           THREAD_DIRECT_IMPERSONATION,
+                                           PsThreadType,
+                                           PreviousMode,
+                                           (PVOID*)&ThreadToImpersonate,
+                                           NULL);
+        if(NT_SUCCESS(Status))
+        {
+            /* Create a client security context */
+            Status = SeCreateClientSecurity(ThreadToImpersonate,
+                                            SecurityQualityOfService,
+                                            0,
+                                            &ClientContext);
+            if(NT_SUCCESS(Status))
+            {
+                /* Do the impersonation */
+                SeImpersonateClient(&ClientContext, Thread);
+                if(ClientContext.ClientToken)
+                {
+                    /* Dereference the client token if we had one */
+                    ObDereferenceObject(ClientContext.ClientToken);
+                }
+            }
+
+            /* Dereference the thread to impersonate */
+            ObDereferenceObject(ThreadToImpersonate);
+        }
+
+        /* Dereference the main thread */
+        ObDereferenceObject(Thread);
+    }
+
+    /* Return status */
+    return Status;
+}
 /* EOF */

Propchange: trunk/reactos/ntoskrnl/ps/security.c
------------------------------------------------------------------------------
--- svn:needs-lock (original)
+++ svn:needs-lock (removed)
@@ -1,1 +1,0 @@
-*




More information about the Ros-diffs mailing list