Reactos

[NTDLL_APITEST] Write NtAccessCheck testcase that tests for empty generic mapping scenario

See b79aadd50bb7d5d6f08532284941c0334514c477 for further information.

+191
+1
modules/rostests/apitests/ntdll/CMakeLists.txt
··· 10 10 load_notifications.c 11 11 locale.c 12 12 NtAcceptConnectPort.c 13 + NtAccessCheck.c 13 14 NtAccessCheckByType.c 14 15 NtAccessCheckByTypeResultList.c 15 16 NtAdjustGroupsToken.c
+188
modules/rostests/apitests/ntdll/NtAccessCheck.c
··· 1 + /* 2 + * PROJECT: ReactOS API tests 3 + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 + * PURPOSE: Tests for the NtAccessCheck API 5 + * COPYRIGHT: Copyright 2023 George Bișoc <george.bisoc@reactos.org> 6 + */ 7 + 8 + #include "precomp.h" 9 + 10 + static 11 + HANDLE 12 + GetToken(VOID) 13 + { 14 + NTSTATUS Status; 15 + HANDLE Token; 16 + HANDLE DuplicatedToken; 17 + OBJECT_ATTRIBUTES ObjectAttributes; 18 + SECURITY_QUALITY_OF_SERVICE Sqos; 19 + 20 + Status = NtOpenProcessToken(NtCurrentProcess(), 21 + TOKEN_QUERY | TOKEN_DUPLICATE, 22 + &Token); 23 + if (!NT_SUCCESS(Status)) 24 + { 25 + trace("Failed to get current process token (Status 0x%08lx)\n", Status); 26 + return NULL; 27 + } 28 + 29 + Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); 30 + Sqos.ImpersonationLevel = SecurityImpersonation; 31 + Sqos.ContextTrackingMode = 0; 32 + Sqos.EffectiveOnly = FALSE; 33 + 34 + InitializeObjectAttributes(&ObjectAttributes, 35 + NULL, 36 + 0, 37 + NULL, 38 + NULL); 39 + ObjectAttributes.SecurityQualityOfService = &Sqos; 40 + 41 + Status = NtDuplicateToken(Token, 42 + TOKEN_QUERY | TOKEN_DUPLICATE, 43 + &ObjectAttributes, 44 + FALSE, 45 + TokenImpersonation, 46 + &DuplicatedToken); 47 + if (!NT_SUCCESS(Status)) 48 + { 49 + trace("Failed to duplicate token (Status 0x%08lx)\n", Status); 50 + NtClose(Token); 51 + return NULL; 52 + } 53 + 54 + return DuplicatedToken; 55 + } 56 + 57 + static 58 + VOID 59 + AccessCheckEmptyMappingTest(VOID) 60 + { 61 + NTSTATUS Status; 62 + NTSTATUS AccessStatus; 63 + ACCESS_MASK GrantedAccess; 64 + PPRIVILEGE_SET PrivilegeSet = NULL; 65 + ULONG PrivilegeSetLength; 66 + HANDLE Token = NULL; 67 + PACL Dacl = NULL; 68 + ULONG DaclSize; 69 + SECURITY_DESCRIPTOR Sd; 70 + PSID WorldSid = NULL; 71 + static SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; 72 + static GENERIC_MAPPING EmptyMapping = {0, 0, 0, 0}; 73 + 74 + /* Allocate all the stuff we need */ 75 + PrivilegeSetLength = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]); 76 + PrivilegeSet = RtlAllocateHeap(RtlGetProcessHeap(), 0, PrivilegeSetLength); 77 + if (PrivilegeSet == NULL) 78 + { 79 + skip("Failed to allocate PrivilegeSet, skipping tests\n"); 80 + return; 81 + } 82 + 83 + Status = RtlAllocateAndInitializeSid(&WorldAuthority, 84 + 1, 85 + SECURITY_WORLD_RID, 86 + 0, 87 + 0, 88 + 0, 89 + 0, 90 + 0, 91 + 0, 92 + 0, 93 + &WorldSid); 94 + if (!NT_SUCCESS(Status)) 95 + { 96 + skip("Failed to create World SID, skipping tests\n"); 97 + goto Quit; 98 + } 99 + 100 + Token = GetToken(); 101 + if (Token == NULL) 102 + { 103 + skip("Failed to get token, skipping tests\n"); 104 + goto Quit; 105 + } 106 + 107 + Status = RtlCreateSecurityDescriptor(&Sd, SECURITY_DESCRIPTOR_REVISION); 108 + if (!NT_SUCCESS(Status)) 109 + { 110 + skip("Failed to create a security descriptor, skipping tests\n"); 111 + goto Quit; 112 + } 113 + 114 + DaclSize = sizeof(ACL) + 115 + sizeof(ACCESS_ALLOWED_OBJECT_ACE) + RtlLengthSid(WorldSid); 116 + Dacl = RtlAllocateHeap(RtlGetProcessHeap(), 117 + HEAP_ZERO_MEMORY, 118 + DaclSize); 119 + if (Dacl == NULL) 120 + { 121 + skip("Failed to allocate memory for DACL, skipping tests\n"); 122 + goto Quit; 123 + } 124 + 125 + /* Setup a ACL and give full access to everyone */ 126 + Status = RtlCreateAcl(Dacl, 127 + DaclSize, 128 + ACL_REVISION); 129 + if (!NT_SUCCESS(Status)) 130 + { 131 + skip("Failed to create DACL, skipping tests\n"); 132 + goto Quit; 133 + } 134 + 135 + Status = RtlAddAccessAllowedAce(Dacl, 136 + ACL_REVISION, 137 + GENERIC_ALL, 138 + WorldSid); 139 + if (!NT_SUCCESS(Status)) 140 + { 141 + skip("Failed to add allowed ACE for World SID, skipping tests\n"); 142 + goto Quit; 143 + } 144 + 145 + /* Setup the descriptor */ 146 + RtlSetGroupSecurityDescriptor(&Sd, WorldSid, FALSE); 147 + RtlSetOwnerSecurityDescriptor(&Sd, WorldSid, FALSE); 148 + RtlSetDaclSecurityDescriptor(&Sd, TRUE, Dacl, FALSE); 149 + 150 + /* Do an access check with empty mapping */ 151 + Status = NtAccessCheck(&Sd, 152 + Token, 153 + MAXIMUM_ALLOWED, 154 + &EmptyMapping, 155 + PrivilegeSet, 156 + &PrivilegeSetLength, 157 + &GrantedAccess, 158 + &AccessStatus); 159 + ok_hex(Status, STATUS_SUCCESS); 160 + ok(AccessStatus == STATUS_SUCCESS, "Expected a success status but got 0x%08lx\n", AccessStatus); 161 + trace("GrantedAccess == 0x%08lx\n", GrantedAccess); 162 + 163 + Quit: 164 + if (Dacl) 165 + { 166 + RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); 167 + } 168 + 169 + if (Token) 170 + { 171 + NtClose(Token); 172 + } 173 + 174 + if (WorldSid) 175 + { 176 + RtlFreeSid(WorldSid); 177 + } 178 + 179 + if (PrivilegeSet) 180 + { 181 + RtlFreeHeap(RtlGetProcessHeap(), 0, PrivilegeSet); 182 + } 183 + } 184 + 185 + START_TEST(NtAccessCheck) 186 + { 187 + AccessCheckEmptyMappingTest(); 188 + }
+2
modules/rostests/apitests/ntdll/testlist.c
··· 6 6 extern void func_LdrEnumResources(void); 7 7 extern void func_load_notifications(void); 8 8 extern void func_NtAcceptConnectPort(void); 9 + extern void func_NtAccessCheck(void); 9 10 extern void func_NtAccessCheckByType(void); 10 11 extern void func_NtAccessCheckByTypeResultList(void); 11 12 extern void func_NtAdjustGroupsToken(void); ··· 102 103 { "LdrEnumResources", func_LdrEnumResources }, 103 104 { "load_notifications", func_load_notifications }, 104 105 { "NtAcceptConnectPort", func_NtAcceptConnectPort }, 106 + { "NtAccessCheck", func_NtAccessCheck }, 105 107 { "NtAccessCheckByType", func_NtAccessCheckByType }, 106 108 { "NtAccessCheckByTypeResultList", func_NtAccessCheckByTypeResultList }, 107 109 { "NtAdjustGroupsToken", func_NtAdjustGroupsToken },