1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Kernel-Mode Test Suite Process Notification Routines test 5 * PROGRAMMER: Constantine Belev (Moscow State Technical University) 6 * Denis Grishin (Moscow State Technical University) 7 * Egor Sinitsyn (Moscow State Technical University) 8 */ 9 10 #include <kmt_test.h> 11 #include <ntifs.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 //------------------------------------------------------------------------------// 17 // Testing Functions // 18 //------------------------------------------------------------------------------// 19 20 // Testing function for SQIT 21 22 void TestsSeQueryInformationToken(PACCESS_TOKEN Token) 23 { 24 NTSTATUS Status; 25 PVOID Buffer = NULL; 26 PSID sid; 27 PTOKEN_OWNER Towner; 28 PTOKEN_DEFAULT_DACL TDefDacl; 29 PTOKEN_GROUPS TGroups; 30 ULONG GroupCount; 31 PACL acl; 32 PTOKEN_STATISTICS TStats; 33 PTOKEN_TYPE TType; 34 PTOKEN_USER TUser; 35 BOOLEAN Flag; 36 ULONG i; 37 38 //----------------------------------------------------------------// 39 // Testing SeQueryInformationToken with various args // 40 //----------------------------------------------------------------// 41 42 ok(Token != NULL, "Token is not captured. Testing SQIT interrupted\n\n"); 43 44 if (Token == NULL) return; 45 46 Status = SeQueryInformationToken(Token, TokenOwner, &Buffer); 47 ok((Status == STATUS_SUCCESS), "SQIT with TokenOwner arg fails with status 0x%08X\n", Status); 48 if (Status == STATUS_SUCCESS) 49 { 50 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenOwner arg. But Buffer == NULL\n"); 51 52 if (Buffer) 53 { 54 Towner = (TOKEN_OWNER *)Buffer; 55 sid = Towner->Owner; 56 ok((RtlValidSid(sid) == TRUE), "TokenOwner's SID is not a valid SID\n"); 57 ExFreePool(Buffer); 58 } 59 } 60 61 //----------------------------------------------------------------// 62 63 Buffer = NULL; 64 Status = SeQueryInformationToken(Token, TokenDefaultDacl, &Buffer); 65 ok(Status == STATUS_SUCCESS, "SQIT with TokenDefaultDacl fails with status 0x%08X\n", Status); 66 if (Status == STATUS_SUCCESS) 67 { 68 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenDefaultDacl arg. But Buffer == NULL\n"); 69 if (Buffer) 70 { 71 TDefDacl = (PTOKEN_DEFAULT_DACL)Buffer; 72 acl = TDefDacl->DefaultDacl; 73 ok(((acl->AclRevision == ACL_REVISION || acl->AclRevision == ACL_REVISION_DS) == TRUE), "DACL is invalid\n"); 74 ExFreePool(Buffer); 75 } 76 } 77 78 //----------------------------------------------------------------// 79 80 Buffer = NULL; 81 Status = SeQueryInformationToken(Token, TokenGroups, &Buffer); 82 ok(Status == STATUS_SUCCESS, "SQIT with TokenGroups fails with status 0x%08X\n", Status); 83 if (Status == STATUS_SUCCESS) 84 { 85 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenGroups arg. But Buffer == NULL\n"); 86 if (Buffer) 87 { 88 TGroups = (PTOKEN_GROUPS)Buffer; 89 GroupCount = TGroups->GroupCount; 90 Flag = TRUE; 91 for (i = 0; i < GroupCount; i++) 92 { 93 sid = TGroups->Groups[i].Sid; 94 if (!RtlValidSid(sid)) 95 { 96 Flag = FALSE; 97 break; 98 } 99 } 100 ok((Flag == TRUE), "TokenGroup's SIDs are not valid\n"); 101 ExFreePool(Buffer); 102 } 103 } 104 105 //----------------------------------------------------------------// 106 107 // Call SQIT with TokenImpersonationLevel argument. Although our token 108 // is not an impersonation token, the call will outright fail. 109 110 Buffer = NULL; 111 Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer); 112 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenImpersonationLevel must return STATUS_INVALID_INFO_CLASS but got 0x%08X\n", Status); 113 ok(Buffer == NULL, "SQIT has failed to query the impersonation level but buffer is not NULL!\n"); 114 115 //----------------------------------------------------------------// 116 117 // Call SQIT with the 4 classes (TokenOrigin, TokenGroupsAndPrivileges, 118 // TokenRestrictedSids and TokenSandBoxInert) are not supported by 119 // SeQueryInformationToken (only NtQueryInformationToken supports them). 120 // 121 122 Buffer = NULL; 123 Status = SeQueryInformationToken(Token, TokenOrigin, &Buffer); 124 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenOrigin failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); 125 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 126 127 Buffer = NULL; 128 Status = SeQueryInformationToken(Token, TokenGroupsAndPrivileges, &Buffer); 129 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenGroupsAndPrivileges failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); 130 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 131 132 Buffer = NULL; 133 Status = SeQueryInformationToken(Token, TokenRestrictedSids, &Buffer); 134 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenRestrictedSids failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); 135 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 136 137 Buffer = NULL; 138 Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer); 139 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenSandBoxInert failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); 140 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 141 142 //----------------------------------------------------------------// 143 144 Buffer = NULL; 145 Status = SeQueryInformationToken(Token, TokenStatistics, &Buffer); 146 ok(Status == STATUS_SUCCESS, "SQIT with TokenStatistics fails with status 0x%08X\n", Status); 147 if (Status == STATUS_SUCCESS) 148 { 149 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenStatistics arg. But Buffer == NULL\n"); 150 if (Buffer) 151 { 152 TStats = (PTOKEN_STATISTICS)Buffer; 153 // just put 0 into 1st arg or use trace to print TokenStatistics 154 ok(1, "print statistics:\n\tTokenID = %u_%d\n\tSecurityImperLevel = %d\n\tPrivCount = %d\n\tGroupCount = %d\n\n", TStats->TokenId.LowPart, 155 TStats->TokenId.HighPart, 156 TStats->ImpersonationLevel, 157 TStats->PrivilegeCount, 158 TStats->GroupCount 159 ); 160 ExFreePool(Buffer); 161 } 162 } else { 163 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 164 } 165 166 //----------------------------------------------------------------// 167 168 Buffer = NULL; 169 Status = SeQueryInformationToken(Token, TokenType, &Buffer); 170 ok(Status == STATUS_SUCCESS, "SQIT with TokenType fails with status 0x%08X\n", Status); 171 if (Status == STATUS_SUCCESS) 172 { 173 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenType arg. But Buffer == NULL\n"); 174 if (Buffer) 175 { 176 TType = (PTOKEN_TYPE)Buffer; 177 ok((*TType == TokenPrimary || *TType == TokenImpersonation), "TokenType in not a primary nor impersonation. FAILED\n"); 178 ExFreePool(Buffer); 179 } 180 } 181 182 //----------------------------------------------------------------// 183 184 Buffer = NULL; 185 Status = SeQueryInformationToken(Token, TokenUser, &Buffer); 186 ok(Status == STATUS_SUCCESS, "SQIT with TokenUser fails\n"); 187 if (Status == STATUS_SUCCESS) 188 { 189 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenUser arg. But Buffer == NULL\n"); 190 if (Buffer) 191 { 192 TUser = (PTOKEN_USER)Buffer; 193 ok(RtlValidSid(TUser->User.Sid), "TokenUser has an invalid Sid\n"); 194 ExFreePool(Buffer); 195 } 196 } 197 198 //----------------------------------------------------------------// 199 200 Buffer = NULL; 201 Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer); 202 ok(Status != STATUS_SUCCESS, "SQIT must fail with wrong TOKEN_INFORMATION_CLASS arg\n"); 203 } 204 205 //------------------------------------------------------------------------------// 206 207 //------------------------------------------------------------------------------// 208 // Body of the main test // 209 //------------------------------------------------------------------------------// 210 211 START_TEST(SeQueryInfoToken) 212 { 213 PACCESS_STATE AccessState; 214 ACCESS_MASK AccessMask = MAXIMUM_ALLOWED; 215 ACCESS_MASK DesiredAccess = MAXIMUM_ALLOWED; 216 NTSTATUS Status = STATUS_SUCCESS; 217 PAUX_ACCESS_DATA AuxData = NULL; 218 PPRIVILEGE_SET NewPrivilegeSet; 219 BOOLEAN Checker; 220 PPRIVILEGE_SET Privileges = NULL; 221 PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL; 222 PACCESS_TOKEN Token = NULL; 223 PTOKEN_PRIVILEGES TPrivileges; 224 PVOID Buffer; 225 POBJECT_TYPE PsProcessType = NULL; 226 PGENERIC_MAPPING GenericMapping; 227 ULONG i; 228 229 SubjectContext = ExAllocatePool(PagedPool, sizeof(SECURITY_SUBJECT_CONTEXT)); 230 231 SeCaptureSubjectContext(SubjectContext); 232 SeLockSubjectContext(SubjectContext); 233 Token = SeQuerySubjectContextToken(SubjectContext); 234 235 // Testing SQIT with current Token 236 TestsSeQueryInformationToken(Token); 237 238 //----------------------------------------------------------------// 239 // Creating an ACCESS_STATE structure // 240 //----------------------------------------------------------------// 241 242 AccessState = ExAllocatePool(PagedPool, sizeof(ACCESS_STATE)); 243 PsProcessType = ExAllocatePool(PagedPool, sizeof(OBJECT_TYPE)); 244 AuxData = ExAllocatePool(PagedPool, 0xC8); 245 GenericMapping = ExAllocatePool(PagedPool, sizeof(GENERIC_MAPPING)); 246 247 Status = SeCreateAccessState(AccessState, 248 (PVOID)AuxData, 249 DesiredAccess, 250 GenericMapping 251 ); 252 253 ok((Status == STATUS_SUCCESS), "SeCreateAccessState failed with Status 0x%08X\n", Status); 254 255 SeCaptureSubjectContext(&AccessState->SubjectSecurityContext); 256 SeLockSubjectContext(&AccessState->SubjectSecurityContext); 257 Token = SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext); 258 259 // Testing SQIT with AccessState Token 260 TestsSeQueryInformationToken(Token); 261 262 //----------------------------------------------------------------// 263 // Testing other functions // 264 //----------------------------------------------------------------// 265 266 //----------------------------------------------------------------// 267 // Testing SeAppendPrivileges // 268 //----------------------------------------------------------------// 269 270 AuxData->PrivilegeSet->PrivilegeCount = 1; 271 272 // Testing SeAppendPrivileges. Must change PrivilegeCount to 2 (1 + 1) 273 274 NewPrivilegeSet = ExAllocatePool(PagedPool, sizeof(PRIVILEGE_SET)); 275 NewPrivilegeSet->PrivilegeCount = 1; 276 277 Status = SeAppendPrivileges(AccessState, NewPrivilegeSet); 278 ok(Status == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); 279 ok((AuxData->PrivilegeSet->PrivilegeCount == 2),"PrivelegeCount must be 2, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount); 280 ExFreePool(NewPrivilegeSet); 281 282 //----------------------------------------------------------------// 283 284 // Testing SeAppendPrivileges. Must change PrivilegeCount to 6 (2 + 4) 285 286 NewPrivilegeSet = ExAllocatePool(PagedPool, 4*sizeof(PRIVILEGE_SET)); 287 NewPrivilegeSet->PrivilegeCount = 4; 288 289 Status = SeAppendPrivileges(AccessState, NewPrivilegeSet); 290 ok(Status == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); 291 ok((AuxData->PrivilegeSet->PrivilegeCount == 6),"PrivelegeCount must be 6, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount); 292 ExFreePool(NewPrivilegeSet); 293 294 //----------------------------------------------------------------// 295 // Testing SePrivilegeCheck // 296 //----------------------------------------------------------------// 297 298 // KPROCESSOR_MODE is set to KernelMode ===> Always return TRUE 299 ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), KernelMode), "SePrivilegeCheck failed with KernelMode mode arg\n"); 300 // and call it again 301 ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), KernelMode), "SePrivilegeCheck failed with KernelMode mode arg\n"); 302 303 //----------------------------------------------------------------// 304 305 // KPROCESSOR_MODE is set to UserMode. Expect false 306 ok(!SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), UserMode), "SePrivilegeCheck unexpected success with UserMode arg\n"); 307 308 //----------------------------------------------------------------// 309 310 //----------------------------------------------------------------// 311 // Testing SeFreePrivileges // 312 //----------------------------------------------------------------// 313 314 Privileges = NULL; 315 Checker = SeAccessCheck( 316 AccessState->SecurityDescriptor, 317 &AccessState->SubjectSecurityContext, 318 FALSE, 319 AccessState->OriginalDesiredAccess, 320 AccessState->PreviouslyGrantedAccess, 321 &Privileges, 322 (PGENERIC_MAPPING)((PCHAR*)PsProcessType + 52), 323 KernelMode, 324 &AccessMask, 325 &Status 326 ); 327 ok(Checker, "Checker is NULL\n"); 328 ok((Privileges != NULL), "Privileges is NULL\n"); 329 if (Privileges) 330 { 331 trace("AuxData->PrivilegeSet->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n", 332 AuxData->PrivilegeSet->PrivilegeCount, Privileges->PrivilegeCount); 333 } 334 if (Privileges) SeFreePrivileges(Privileges); 335 336 337 //----------------------------------------------------------------// 338 // Testing SePrivilegeCheck // 339 //----------------------------------------------------------------// 340 // I'm trying to make success call of SePrivilegeCheck from UserMode 341 // If we sets Privileges properly, can we expect true from SePrivilegeCheck? 342 // answer: yes 343 // This test demonstrates it 344 345 Buffer = NULL; 346 Status = SeQueryInformationToken(Token, TokenPrivileges, &Buffer); 347 if (Status == STATUS_SUCCESS) 348 { 349 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenPrivileges arg. But Buffer == NULL\n"); 350 if (Buffer) 351 { 352 TPrivileges = (PTOKEN_PRIVILEGES)(Buffer); 353 //trace("TPCount = %u\n\n", TPrivileges->PrivilegeCount); 354 355 NewPrivilegeSet = ExAllocatePool(PagedPool, 14*sizeof(PRIVILEGE_SET)); 356 NewPrivilegeSet->PrivilegeCount = 14; 357 358 ok((SeAppendPrivileges(AccessState, NewPrivilegeSet)) == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); 359 ok((AuxData->PrivilegeSet->PrivilegeCount == 20),"PrivelegeCount must be 20, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount); 360 ExFreePool(NewPrivilegeSet); 361 for (i = 0; i < AuxData->PrivilegeSet->PrivilegeCount; i++) 362 { 363 AuxData->PrivilegeSet->Privilege[i].Attributes = TPrivileges->Privileges[i].Attributes; 364 AuxData->PrivilegeSet->Privilege[i].Luid = TPrivileges->Privileges[i].Luid; 365 } 366 //trace("AccessState->privCount = %u\n\n", ((PAUX_ACCESS_DATA)(AccessState->AuxData))->PrivilegeSet->PrivilegeCount); 367 368 ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), UserMode), "SePrivilegeCheck fails in UserMode, but I wish it will success\n"); 369 } 370 } 371 372 // Call SeFreePrivileges again 373 374 Privileges = NULL; 375 Checker = SeAccessCheck( 376 AccessState->SecurityDescriptor, 377 &AccessState->SubjectSecurityContext, 378 TRUE, 379 AccessState->OriginalDesiredAccess, 380 AccessState->PreviouslyGrantedAccess, 381 &Privileges, 382 (PGENERIC_MAPPING)((PCHAR*)PsProcessType + 52), 383 KernelMode, 384 &AccessMask, 385 &Status 386 ); 387 ok(Checker, "Checker is NULL\n"); 388 ok((Privileges != NULL), "Privileges is NULL\n"); 389 if (Privileges) 390 { 391 trace("AuxData->PrivilegeSet->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n", 392 AuxData->PrivilegeSet->PrivilegeCount, Privileges->PrivilegeCount); 393 } 394 if (Privileges) SeFreePrivileges(Privileges); 395 396 //----------------------------------------------------------------// 397 // Missing for now // 398 //----------------------------------------------------------------// 399 400 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 401 SeUnlockSubjectContext(SubjectContext); 402 403 SeDeleteAccessState(AccessState); 404 405 if (GenericMapping) ExFreePool(GenericMapping); 406 if (PsProcessType) ExFreePool(PsProcessType); 407 if (SubjectContext) ExFreePool(SubjectContext); 408 if (AuxData) ExFreePool(AuxData); 409 if (AccessState) ExFreePool(AccessState); 410 } 411