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 } 189