[NTOS:SE]
[reactos.git] / reactos / ntoskrnl / se / token.c
index f476cd6..2eeb1ff 100644 (file)
@@ -123,7 +123,7 @@ SepUpdateSinglePrivilegeFlagToken(
     _In_ ULONG Index)
 {
     ULONG TokenFlag;
-    NT_ASSERT(Index < Token->PrivilegeCount);
+    ASSERT(Index < Token->PrivilegeCount);
 
     /* The high part of all values we are interested in is 0 */
     if (Token->Privileges[Index].Luid.HighPart != 0)
@@ -189,7 +189,7 @@ SepRemovePrivilegeToken(
     _In_ ULONG Index)
 {
     ULONG MoveCount;
-    NT_ASSERT(Index < Token->PrivilegeCount);
+    ASSERT(Index < Token->PrivilegeCount);
 
     /* Calculate the number of trailing privileges */
     MoveCount = Token->PrivilegeCount - Index - 1;
@@ -243,19 +243,28 @@ SeExchangePrimaryToken(PEPROCESS Process,
         if (OldToken == NewToken)
         {
             /* So it's a nop. */
-            PsDereferencePrimaryToken(OldToken);
+            *OldTokenP = OldToken;
             return STATUS_SUCCESS;
         }
 
         Status = SepCompareTokens(OldToken, NewToken, &IsEqual);
         if (!NT_SUCCESS(Status))
         {
+            *OldTokenP = NULL;
             PsDereferencePrimaryToken(OldToken);
             return Status;
         }
 
-        PsDereferencePrimaryToken(OldToken);
-        return IsEqual ? STATUS_SUCCESS : STATUS_TOKEN_ALREADY_IN_USE;
+        if (!IsEqual)
+        {
+            *OldTokenP = NULL;
+            PsDereferencePrimaryToken(OldToken);
+            return STATUS_TOKEN_ALREADY_IN_USE;
+        }
+        /* Silently return STATUS_SUCCESS but do not set the new token,
+         * as it's already in use elsewhere. */
+        *OldTokenP = OldToken;
+        return STATUS_SUCCESS;
     }
 
     /* Mark new token in use */
@@ -384,25 +393,14 @@ SepDuplicateToken(PTOKEN Token,
     /* Zero out the buffer */
     RtlZeroMemory(AccessToken, sizeof(TOKEN));
 
-    Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(AccessToken);
-        return Status;
-    }
-
-    Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(AccessToken);
-        return Status;
-    }
+    ExAllocateLocallyUniqueId(&AccessToken->TokenId);
 
     AccessToken->TokenLock = &SepTokenLock;
 
     AccessToken->TokenType  = TokenType;
     AccessToken->ImpersonationLevel = Level;
     RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
+    RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
 
     AccessToken->TokenSource.SourceIdentifier.LowPart = Token->TokenSource.SourceIdentifier.LowPart;
     AccessToken->TokenSource.SourceIdentifier.HighPart = Token->TokenSource.SourceIdentifier.HighPart;
@@ -562,13 +560,13 @@ SeIsTokenChild(IN PTOKEN Token,
     ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
 
     /* Get the ID */
-    ProcessLuid = ProcessToken->TokenId;
+    ProcessLuid = ProcessToken->AuthenticationId;
 
     /* Dereference the token */
     ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken);
 
     /* Get our LUID */
-    CallerLuid = Token->TokenId;
+    CallerLuid = Token->AuthenticationId;
 
     /* Compare the LUIDs */
     if (RtlEqualLuid(&CallerLuid, &ProcessLuid)) *IsChild = TRUE;
@@ -719,13 +717,8 @@ SepCreateToken(OUT PHANDLE TokenHandle,
         }
     }
 
-    Status = ZwAllocateLocallyUniqueId(&TokenId);
-    if (!NT_SUCCESS(Status))
-        return Status;
-
-    Status = ZwAllocateLocallyUniqueId(&ModifiedId);
-    if (!NT_SUCCESS(Status))
-        return Status;
+    ExAllocateLocallyUniqueId(&TokenId);
+    ExAllocateLocallyUniqueId(&ModifiedId);
 
     Status = ObCreateObject(PreviousMode,
                             SeTokenObjectType,
@@ -1073,8 +1066,47 @@ SeQueryInformationToken(IN PACCESS_TOKEN Token,
                         IN TOKEN_INFORMATION_CLASS TokenInformationClass,
                         OUT PVOID *TokenInformation)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PSECURITY_IMPERSONATION_LEVEL SeImpersonationLvl;
+    PAGED_CODE();
+
+    if (TokenInformationClass >= MaxTokenInfoClass)
+    {
+        DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
+        return STATUS_INVALID_INFO_CLASS;
+    }
+    
+    switch (TokenInformationClass)
+    {
+        case TokenImpersonationLevel:
+            /* It is mandatory to have an impersonation token */
+            if (((PTOKEN)Token)->TokenType != TokenImpersonation)
+            {
+                Status = STATUS_INVALID_INFO_CLASS;
+                break;
+            }
+
+            /* Allocate the output buffer */
+            SeImpersonationLvl = ExAllocatePoolWithTag(PagedPool, sizeof(SECURITY_IMPERSONATION_LEVEL), TAG_SE);
+            if (SeImpersonationLvl == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                break;
+            }
+
+            /* Set impersonation level and return the structure */
+            *SeImpersonationLvl = ((PTOKEN)Token)->ImpersonationLevel;
+            *TokenInformation = SeImpersonationLvl;
+            Status = STATUS_SUCCESS;
+            break;
+
+        default:
+            UNIMPLEMENTED;
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+    }
+
+    return Status;
 }
 
 /*
@@ -1900,8 +1932,20 @@ NtSetInformationToken(IN HANDLE TokenHandle,
                                 ExFreePoolWithTag(Token->DefaultDacl, TAG_TOKEN_ACL);
                             }
 
-                            /* Set the new dacl */
-                            Token->DefaultDacl = CapturedAcl;
+                            Token->DefaultDacl = ExAllocatePoolWithTag(PagedPool,
+                                                                       CapturedAcl->AclSize,
+                                                                       TAG_TOKEN_ACL);
+                            if (!Token->DefaultDacl)
+                            {
+                                ExFreePoolWithTag(CapturedAcl, TAG_ACL);
+                                Status = STATUS_NO_MEMORY;
+                            }
+                            else
+                            {
+                                /* Set the new dacl */
+                                RtlCopyMemory(Token->DefaultDacl, CapturedAcl, CapturedAcl->AclSize);
+                                ExFreePoolWithTag(CapturedAcl, TAG_ACL);
+                            }
                         }
                     }
                     else
@@ -2808,6 +2852,10 @@ NtCreateToken(
                                NonPagedPool,
                                FALSE,
                                &CapturedDefaultDacl);
+        if (!NT_SUCCESS(Status))
+        {
+            goto Cleanup;
+        }
     }
 
     /* Call the internal function */
@@ -2898,10 +2946,12 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
         _SEH2_END;
     }
 
+    /* Validate object attributes */
+    HandleAttributes = ObpValidateAttributes(HandleAttributes, PreviousMode);
+
     /*
      * At first open the thread token for information access and verify
-     * that the token associated with thread is valid.
-     */
+     * that the token associated with thread is valid.     */
 
     Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_QUERY_INFORMATION,
                                        PsThreadType, PreviousMode, (PVOID*)&Thread,
@@ -3000,6 +3050,8 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
 
     if (CopyOnOpen && NewThread) ObDereferenceObject(NewThread);
 
+    ObDereferenceObject(Thread);
+
     if (NT_SUCCESS(Status))
     {
         _SEH2_TRY