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 108 // 109 // What's up? Why SQIT fails with right arg? 110 // Because your token has Token->TokenType != TokenImpersonation. -hbelusca 111 112 Buffer = NULL; 113 Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer); 114 ok(Status == STATUS_SUCCESS, "SQIT with TokenImpersonationLevel fails with status 0x%08X\n", Status); 115 if (Buffer) ExFreePool(Buffer); 116 117 Buffer = NULL; 118 Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer); 119 ok(Status == STATUS_SUCCESS, "and again: SQIT with TokenImpersonationLevel fails with status 0x%08X\n", Status); 120 if (Status == STATUS_SUCCESS) 121 { 122 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenImpersonationLevel arg. But Buffer == NULL\n"); 123 } else { 124 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 125 } 126 if (Buffer) ExFreePool(Buffer); 127 128 //----------------------------------------------------------------// 129 130 // Call SQIT with the 4 classes (TokenOrigin, TokenGroupsAndPrivileges, 131 // TokenRestrictedSids and TokenSandBoxInert) are not supported by 132 // SeQueryInformationToken (only NtQueryInformationToken supports them). 133 // 134 135 Buffer = NULL; 136 Status = SeQueryInformationToken(Token, TokenOrigin, &Buffer); 137 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenOrigin failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); 138 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 139 140 Buffer = NULL; 141 Status = SeQueryInformationToken(Token, TokenGroupsAndPrivileges, &Buffer); 142 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenGroupsAndPrivileges failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); 143 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 144 145 Buffer = NULL; 146 Status = SeQueryInformationToken(Token, TokenRestrictedSids, &Buffer); 147 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenRestrictedSids failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); 148 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 149 150 Buffer = NULL; 151 Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer); 152 ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenSandBoxInert failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); 153 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 154 155 //----------------------------------------------------------------// 156 157 Buffer = NULL; 158 Status = SeQueryInformationToken(Token, TokenStatistics, &Buffer); 159 ok(Status == STATUS_SUCCESS, "SQIT with TokenStatistics fails with status 0x%08X\n", Status); 160 if (Status == STATUS_SUCCESS) 161 { 162 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenStatistics arg. But Buffer == NULL\n"); 163 if (Buffer) 164 { 165 TStats = (PTOKEN_STATISTICS)Buffer; 166 // just put 0 into 1st arg or use trace to print TokenStatistics 167 ok(1, "print statistics:\n\tTokenID = %u_%d\n\tSecurityImperLevel = %d\n\tPrivCount = %d\n\tGroupCount = %d\n\n", TStats->TokenId.LowPart, 168 TStats->TokenId.HighPart, 169 TStats->ImpersonationLevel, 170 TStats->PrivilegeCount, 171 TStats->GroupCount 172 ); 173 ExFreePool(Buffer); 174 } 175 } else { 176 ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); 177 } 178 179 //----------------------------------------------------------------// 180 181 Buffer = NULL; 182 Status = SeQueryInformationToken(Token, TokenType, &Buffer); 183 ok(Status == STATUS_SUCCESS, "SQIT with TokenType fails with status 0x%08X\n", Status); 184 if (Status == STATUS_SUCCESS) 185 { 186 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenType arg. But Buffer == NULL\n"); 187 if (Buffer) 188 { 189 TType = (PTOKEN_TYPE)Buffer; 190 ok((*TType == TokenPrimary || *TType == TokenImpersonation), "TokenType in not a primary nor impersonation. FAILED\n"); 191 ExFreePool(Buffer); 192 } 193 } 194 195 //----------------------------------------------------------------// 196 197 Buffer = NULL; 198 Status = SeQueryInformationToken(Token, TokenUser, &Buffer); 199 ok(Status == STATUS_SUCCESS, "SQIT with TokenUser fails\n"); 200 if (Status == STATUS_SUCCESS) 201 { 202 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenUser arg. But Buffer == NULL\n"); 203 if (Buffer) 204 { 205 TUser = (PTOKEN_USER)Buffer; 206 ok(RtlValidSid(TUser->User.Sid), "TokenUser has an invalid Sid\n"); 207 ExFreePool(Buffer); 208 } 209 } 210 211 //----------------------------------------------------------------// 212 213 Buffer = NULL; 214 Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer); 215 ok(Status != STATUS_SUCCESS, "SQIT must fail with wrong TOKEN_INFORMATION_CLASS arg\n"); 216 } 217 218 //------------------------------------------------------------------------------// 219 220 //------------------------------------------------------------------------------// 221 // Body of the main test // 222 //------------------------------------------------------------------------------// 223 224 START_TEST(SeQueryInfoToken) 225 { 226 PACCESS_STATE AccessState; 227 ACCESS_MASK AccessMask = MAXIMUM_ALLOWED; 228 ACCESS_MASK DesiredAccess = MAXIMUM_ALLOWED; 229 NTSTATUS Status = STATUS_SUCCESS; 230 PAUX_ACCESS_DATA AuxData = NULL; 231 PPRIVILEGE_SET NewPrivilegeSet; 232 BOOLEAN Checker; 233 PPRIVILEGE_SET Privileges = NULL; 234 PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL; 235 PACCESS_TOKEN Token = NULL; 236 PTOKEN_PRIVILEGES TPrivileges; 237 PVOID Buffer; 238 POBJECT_TYPE PsProcessType = NULL; 239 PGENERIC_MAPPING GenericMapping; 240 ULONG i; 241 242 SubjectContext = ExAllocatePool(PagedPool, sizeof(SECURITY_SUBJECT_CONTEXT)); 243 244 SeCaptureSubjectContext(SubjectContext); 245 SeLockSubjectContext(SubjectContext); 246 Token = SeQuerySubjectContextToken(SubjectContext); 247 248 // Testing SQIT with current Token 249 TestsSeQueryInformationToken(Token); 250 251 //----------------------------------------------------------------// 252 // Creating an ACCESS_STATE structure // 253 //----------------------------------------------------------------// 254 255 AccessState = ExAllocatePool(PagedPool, sizeof(ACCESS_STATE)); 256 PsProcessType = ExAllocatePool(PagedPool, sizeof(OBJECT_TYPE)); 257 AuxData = ExAllocatePool(PagedPool, 0xC8); 258 GenericMapping = ExAllocatePool(PagedPool, sizeof(GENERIC_MAPPING)); 259 260 Status = SeCreateAccessState(AccessState, 261 (PVOID)AuxData, 262 DesiredAccess, 263 GenericMapping 264 ); 265 266 ok((Status == STATUS_SUCCESS), "SeCreateAccessState failed with Status 0x%08X\n", Status); 267 268 SeCaptureSubjectContext(&AccessState->SubjectSecurityContext); 269 SeLockSubjectContext(&AccessState->SubjectSecurityContext); 270 Token = SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext); 271 272 // Testing SQIT with AccessState Token 273 TestsSeQueryInformationToken(Token); 274 275 //----------------------------------------------------------------// 276 // Testing other functions // 277 //----------------------------------------------------------------// 278 279 //----------------------------------------------------------------// 280 // Testing SeAppendPrivileges // 281 //----------------------------------------------------------------// 282 283 AuxData->PrivilegeSet->PrivilegeCount = 1; 284 285 // Testing SeAppendPrivileges. Must change PrivilegeCount to 2 (1 + 1) 286 287 NewPrivilegeSet = ExAllocatePool(PagedPool, sizeof(PRIVILEGE_SET)); 288 NewPrivilegeSet->PrivilegeCount = 1; 289 290 Status = SeAppendPrivileges(AccessState, NewPrivilegeSet); 291 ok(Status == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); 292 ok((AuxData->PrivilegeSet->PrivilegeCount == 2),"PrivelegeCount must be 2, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount); 293 ExFreePool(NewPrivilegeSet); 294 295 //----------------------------------------------------------------// 296 297 // Testing SeAppendPrivileges. Must change PrivilegeCount to 6 (2 + 4) 298 299 NewPrivilegeSet = ExAllocatePool(PagedPool, 4*sizeof(PRIVILEGE_SET)); 300 NewPrivilegeSet->PrivilegeCount = 4; 301 302 Status = SeAppendPrivileges(AccessState, NewPrivilegeSet); 303 ok(Status == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); 304 ok((AuxData->PrivilegeSet->PrivilegeCount == 6),"PrivelegeCount must be 6, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount); 305 ExFreePool(NewPrivilegeSet); 306 307 //----------------------------------------------------------------// 308 // Testing SePrivilegeCheck // 309 //----------------------------------------------------------------// 310 311 // KPROCESSOR_MODE is set to KernelMode ===> Always return TRUE 312 ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), KernelMode), "SePrivilegeCheck failed with KernelMode mode arg\n"); 313 // and call it again 314 ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), KernelMode), "SePrivilegeCheck failed with KernelMode mode arg\n"); 315 316 //----------------------------------------------------------------// 317 318 // KPROCESSOR_MODE is set to UserMode. Expect false 319 ok(!SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), UserMode), "SePrivilegeCheck unexpected success with UserMode arg\n"); 320 321 //----------------------------------------------------------------// 322 323 //----------------------------------------------------------------// 324 // Testing SeFreePrivileges // 325 //----------------------------------------------------------------// 326 327 Privileges = NULL; 328 Checker = SeAccessCheck( 329 AccessState->SecurityDescriptor, 330 &AccessState->SubjectSecurityContext, 331 FALSE, 332 AccessState->OriginalDesiredAccess, 333 AccessState->PreviouslyGrantedAccess, 334 &Privileges, 335 (PGENERIC_MAPPING)((PCHAR*)PsProcessType + 52), 336 KernelMode, 337 &AccessMask, 338 &Status 339 ); 340 ok(Checker, "Checker is NULL\n"); 341 ok((Privileges != NULL), "Privileges is NULL\n"); 342 if (Privileges) 343 { 344 trace("AuxData->PrivilegeSet->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n", 345 AuxData->PrivilegeSet->PrivilegeCount, Privileges->PrivilegeCount); 346 } 347 if (Privileges) SeFreePrivileges(Privileges); 348 349 350 //----------------------------------------------------------------// 351 // Testing SePrivilegeCheck // 352 //----------------------------------------------------------------// 353 // I'm trying to make success call of SePrivilegeCheck from UserMode 354 // If we sets Privileges properly, can we expect true from SePrivilegeCheck? 355 // answer: yes 356 // This test demonstrates it 357 358 Buffer = NULL; 359 Status = SeQueryInformationToken(Token, TokenPrivileges, &Buffer); 360 if (Status == STATUS_SUCCESS) 361 { 362 ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenPrivileges arg. But Buffer == NULL\n"); 363 if (Buffer) 364 { 365 TPrivileges = (PTOKEN_PRIVILEGES)(Buffer); 366 //trace("TPCount = %u\n\n", TPrivileges->PrivilegeCount); 367 368 NewPrivilegeSet = ExAllocatePool(PagedPool, 14*sizeof(PRIVILEGE_SET)); 369 NewPrivilegeSet->PrivilegeCount = 14; 370 371 ok((SeAppendPrivileges(AccessState, NewPrivilegeSet)) == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); 372 ok((AuxData->PrivilegeSet->PrivilegeCount == 20),"PrivelegeCount must be 20, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount); 373 ExFreePool(NewPrivilegeSet); 374 for (i = 0; i < AuxData->PrivilegeSet->PrivilegeCount; i++) 375 { 376 AuxData->PrivilegeSet->Privilege[i].Attributes = TPrivileges->Privileges[i].Attributes; 377 AuxData->PrivilegeSet->Privilege[i].Luid = TPrivileges->Privileges[i].Luid; 378 } 379 //trace("AccessState->privCount = %u\n\n", ((PAUX_ACCESS_DATA)(AccessState->AuxData))->PrivilegeSet->PrivilegeCount); 380 381 ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), UserMode), "SePrivilegeCheck fails in UserMode, but I wish it will success\n"); 382 } 383 } 384 385 // Call SeFreePrivileges again 386 387 Privileges = NULL; 388 Checker = SeAccessCheck( 389 AccessState->SecurityDescriptor, 390 &AccessState->SubjectSecurityContext, 391 TRUE, 392 AccessState->OriginalDesiredAccess, 393 AccessState->PreviouslyGrantedAccess, 394 &Privileges, 395 (PGENERIC_MAPPING)((PCHAR*)PsProcessType + 52), 396 KernelMode, 397 &AccessMask, 398 &Status 399 ); 400 ok(Checker, "Checker is NULL\n"); 401 ok((Privileges != NULL), "Privileges is NULL\n"); 402 if (Privileges) 403 { 404 trace("AuxData->PrivilegeSet->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n", 405 AuxData->PrivilegeSet->PrivilegeCount, Privileges->PrivilegeCount); 406 } 407 if (Privileges) SeFreePrivileges(Privileges); 408 409 //----------------------------------------------------------------// 410 // Missing for now // 411 //----------------------------------------------------------------// 412 413 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 414 SeUnlockSubjectContext(SubjectContext); 415 416 SeDeleteAccessState(AccessState); 417 418 if (GenericMapping) ExFreePool(GenericMapping); 419 if (PsProcessType) ExFreePool(PsProcessType); 420 if (SubjectContext) ExFreePool(SubjectContext); 421 if (AuxData) ExFreePool(AuxData); 422 if (AccessState) ExFreePool(AccessState); 423 }