Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434/** PROJECT: ReactOS kernel-mode tests* LICENSE: GPLv2+ - See COPYING in the top level directory* PURPOSE: Kernel-Mode Test Suite Process Notification Routines test* PROGRAMMER: Constantine Belev (Moscow State Technical University)* Denis Grishin (Moscow State Technical University)* Egor Sinitsyn (Moscow State Technical University)*/
#include <kmt_test.h>#include <ntifs.h>
#define NDEBUG#include <debug.h>
// Copied from PspProcessMapping -- although the values don't matter much for// the most part.static GENERIC_MAPPING ProcessGenericMapping ={ STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, PROCESS_ALL_ACCESS};
//------------------------------------------------------------------------------//// Testing Functions ////------------------------------------------------------------------------------//
// Testing function for SQIT
void TestsSeQueryInformationToken(PACCESS_TOKEN Token){ NTSTATUS Status; PVOID Buffer = NULL; PSID sid; PTOKEN_OWNER Towner; PTOKEN_DEFAULT_DACL TDefDacl; PTOKEN_GROUPS TGroups; ULONG GroupCount; PACL acl; PTOKEN_STATISTICS TStats; PTOKEN_TYPE TType; PTOKEN_USER TUser; BOOLEAN Flag; ULONG i;
//----------------------------------------------------------------// // Testing SeQueryInformationToken with various args // //----------------------------------------------------------------//
ok(Token != NULL, "Token is not captured. Testing SQIT interrupted\n\n");
if (Token == NULL) return;
Status = SeQueryInformationToken(Token, TokenOwner, &Buffer); ok((Status == STATUS_SUCCESS), "SQIT with TokenOwner arg fails with status 0x%08X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenOwner arg. But Buffer == NULL\n");
if (Buffer) { Towner = (TOKEN_OWNER *)Buffer; sid = Towner->Owner; ok((RtlValidSid(sid) == TRUE), "TokenOwner's SID is not a valid SID\n"); ExFreePool(Buffer); } }
//----------------------------------------------------------------//
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenDefaultDacl, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenDefaultDacl fails with status 0x%08X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenDefaultDacl arg. But Buffer == NULL\n"); if (Buffer) { TDefDacl = (PTOKEN_DEFAULT_DACL)Buffer; acl = TDefDacl->DefaultDacl; ok(((acl->AclRevision == ACL_REVISION || acl->AclRevision == ACL_REVISION_DS) == TRUE), "DACL is invalid\n"); ExFreePool(Buffer); } }
//----------------------------------------------------------------//
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenGroups, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenGroups fails with status 0x%08X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenGroups arg. But Buffer == NULL\n"); if (Buffer) { TGroups = (PTOKEN_GROUPS)Buffer; GroupCount = TGroups->GroupCount; Flag = TRUE; for (i = 0; i < GroupCount; i++) { sid = TGroups->Groups[i].Sid; if (!RtlValidSid(sid)) { Flag = FALSE; break; } } ok((Flag == TRUE), "TokenGroup's SIDs are not valid\n"); ExFreePool(Buffer); } }
//----------------------------------------------------------------//
// Call SQIT with TokenImpersonationLevel argument. Although our token // is not an impersonation token, the call will outright fail.
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer); ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenImpersonationLevel must return STATUS_INVALID_INFO_CLASS but got 0x%08X\n", Status); ok(Buffer == NULL, "SQIT has failed to query the impersonation level but buffer is not NULL!\n");
//----------------------------------------------------------------//
// Call SQIT with the 4 classes (TokenOrigin, TokenGroupsAndPrivileges, // TokenRestrictedSids and TokenSandBoxInert) are not supported by // SeQueryInformationToken (only NtQueryInformationToken supports them). //
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenOrigin, &Buffer); ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenOrigin failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenGroupsAndPrivileges, &Buffer); ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenGroupsAndPrivileges failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenRestrictedSids, &Buffer); ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenRestrictedSids failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer); ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenSandBoxInert failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
//----------------------------------------------------------------//
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenStatistics, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenStatistics fails with status 0x%08X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenStatistics arg. But Buffer == NULL\n"); if (Buffer) { TStats = (PTOKEN_STATISTICS)Buffer; // just put 0 into 1st arg or use trace to print TokenStatistics ok(1, "print statistics:\n\tTokenID = %u_%d\n\tSecurityImperLevel = %d\n\tPrivCount = %d\n\tGroupCount = %d\n\n", TStats->TokenId.LowPart, TStats->TokenId.HighPart, TStats->ImpersonationLevel, TStats->PrivilegeCount, TStats->GroupCount ); ExFreePool(Buffer); } } else { ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); }
//----------------------------------------------------------------//
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenType, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenType fails with status 0x%08X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenType arg. But Buffer == NULL\n"); if (Buffer) { TType = (PTOKEN_TYPE)Buffer; ok((*TType == TokenPrimary || *TType == TokenImpersonation), "TokenType in not a primary nor impersonation. FAILED\n"); ExFreePool(Buffer); } }
//----------------------------------------------------------------//
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenUser, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenUser fails\n"); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenUser arg. But Buffer == NULL\n"); if (Buffer) { TUser = (PTOKEN_USER)Buffer; ok(RtlValidSid(TUser->User.Sid), "TokenUser has an invalid Sid\n"); ExFreePool(Buffer); } }
//----------------------------------------------------------------//
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer); ok(Status != STATUS_SUCCESS, "SQIT must fail with wrong TOKEN_INFORMATION_CLASS arg\n");}
//------------------------------------------------------------------------------//
//------------------------------------------------------------------------------//// Body of the main test ////------------------------------------------------------------------------------//
START_TEST(SeQueryInfoToken){ PACCESS_STATE AccessState; ACCESS_MASK AccessMask = MAXIMUM_ALLOWED; ACCESS_MASK DesiredAccess = MAXIMUM_ALLOWED; NTSTATUS Status = STATUS_SUCCESS; PAUX_ACCESS_DATA AuxData = NULL; PPRIVILEGE_SET NewPrivilegeSet; ULONG InitialPrivilegeCount; BOOLEAN Checker; PPRIVILEGE_SET Privileges = NULL; PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL; PACCESS_TOKEN Token = NULL; PTOKEN_PRIVILEGES TPrivileges; PVOID Buffer; ULONG i;
SubjectContext = ExAllocatePool(PagedPool, sizeof(SECURITY_SUBJECT_CONTEXT));
SeCaptureSubjectContext(SubjectContext); SeLockSubjectContext(SubjectContext); Token = SeQuerySubjectContextToken(SubjectContext);
// Testing SQIT with current Token TestsSeQueryInformationToken(Token);
//----------------------------------------------------------------// // Creating an ACCESS_STATE structure // //----------------------------------------------------------------//
AccessState = ExAllocatePool(PagedPool, sizeof(ACCESS_STATE)); // AUX_ACCESS_DATA gets larger in newer Windows version. // This is the largest known size, found in Windows 10/11. AuxData = ExAllocatePoolZero(PagedPool, 0xE0, 'QSmK');
Status = SeCreateAccessState(AccessState, AuxData, DesiredAccess, &ProcessGenericMapping );
ok((Status == STATUS_SUCCESS), "SeCreateAccessState failed with Status 0x%08X\n", Status);
SeCaptureSubjectContext(&AccessState->SubjectSecurityContext); SeLockSubjectContext(&AccessState->SubjectSecurityContext); Token = SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext);
// Testing SQIT with AccessState Token TestsSeQueryInformationToken(Token);
//----------------------------------------------------------------// // Testing other functions // //----------------------------------------------------------------//
//----------------------------------------------------------------// // Testing SeAppendPrivileges // //----------------------------------------------------------------//
InitialPrivilegeCount = AuxData->PrivilegesUsed->PrivilegeCount; trace("Initial privilege count = %lu\n", InitialPrivilegeCount);
// Testing SeAppendPrivileges. Must change PrivilegeCount to 2 (1 + 1)
NewPrivilegeSet = ExAllocatePoolZero(PagedPool, FIELD_OFFSET(PRIVILEGE_SET, Privilege[1]), 'QSmK'); NewPrivilegeSet->PrivilegeCount = 1;
Status = SeAppendPrivileges(AccessState, NewPrivilegeSet); ok(Status == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); ok_eq_ulong(AuxData->PrivilegesUsed->PrivilegeCount, InitialPrivilegeCount + 1); ExFreePoolWithTag(NewPrivilegeSet, 'QSmK');
//----------------------------------------------------------------//
// Testing SeAppendPrivileges. Must change PrivilegeCount to 6 (2 + 4)
NewPrivilegeSet = ExAllocatePoolZero(PagedPool, FIELD_OFFSET(PRIVILEGE_SET, Privilege[4]), 'QSmK'); NewPrivilegeSet->PrivilegeCount = 4;
Status = SeAppendPrivileges(AccessState, NewPrivilegeSet); ok(Status == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); ok_eq_ulong(AuxData->PrivilegesUsed->PrivilegeCount, InitialPrivilegeCount + 5); ExFreePoolWithTag(NewPrivilegeSet, 'QSmK');
//----------------------------------------------------------------// // Testing SePrivilegeCheck // //----------------------------------------------------------------//
// KPROCESSOR_MODE is set to KernelMode ===> Always return TRUE ok(SePrivilegeCheck(AuxData->PrivilegesUsed, &(AccessState->SubjectSecurityContext), KernelMode), "SePrivilegeCheck failed with KernelMode mode arg\n"); // and call it again ok(SePrivilegeCheck(AuxData->PrivilegesUsed, &(AccessState->SubjectSecurityContext), KernelMode), "SePrivilegeCheck failed with KernelMode mode arg\n");
//----------------------------------------------------------------//
// KPROCESSOR_MODE is set to UserMode. Expect false ok(!SePrivilegeCheck(AuxData->PrivilegesUsed, &(AccessState->SubjectSecurityContext), UserMode), "SePrivilegeCheck unexpected success with UserMode arg\n");
//----------------------------------------------------------------//
//----------------------------------------------------------------// // Testing SeFreePrivileges // //----------------------------------------------------------------//
// FIXME: KernelMode will automatically get all access granted without // getting Privileges filled in. For UserMode, Privileges will only get // filled if either WRITE_OWNER or ACCESS_SYSTEM_SECURITY is requested // and granted. So this doesn't really test SeFreePrivileges. Privileges = NULL; Checker = SeAccessCheck( AccessState->SecurityDescriptor, &AccessState->SubjectSecurityContext, FALSE, AccessState->OriginalDesiredAccess, AccessState->PreviouslyGrantedAccess, &Privileges, &ProcessGenericMapping, KernelMode, &AccessMask, &Status ); ok(Checker, "Checker is NULL\n"); ok(Privileges == NULL, "Privileges is not NULL\n"); if (Privileges) { trace("AuxData->PrivilegesUsed->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n", AuxData->PrivilegesUsed->PrivilegeCount, Privileges->PrivilegeCount); } if (Privileges) SeFreePrivileges(Privileges);
//----------------------------------------------------------------// // Testing SePrivilegeCheck // //----------------------------------------------------------------// // I'm trying to make success call of SePrivilegeCheck from UserMode // If we sets Privileges properly, can we expect true from SePrivilegeCheck? // answer: yes // This test demonstrates it
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenPrivileges, &Buffer); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenPrivileges arg. But Buffer == NULL\n"); if (Buffer) { TPrivileges = (PTOKEN_PRIVILEGES)(Buffer); //trace("TPCount = %u\n\n", TPrivileges->PrivilegeCount);
NewPrivilegeSet = ExAllocatePoolZero(PagedPool, FIELD_OFFSET(PRIVILEGE_SET, Privilege[14]), 'QSmK'); NewPrivilegeSet->PrivilegeCount = 14;
ok((SeAppendPrivileges(AccessState, NewPrivilegeSet)) == STATUS_SUCCESS, "SeAppendPrivileges failed\n"); ok_eq_ulong(AuxData->PrivilegesUsed->PrivilegeCount, InitialPrivilegeCount + 19); ExFreePoolWithTag(NewPrivilegeSet, 'QSmK'); for (i = 0; i < AuxData->PrivilegesUsed->PrivilegeCount; i++) { AuxData->PrivilegesUsed->Privilege[i].Attributes = TPrivileges->Privileges[i].Attributes; AuxData->PrivilegesUsed->Privilege[i].Luid = TPrivileges->Privileges[i].Luid; } //trace("AccessState->privCount = %u\n\n", ((PAUX_ACCESS_DATA)(AccessState->AuxData))->PrivilegesUsed->PrivilegeCount);
ok(SePrivilegeCheck(AuxData->PrivilegesUsed, &(AccessState->SubjectSecurityContext), UserMode), "SePrivilegeCheck fails in UserMode, but I wish it will success\n"); } }
// Call SeFreePrivileges again
// FIXME: See other SeAccessCheck call above, we're not really testing // SeFreePrivileges here. Privileges = NULL; Checker = SeAccessCheck( AccessState->SecurityDescriptor, &AccessState->SubjectSecurityContext, TRUE, AccessState->OriginalDesiredAccess, AccessState->PreviouslyGrantedAccess, &Privileges, &ProcessGenericMapping, KernelMode, &AccessMask, &Status ); ok(Checker, "Checker is NULL\n"); ok(Privileges == NULL, "Privileges is not NULL\n"); if (Privileges) { trace("AuxData->PrivilegesUsed->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n", AuxData->PrivilegesUsed->PrivilegeCount, Privileges->PrivilegeCount); } if (Privileges) SeFreePrivileges(Privileges);
//----------------------------------------------------------------// // Missing for now // //----------------------------------------------------------------//
SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); SeUnlockSubjectContext(SubjectContext);
SeDeleteAccessState(AccessState);
if (SubjectContext) ExFreePool(SubjectContext); if (AuxData) ExFreePoolWithTag(AuxData, 'QSmK'); if (AccessState) ExFreePool(AccessState);}