[NTOSKRNL]
authorEric Kohl <eric.kohl@reactos.org>
Sun, 30 May 2010 19:46:02 +0000 (19:46 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 30 May 2010 19:46:02 +0000 (19:46 +0000)
Make NtDuplicateToken fail if the caller tries to create a new impersonation token with a raised impersonation level. This fixes a winetest.

svn path=/trunk/; revision=47456

reactos/ntoskrnl/se/token.c

index 30f7fc8..04fe7c2 100644 (file)
@@ -1844,39 +1844,61 @@ NtDuplicateToken(IN HANDLE ExistingTokenHandle,
                                        PreviousMode,
                                        (PVOID*)&Token,
                                        NULL);
-    if (NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
-        Status = SepDuplicateToken(Token,
-                                   ObjectAttributes,
-                                   EffectiveOnly,
-                                   TokenType,
-                                   (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
-                                   PreviousMode,
-                                   &NewToken);
+        SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
+                                           PreviousMode,
+                                           FALSE);
+        return Status;
+    }
 
-        ObDereferenceObject(Token);
+    /*
+     * Fail, if the original token is an impersonation token and the caller
+     * tries to raise the impersonation level of the new token above the
+     * impersonation level of the original token.
+     */
+    if (Token->TokenType == TokenImpersonation)
+    {
+        if (QoSPresent &&
+            CapturedSecurityQualityOfService->ImpersonationLevel >Token->ImpersonationLevel)
+        {
+            ObDereferenceObject(Token);
+            SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
+                                               PreviousMode,
+                                               FALSE);
+            return STATUS_BAD_IMPERSONATION_LEVEL;
+        }
+    }
+
+    Status = SepDuplicateToken(Token,
+                               ObjectAttributes,
+                               EffectiveOnly,
+                               TokenType,
+                               (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
+                               PreviousMode,
+                               &NewToken);
+
+    ObDereferenceObject(Token);
 
+    if (NT_SUCCESS(Status))
+    {
+        Status = ObInsertObject((PVOID)NewToken,
+                                NULL,
+                                DesiredAccess,
+                                0,
+                                NULL,
+                                &hToken);
         if (NT_SUCCESS(Status))
         {
-            Status = ObInsertObject((PVOID)NewToken,
-                                    NULL,
-                                    DesiredAccess,
-                                    0,
-                                    NULL,
-                                    &hToken);
-
-            if (NT_SUCCESS(Status))
+            _SEH2_TRY
             {
-                _SEH2_TRY
-                {
-                    *NewTokenHandle = hToken;
-                }
-                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-                {
-                    Status = _SEH2_GetExceptionCode();
-                }
-                _SEH2_END;
+                *NewTokenHandle = hToken;
             }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                Status = _SEH2_GetExceptionCode();
+            }
+            _SEH2_END;
         }
     }