https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fefb1b77458f05ecdc4e0956c1b69c109f51142e

commit fefb1b77458f05ecdc4e0956c1b69c109f51142e
Author:     George Bișoc <george.bi...@reactos.org>
AuthorDate: Sat Sep 30 21:05:18 2023 +0200
Commit:     George Bișoc <george.bi...@reactos.org>
CommitDate: Wed Oct 4 18:04:29 2023 +0200

    [NTDLL_APITEST] Write NtAccessCheck testcase that tests for empty generic 
mapping scenario
    
    See b79aadd50bb7d5d6f08532284941c0334514c477 for further information.
---
 modules/rostests/apitests/ntdll/CMakeLists.txt  |   1 +
 modules/rostests/apitests/ntdll/NtAccessCheck.c | 188 ++++++++++++++++++++++++
 modules/rostests/apitests/ntdll/testlist.c      |   2 +
 3 files changed, 191 insertions(+)

diff --git a/modules/rostests/apitests/ntdll/CMakeLists.txt 
b/modules/rostests/apitests/ntdll/CMakeLists.txt
index 85515a2efaf..b6ce3a1cf4d 100644
--- a/modules/rostests/apitests/ntdll/CMakeLists.txt
+++ b/modules/rostests/apitests/ntdll/CMakeLists.txt
@@ -10,6 +10,7 @@ list(APPEND SOURCE
     load_notifications.c
     locale.c
     NtAcceptConnectPort.c
+    NtAccessCheck.c
     NtAccessCheckByType.c
     NtAccessCheckByTypeResultList.c
     NtAdjustGroupsToken.c
diff --git a/modules/rostests/apitests/ntdll/NtAccessCheck.c 
b/modules/rostests/apitests/ntdll/NtAccessCheck.c
new file mode 100644
index 00000000000..c987a445b13
--- /dev/null
+++ b/modules/rostests/apitests/ntdll/NtAccessCheck.c
@@ -0,0 +1,188 @@
+/*
+ * PROJECT:         ReactOS API tests
+ * LICENSE:         GPL-2.0-or-later 
(https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:         Tests for the NtAccessCheck API
+ * COPYRIGHT:       Copyright 2023 George Bișoc <george.bi...@reactos.org>
+ */
+
+#include "precomp.h"
+
+static
+HANDLE
+GetToken(VOID)
+{
+    NTSTATUS Status;
+    HANDLE Token;
+    HANDLE DuplicatedToken;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    SECURITY_QUALITY_OF_SERVICE Sqos;
+
+    Status = NtOpenProcessToken(NtCurrentProcess(),
+                                TOKEN_QUERY | TOKEN_DUPLICATE,
+                                &Token);
+    if (!NT_SUCCESS(Status))
+    {
+        trace("Failed to get current process token (Status 0x%08lx)\n", 
Status);
+        return NULL;
+    }
+
+    Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+    Sqos.ImpersonationLevel = SecurityImpersonation;
+    Sqos.ContextTrackingMode = 0;
+    Sqos.EffectiveOnly = FALSE;
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               NULL,
+                               0,
+                               NULL,
+                               NULL);
+    ObjectAttributes.SecurityQualityOfService = &Sqos;
+
+    Status = NtDuplicateToken(Token,
+                              TOKEN_QUERY | TOKEN_DUPLICATE,
+                              &ObjectAttributes,
+                              FALSE,
+                              TokenImpersonation,
+                              &DuplicatedToken);
+    if (!NT_SUCCESS(Status))
+    {
+        trace("Failed to duplicate token (Status 0x%08lx)\n", Status);
+        NtClose(Token);
+        return NULL;
+    }
+
+    return DuplicatedToken;
+}
+
+static
+VOID
+AccessCheckEmptyMappingTest(VOID)
+{
+    NTSTATUS Status;
+    NTSTATUS AccessStatus;
+    ACCESS_MASK GrantedAccess;
+    PPRIVILEGE_SET PrivilegeSet = NULL;
+    ULONG PrivilegeSetLength;
+    HANDLE Token = NULL;
+    PACL Dacl = NULL;
+    ULONG DaclSize;
+    SECURITY_DESCRIPTOR Sd;
+    PSID WorldSid = NULL;
+    static SID_IDENTIFIER_AUTHORITY WorldAuthority = 
{SECURITY_WORLD_SID_AUTHORITY};
+    static GENERIC_MAPPING EmptyMapping = {0, 0, 0, 0};
+
+    /* Allocate all the stuff we need */
+    PrivilegeSetLength = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
+    PrivilegeSet = RtlAllocateHeap(RtlGetProcessHeap(), 0, PrivilegeSetLength);
+    if (PrivilegeSet == NULL)
+    {
+        skip("Failed to allocate PrivilegeSet, skipping tests\n");
+        return;
+    }
+
+    Status = RtlAllocateAndInitializeSid(&WorldAuthority,
+                                         1,
+                                         SECURITY_WORLD_RID,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         &WorldSid);
+    if (!NT_SUCCESS(Status))
+    {
+        skip("Failed to create World SID, skipping tests\n");
+        goto Quit;
+    }
+
+    Token = GetToken();
+    if (Token == NULL)
+    {
+        skip("Failed to get token, skipping tests\n");
+        goto Quit;
+    }
+
+    Status = RtlCreateSecurityDescriptor(&Sd, SECURITY_DESCRIPTOR_REVISION);
+    if (!NT_SUCCESS(Status))
+    {
+        skip("Failed to create a security descriptor, skipping tests\n");
+        goto Quit;
+    }
+
+    DaclSize = sizeof(ACL) +
+               sizeof(ACCESS_ALLOWED_OBJECT_ACE) + RtlLengthSid(WorldSid);
+    Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
+                           HEAP_ZERO_MEMORY,
+                           DaclSize);
+    if (Dacl == NULL)
+    {
+        skip("Failed to allocate memory for DACL, skipping tests\n");
+        goto Quit;
+    }
+
+    /* Setup a ACL and give full access to everyone */
+    Status = RtlCreateAcl(Dacl,
+                          DaclSize,
+                          ACL_REVISION);
+    if (!NT_SUCCESS(Status))
+    {
+        skip("Failed to create DACL, skipping tests\n");
+        goto Quit;
+    }
+
+    Status = RtlAddAccessAllowedAce(Dacl,
+                                    ACL_REVISION,
+                                    GENERIC_ALL,
+                                    WorldSid);
+    if (!NT_SUCCESS(Status))
+    {
+        skip("Failed to add allowed ACE for World SID, skipping tests\n");
+        goto Quit;
+    }
+
+    /* Setup the descriptor */
+    RtlSetGroupSecurityDescriptor(&Sd, WorldSid, FALSE);
+    RtlSetOwnerSecurityDescriptor(&Sd, WorldSid, FALSE);
+    RtlSetDaclSecurityDescriptor(&Sd, TRUE, Dacl, FALSE);
+
+    /* Do an access check with empty mapping */
+    Status = NtAccessCheck(&Sd,
+                           Token,
+                           MAXIMUM_ALLOWED,
+                           &EmptyMapping,
+                           PrivilegeSet,
+                           &PrivilegeSetLength,
+                           &GrantedAccess,
+                           &AccessStatus);
+    ok_hex(Status, STATUS_SUCCESS);
+    ok(AccessStatus == STATUS_SUCCESS, "Expected a success status but got 
0x%08lx\n", AccessStatus);
+    trace("GrantedAccess == 0x%08lx\n", GrantedAccess);
+
+Quit:
+    if (Dacl)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
+    }
+
+    if (Token)
+    {
+        NtClose(Token);
+    }
+
+    if (WorldSid)
+    {
+        RtlFreeSid(WorldSid);
+    }
+
+    if (PrivilegeSet)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 0, PrivilegeSet);
+    }
+}
+
+START_TEST(NtAccessCheck)
+{
+    AccessCheckEmptyMappingTest();
+}
diff --git a/modules/rostests/apitests/ntdll/testlist.c 
b/modules/rostests/apitests/ntdll/testlist.c
index 2be58938238..438cc56a172 100644
--- a/modules/rostests/apitests/ntdll/testlist.c
+++ b/modules/rostests/apitests/ntdll/testlist.c
@@ -6,6 +6,7 @@
 extern void func_LdrEnumResources(void);
 extern void func_load_notifications(void);
 extern void func_NtAcceptConnectPort(void);
+extern void func_NtAccessCheck(void);
 extern void func_NtAccessCheckByType(void);
 extern void func_NtAccessCheckByTypeResultList(void);
 extern void func_NtAdjustGroupsToken(void);
@@ -102,6 +103,7 @@ const struct test winetest_testlist[] =
     { "LdrEnumResources",               func_LdrEnumResources },
     { "load_notifications",             func_load_notifications },
     { "NtAcceptConnectPort",            func_NtAcceptConnectPort },
+    { "NtAccessCheck",                  func_NtAccessCheck },
     { "NtAccessCheckByType",            func_NtAccessCheckByType },
     { "NtAccessCheckByTypeResultList",  func_NtAccessCheckByTypeResultList },
     { "NtAdjustGroupsToken",            func_NtAdjustGroupsToken },

Reply via email to