/*++ Copyright (c) 1989 Microsoft Corporation Module Name: cttoken.c Abstract: Common token object test routines. These routines are used in both kernel and user mode tests. This test assumes the security runtime library routines are functioning correctly. NOTE: This test program allocates a lot of memory and frees none of it ! ! ! Author: Jim Kelly (JimK) 27-June-1990 Environment: Test of token object. Revision History: --*/ #include "tsecomm.c" // Mode dependent macros and routines. //////////////////////////////////////////////////////////////// // // // Module wide variables // // // //////////////////////////////////////////////////////////////// #define DEFAULT_DACL_LENGTH (1024L) #define GROUP_IDS_LENGTH (1024L) #define NEW_GROUP_STATE_LENGTH (1024L) #define PRIVILEGES_LENGTH (128L) #define TOO_BIG_ACL_SIZE (2048L) #define TOO_BIG_PRIMARY_GROUP_SIZE (39L) // // definitions related to TokenWithGroups // (we also substitute SYSTEM for NEANDERTHOL in some tests) // #define FLINTSTONE_INDEX (0L) #define CHILD_INDEX (1L) #define NEANDERTHOL_INDEX (2L) #define SYSTEM_INDEX (2L) #define WORLD_INDEX (3L) #define GROUP_COUNT (4L) // // Definitions related to TokenWithPrivileges // #define UNSOLICITED_INDEX (0L) #define SECURITY_INDEX (1L) #define ASSIGN_PRIMARY_INDEX (2L) #define PRIVILEGE_COUNT (3L) NTSTATUS Status; HANDLE SimpleToken; HANDLE TokenWithGroups; HANDLE TokenWithDefaultOwner; HANDLE TokenWithPrivileges; HANDLE TokenWithDefaultDacl; HANDLE Token; HANDLE ProcessToken; HANDLE ImpersonationToken; HANDLE AnonymousToken; OBJECT_ATTRIBUTES PrimaryTokenAttributes; PSECURITY_DESCRIPTOR PrimarySecurityDescriptor; SECURITY_QUALITY_OF_SERVICE PrimarySecurityQos; OBJECT_ATTRIBUTES ImpersonationTokenAttributes; PSECURITY_DESCRIPTOR ImpersonationSecurityDescriptor; SECURITY_QUALITY_OF_SERVICE ImpersonationSecurityQos; OBJECT_ATTRIBUTES AnonymousTokenAttributes; PSECURITY_DESCRIPTOR AnonymousSecurityDescriptor; SECURITY_QUALITY_OF_SERVICE AnonymousSecurityQos; ULONG DisabledGroupAttributes; ULONG OptionalGroupAttributes; ULONG NormalGroupAttributes; ULONG OwnerGroupAttributes; ULONG LengthAvailable; ULONG CurrentLength; TIME_FIELDS TempTimeFields = {3000, 1, 1, 1, 1, 1, 1, 1}; LARGE_INTEGER NoExpiration; LUID BadAuthenticationId; LUID SystemAuthenticationId = SYSTEM_LUID; LUID OriginalAuthenticationId; TOKEN_SOURCE TestSource = {"SE: TEST", 0}; PSID Owner; PSID Group; PACL Dacl; PSID TempOwner; PSID TempGroup; PACL TempDacl; UQUAD ThreadStack[256]; INITIAL_TEB InitialTeb; NTSTATUS Status; CLIENT_ID ThreadClientId; CONTEXT ThreadContext; HANDLE ThreadHandle; OBJECT_ATTRIBUTES ThreadObja; //////////////////////////////////////////////////////////////// // // // Private Macros // // // //////////////////////////////////////////////////////////////// #define TestpPrintLuid(G) \ DbgPrint( "(0x%lx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx)", \ (G).Data1, (G).Data2, (G).Data3, \ (G).Data4[0], (G).Data4[1], (G).Data4[2], \ (G).Data4[3], (G).Data4[4], (G).Data4[5], \ (G).Data4[6], (G).Data4[7]); \ //////////////////////////////////////////////////////////////// // // // Initialization Routine // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenInitialize() { NTSTATUS Status; ULONG ReturnLength; HANDLE ProcessToken; TOKEN_STATISTICS ProcessTokenStatistics; if (!TSeVariableInitialization()) { DbgPrint("Se: Failed to initialize global test variables.\n"); return FALSE; } DisabledGroupAttributes = (SE_GROUP_ENABLED_BY_DEFAULT); OptionalGroupAttributes = (SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ); NormalGroupAttributes = (SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ); OwnerGroupAttributes = (SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED | SE_GROUP_OWNER ); PrimarySecurityDescriptor = (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 ); Status = RtlCreateSecurityDescriptor ( PrimarySecurityDescriptor, SECURITY_DESCRIPTOR_REVISION1 ); ASSERT(NT_SUCCESS(Status)); Status = RtlSetDaclSecurityDescriptor ( PrimarySecurityDescriptor, TRUE, //DaclPresent, NULL, //Dacl OPTIONAL, // No protection FALSE //DaclDefaulted OPTIONAL ); ASSERT(NT_SUCCESS(Status)); InitializeObjectAttributes( &PrimaryTokenAttributes, NULL, OBJ_INHERIT, NULL, PrimarySecurityDescriptor ); ImpersonationSecurityDescriptor = (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 ); ImpersonationSecurityQos.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE); ImpersonationSecurityQos.ImpersonationLevel = SecurityImpersonation; ImpersonationSecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; ImpersonationSecurityQos.EffectiveOnly = FALSE; InitializeObjectAttributes( &ImpersonationTokenAttributes, NULL, OBJ_INHERIT, NULL, NULL ); ImpersonationTokenAttributes.SecurityQualityOfService = &ImpersonationSecurityQos; AnonymousSecurityDescriptor = (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 ); AnonymousSecurityQos.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE); AnonymousSecurityQos.ImpersonationLevel = SecurityAnonymous; AnonymousSecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; AnonymousSecurityQos.EffectiveOnly = FALSE; InitializeObjectAttributes( &AnonymousTokenAttributes, NULL, OBJ_INHERIT, NULL, NULL ); AnonymousTokenAttributes.SecurityQualityOfService = &AnonymousSecurityQos; // // Build an ACL for use. // Dacl = (PACL)TstAllocatePool( PagedPool, 256 ); Dacl->AclRevision=ACL_REVISION; Dacl->Sbz1=0; Dacl->Sbz2=0; Dacl->AclSize=256; Dacl->AceCount=0; // // Set up expiration times // TempTimeFields.Year = 3000; TempTimeFields.Month = 1; TempTimeFields.Day = 1; TempTimeFields.Hour = 1; TempTimeFields.Minute = 1; TempTimeFields.Second = 1; TempTimeFields.Milliseconds = 1; TempTimeFields.Weekday = 1; RtlTimeFieldsToTime( &TempTimeFields, &NoExpiration ); // // Set up a bad authentication ID // BadAuthenticationId = FredLuid; // // Use a token source specific to security test // NtAllocateLocallyUniqueId( &(TestSource.SourceIdentifier) ); // // Create a new thread for impersonation tests // // // Initialize object attributes. // Note that the name of the thread is NULL so that we // can run multiple copies of the test at the same time // without collisions. // InitializeObjectAttributes(&ThreadObja, NULL, 0, NULL, NULL); // // Initialize thread context and initial TEB. // RtlInitializeContext(NtCurrentProcess(), &ThreadContext, NULL, (PVOID)TestTokenInitialize, &ThreadStack[254]); InitialTeb.StackBase = &ThreadStack[254]; InitialTeb.StackLimit = &ThreadStack[0]; // // Create a thread in a suspended state. // Status = NtCreateThread(&ThreadHandle, THREAD_ALL_ACCESS, &ThreadObja, NtCurrentProcess(), &ThreadClientId, &ThreadContext, &InitialTeb, TRUE); ASSERT(NT_SUCCESS(Status)); // // The following is sortof a horse-before-the-cart type of initialization. // Now that the system is enforcing things like "you can only create a // token with an AuthenticationId that the reference monitor has been told // about, it is necessary to obtain some information out of our current // token. // Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_ALL_ACCESS, &ProcessToken ); ASSERT( NT_SUCCESS(Status) ); Status = NtQueryInformationToken( ProcessToken, // Handle TokenStatistics, // TokenInformationClass &ProcessTokenStatistics, // TokenInformation sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); OriginalAuthenticationId = ProcessTokenStatistics.AuthenticationId; DbgPrint("Done.\n"); return TRUE; } //////////////////////////////////////////////////////////////// // // // Test routines // // // //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// // // // Token Creation Test // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenCreate() { BOOLEAN CompletionStatus = TRUE; TOKEN_USER UserId; TOKEN_PRIMARY_GROUP PrimaryGroup; PTOKEN_GROUPS GroupIds; PTOKEN_PRIVILEGES Privileges; TOKEN_DEFAULT_DACL DefaultDacl; TOKEN_DEFAULT_DACL NullDefaultDacl; TOKEN_OWNER Owner; DbgPrint("\n"); GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool, GROUP_IDS_LENGTH ); Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool, PRIVILEGES_LENGTH ); DefaultDacl.DefaultDacl = (PACL)TstAllocatePool( PagedPool, DEFAULT_DACL_LENGTH ); // // Create the simplest token possible // (no Groups, explicit Owner, or DefaultDacl) // DbgPrint("Se: Create Simple Token ... "); UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; GroupIds->GroupCount = 0; Privileges->PrivilegeCount = 0; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &SystemAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges NULL, // Owner &PrimaryGroup, // Primary Group NULL, // Default Dacl &TestSource // TokenSource ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtDuplicateObject( NtCurrentProcess(), // SourceProcessHandle Token, // SourceHandle NtCurrentProcess(), // TargetProcessHandle &SimpleToken, // TargetHandle 0, // DesiredAccess (over-ridden by option) 0, // HandleAttributes DUPLICATE_SAME_ACCESS // Options ); ASSERT(NT_SUCCESS(Status)); Status = NtClose(Token); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Create a token with groups // DbgPrint("Se: Create Token With Groups ... "); GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[0].Sid = FlintstoneSid; GroupIds->Groups[1].Sid = ChildSid; GroupIds->Groups[2].Sid = NeandertholSid; GroupIds->Groups[3].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Privileges->PrivilegeCount = 0; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &OriginalAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges NULL, // Owner &PrimaryGroup, // Primary Group NULL, // Default Dacl &TestSource // TokenSource ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtDuplicateObject( NtCurrentProcess(), // SourceProcessHandle Token, // SourceHandle NtCurrentProcess(), // TargetProcessHandle &TokenWithGroups, // TargetHandle 0, // DesiredAccess (over-ridden by option) 0, // HandleAttributes DUPLICATE_SAME_ACCESS // Options ); ASSERT(NT_SUCCESS(Status)); Status = NtClose(Token); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Create a token with default owner // DbgPrint("Se: Create Token Default Owner ... "); GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid; GroupIds->Groups[CHILD_INDEX].Sid = ChildSid; GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid; GroupIds->Groups[WORLD_INDEX].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Owner.Owner = FlintstoneSid; Privileges->PrivilegeCount = 0; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &SystemAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges &Owner, // Owner &PrimaryGroup, // Primary Group NULL, // Default Dacl &TestSource // TokenSource ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtDuplicateObject( NtCurrentProcess(), // SourceProcessHandle Token, // SourceHandle NtCurrentProcess(), // TargetProcessHandle &TokenWithDefaultOwner, // TargetHandle 0, // DesiredAccess (over-ridden by option) 0, // HandleAttributes DUPLICATE_SAME_ACCESS // Options ); ASSERT(NT_SUCCESS(Status)); Status = NtClose(Token); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Create a token with default privileges // DbgPrint("Se: Create Token privileges ... "); GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid; GroupIds->Groups[CHILD_INDEX].Sid = ChildSid; GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid; GroupIds->Groups[WORLD_INDEX].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Owner.Owner = FlintstoneSid; Privileges->PrivilegeCount = PRIVILEGE_COUNT; Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege; Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege; Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &OriginalAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges &Owner, // Owner &PrimaryGroup, // Primary Group NULL, // Default Dacl &TestSource // TokenSource ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtDuplicateObject( NtCurrentProcess(), // SourceProcessHandle Token, // SourceHandle NtCurrentProcess(), // TargetProcessHandle &TokenWithPrivileges, // TargetHandle 0, // DesiredAccess (over-ridden by option) 0, // HandleAttributes DUPLICATE_SAME_ACCESS // Options ); ASSERT(NT_SUCCESS(Status)); Status = NtClose(Token); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Create a token with default DACL // DbgPrint("Se: Create Token With Default Dacl ... "); GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid; GroupIds->Groups[CHILD_INDEX].Sid = ChildSid; GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid; GroupIds->Groups[WORLD_INDEX].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Owner.Owner = FlintstoneSid; Privileges->PrivilegeCount = PRIVILEGE_COUNT; Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege; Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege; Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION); ASSERT(NT_SUCCESS(Status) ); Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &SystemAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges &Owner, // Owner &PrimaryGroup, // Primary Group &DefaultDacl, // Default Dacl &TestSource // TokenSource ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); // // Save a copy of this for later use... // Status = NtDuplicateObject( NtCurrentProcess(), // SourceProcessHandle Token, // SourceHandle NtCurrentProcess(), // TargetProcessHandle &TokenWithDefaultDacl, // TargetHandle 0, // DesiredAccess (over-ridden by option) 0, // HandleAttributes DUPLICATE_SAME_ACCESS // Options ); ASSERT(NT_SUCCESS(Status)); Status = NtClose(Token); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Create a token with a null default DACL // DbgPrint("Se: Create Token With a Null Default Dacl ... "); GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid; GroupIds->Groups[CHILD_INDEX].Sid = ChildSid; GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid; GroupIds->Groups[WORLD_INDEX].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Owner.Owner = FlintstoneSid; Privileges->PrivilegeCount = PRIVILEGE_COUNT; Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege; Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege; Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED; PrimaryGroup.PrimaryGroup = FlintstoneSid; NullDefaultDacl.DefaultDacl = NULL; Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &OriginalAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges &Owner, // Owner &PrimaryGroup, // Primary Group &NullDefaultDacl, // Default Dacl &TestSource // TokenSource ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtClose(Token); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Create an impersonation token, Impersonation level = Impersonation // DbgPrint("Se: Create an impersonation token ... "); GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid; GroupIds->Groups[CHILD_INDEX].Sid = ChildSid; GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid; GroupIds->Groups[WORLD_INDEX].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Owner.Owner = FlintstoneSid; Privileges->PrivilegeCount = PRIVILEGE_COUNT; Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege; Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege; Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION); ASSERT(NT_SUCCESS(Status) ); Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &ImpersonationTokenAttributes, // ObjectAttributes TokenImpersonation, // TokenType &SystemAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges &Owner, // Owner &PrimaryGroup, // Primary Group &DefaultDacl, // Default Dacl &TestSource // TokenSource ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtDuplicateObject( NtCurrentProcess(), // SourceProcessHandle Token, // SourceHandle NtCurrentProcess(), // TargetProcessHandle &ImpersonationToken, // TargetHandle 0, // DesiredAccess (over-ridden by option) 0, // HandleAttributes DUPLICATE_SAME_ACCESS // Options ); ASSERT(NT_SUCCESS(Status)); Status = NtClose(Token); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Create an impersonation token, Impersonation level = Anonymous // DbgPrint("Se: Create an anonymous token ... "); GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid; GroupIds->Groups[CHILD_INDEX].Sid = ChildSid; GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid; GroupIds->Groups[WORLD_INDEX].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Owner.Owner = FlintstoneSid; Privileges->PrivilegeCount = PRIVILEGE_COUNT; Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege; Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege; Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION); ASSERT(NT_SUCCESS(Status) ); Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &AnonymousTokenAttributes, // ObjectAttributes TokenImpersonation, // TokenType &OriginalAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges &Owner, // Owner &PrimaryGroup, // Primary Group &DefaultDacl, // Default Dacl &TestSource // TokenSource ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtDuplicateObject( NtCurrentProcess(), // SourceProcessHandle Token, // SourceHandle NtCurrentProcess(), // TargetProcessHandle &AnonymousToken, // TargetHandle 0, // DesiredAccess (over-ridden by option) 0, // HandleAttributes DUPLICATE_SAME_ACCESS // Options ); ASSERT(NT_SUCCESS(Status)); Status = NtClose(Token); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Create the simplest token possible // (no Groups, explicit Owner, or DefaultDacl) // DbgPrint("Se: Create Token With Bad Authentication Id ... "); UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; GroupIds->GroupCount = 0; Privileges->PrivilegeCount = 0; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &BadAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges NULL, // Owner &PrimaryGroup, // Primary Group NULL, // Default Dacl &TestSource // TokenSource ); if (Status == STATUS_NO_SUCH_LOGON_SESSION) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Status should be: 0x%lx \n", STATUS_NO_SUCH_LOGON_SESSION); CompletionStatus = FALSE; } // // All done with this test // return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Open Primary Token Test // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenOpenPrimary() { NTSTATUS Status; BOOLEAN CompletionStatus = TRUE; HANDLE ProcessToken; HANDLE SubProcessToken; HANDLE SubProcess; TOKEN_STATISTICS ProcessTokenStatistics; TOKEN_STATISTICS SubProcessTokenStatistics; ULONG ReturnLength; DbgPrint("\n"); // // Open the current process's token // DbgPrint("Se: Open own process's token ... "); Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_ALL_ACCESS, &ProcessToken ); if (NT_SUCCESS(Status)) { Status = NtQueryInformationToken( ProcessToken, // Handle TokenStatistics, // TokenInformationClass &ProcessTokenStatistics, // TokenInformation sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); if ( ProcessTokenStatistics.TokenType == TokenPrimary) { if ( RtlEqualLuid( &ProcessTokenStatistics.AuthenticationId, &OriginalAuthenticationId ) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected authentication ID value.\n"); DbgPrint("Authentication ID is: "); TestpPrintLuid(ProcessTokenStatistics.AuthenticationId); DbgPrint("\n"); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Token type not TokenPrimary.\n"); DbgPrint("Returned token type is: 0x%lx \n", ProcessTokenStatistics.TokenType); DbgPrint("Authentication ID is: "); TestpPrintLuid(ProcessTokenStatistics.AuthenticationId); DbgPrint("\n"); CompletionStatus = FALSE; } Status = NtClose(ProcessToken); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } // // Open another process's token // DbgPrint("Se: Open another process's token ... "); Status = NtCreateProcess( &SubProcess, (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE), NULL, NtCurrentProcess(), // ParentProcess FALSE, // InheritObjectTable NULL, // SectionHandle, NULL, // DebugPort, NULL // ExceptionPort ); Status = NtOpenProcessToken( SubProcess, TOKEN_ALL_ACCESS, &SubProcessToken ); if (NT_SUCCESS(Status)) { Status = NtQueryInformationToken( SubProcessToken, // Handle TokenStatistics, // TokenInformationClass &SubProcessTokenStatistics, // TokenInformation sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); if ( SubProcessTokenStatistics.TokenType == TokenPrimary) { if ( RtlEqualLuid( &SubProcessTokenStatistics.AuthenticationId, &OriginalAuthenticationId ) ) { if ( (ProcessTokenStatistics.TokenId.HighPart == SubProcessTokenStatistics.TokenId.HighPart) && (ProcessTokenStatistics.TokenId.LowPart == SubProcessTokenStatistics.TokenId.LowPart) ) { DbgPrint("********** Failed ************\n"); DbgPrint("Same token as parent process (token IDs match).\n"); DbgPrint("Authentication ID is: "); TestpPrintLuid(SubProcessTokenStatistics.AuthenticationId); DbgPrint("\n"); CompletionStatus = FALSE; } else { DbgPrint("Succeeded.\n"); } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected authentication ID value.\n"); DbgPrint("Authentication ID is: "); TestpPrintLuid(SubProcessTokenStatistics.AuthenticationId); DbgPrint("\n"); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Token type not TokenPrimary.\n"); DbgPrint("Returned token type is: 0x%lx \n", SubProcessTokenStatistics.TokenType); DbgPrint("Authentication ID is: "); TestpPrintLuid(SubProcessTokenStatistics.AuthenticationId); DbgPrint("\n"); CompletionStatus = FALSE; } Status = NtClose(SubProcessToken); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Query Token Test // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenQuery() { BOOLEAN CompletionStatus = TRUE; ULONG ReturnLength; BOOLEAN ValuesCompare; PTOKEN_USER UserId; PTOKEN_PRIMARY_GROUP PrimaryGroup; PTOKEN_GROUPS GroupIds; PTOKEN_PRIVILEGES Privileges; PTOKEN_OWNER Owner; PTOKEN_DEFAULT_DACL DefaultDacl; SECURITY_IMPERSONATION_LEVEL QueriedImpersonationLevel; TOKEN_SOURCE QueriedSource; TOKEN_TYPE QueriedType; TOKEN_STATISTICS QueriedStatistics; DbgPrint("\n"); #if 0 // // Query invalid return buffer address // DbgPrint("Se: Query with invalid buffer address ... "); UserId = (PTOKEN_USER)((PVOID)0x200L); Status = NtQueryInformationToken( SimpleToken, // Handle TokenUser, // TokenInformationClass UserId, // TokenInformation 3000, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_ACCESS_VIOLATION) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); #endif //0 //////////////////////////////////////////////////////////////////////// // // // Query User ID // // // //////////////////////////////////////////////////////////////////////// // // Query User ID with zero length buffer // DbgPrint("Se: Query User ID with zero length buffer ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenUser, // TokenInformationClass UserId, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); UserId = (PTOKEN_USER)TstAllocatePool( PagedPool, ReturnLength ); // // Query user SID // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query token user ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenUser, // TokenInformationClass UserId, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // if (RtlEqualSid((UserId->User.Sid), PebblesSid) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query user with too small buffer ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenUser, // TokenInformationClass UserId, // TokenInformation ReturnLength-1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); //////////////////////////////////////////////////////////////////////// // // // Query Primary Group // // // //////////////////////////////////////////////////////////////////////// // // Query primary group with zero length buffer // DbgPrint("Se: Query primary group with zero length buffer ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenPrimaryGroup, // TokenInformationClass PrimaryGroup, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); PrimaryGroup = (PTOKEN_PRIMARY_GROUP)TstAllocatePool( PagedPool, ReturnLength ); // // Query primary group SID // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query primary group ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenPrimaryGroup, // TokenInformationClass PrimaryGroup, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // if (RtlEqualSid( PrimaryGroup->PrimaryGroup, FlintstoneSid) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query primary group with too small buffer ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenPrimaryGroup, // TokenInformationClass PrimaryGroup, // TokenInformation ReturnLength-1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); //////////////////////////////////////////////////////////////////////// // // // Query Groups // // // //////////////////////////////////////////////////////////////////////// // // Query groups with zero length buffer // DbgPrint("Se: Query groups with zero length buffer ... "); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenGroups, // TokenInformationClass GroupIds, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool, ReturnLength ); // // Query Group SIDs // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query groups ... "); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenGroups, // TokenInformationClass GroupIds, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // Group count = 4 // SID 0 = Flintstone // SID 1 = ChildSid // SID 2 = NeandertholSid // SID 3 = WorldSid // ValuesCompare = TRUE; if (GroupIds->GroupCount != GROUP_COUNT) { ValuesCompare = FALSE; } if ( (!RtlEqualSid((GroupIds->Groups[FLINTSTONE_INDEX].Sid), FlintstoneSid)) || (GroupIds->Groups[FLINTSTONE_INDEX].Attributes != OwnerGroupAttributes) ) { ValuesCompare = FALSE; } if ( (!RtlEqualSid((GroupIds->Groups[CHILD_INDEX].Sid), ChildSid)) || (GroupIds->Groups[CHILD_INDEX].Attributes != OptionalGroupAttributes) ) { ValuesCompare = FALSE; } if ( (!RtlEqualSid((GroupIds->Groups[NEANDERTHOL_INDEX].Sid), NeandertholSid)) || (GroupIds->Groups[NEANDERTHOL_INDEX].Attributes != OptionalGroupAttributes) ) { ValuesCompare = FALSE; } if ( (!RtlEqualSid((GroupIds->Groups[WORLD_INDEX].Sid), WorldSid)) || (GroupIds->Groups[WORLD_INDEX].Attributes != NormalGroupAttributes) ) { ValuesCompare = FALSE; } if ( ValuesCompare ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); DbgPrint("Returned group count is: 0x%lx \n", GroupIds->GroupCount); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query groups with too small buffer ... "); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenGroups, // TokenInformationClass GroupIds, // TokenInformation ReturnLength-1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); //////////////////////////////////////////////////////////////////////// // // // Query Privileges // // // //////////////////////////////////////////////////////////////////////// // // Query groups with zero length buffer // DbgPrint("Se: Query privileges with zero length buffer ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenPrivileges, // TokenInformationClass NULL, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool, ReturnLength ); // // Query privileges // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query privileges ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenPrivileges, // TokenInformationClass Privileges, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // Privilege count = PRIVILEGE_COUNT // Privilege UNSOLICITED_INDEX = UnsolicitedInputPrivilege // Privilege SECURITY_INDEX = SecurityPrivilege // Privilege ASSIGN_PRIMARY_INDEX = AssignPrimaryPrivilege // ValuesCompare = TRUE; if (Privileges->PrivilegeCount != PRIVILEGE_COUNT) { ValuesCompare = FALSE; } if ( !(Privileges->Privileges[UNSOLICITED_INDEX].Luid.QuadPart == UnsolicitedInputPrivilege.QuadPart) || (Privileges->Privileges[UNSOLICITED_INDEX].Attributes != 0) ) { ValuesCompare = FALSE; } if ( !(Privileges->Privileges[SECURITY_INDEX].Luid.QuadPart == SecurityPrivilege.QuadPart) || (Privileges->Privileges[SECURITY_INDEX].Attributes != 0) ) { ValuesCompare = FALSE; } if ( !(Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid.QuadPart == AssignPrimaryTokenPrivilege.QuadPart) || (Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes != SE_PRIVILEGE_ENABLED) ) { ValuesCompare = FALSE; } if ( ValuesCompare ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query privileges with too small buffer ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenPrivileges, // TokenInformationClass Privileges, // TokenInformation ReturnLength-1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); //////////////////////////////////////////////////////////////////////// // // // Query Owner // // // //////////////////////////////////////////////////////////////////////// // // Query Owner of simple token with zero length buffer // DbgPrint("Se: Query Owner of simple token with zero length buffer... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenOwner, // TokenInformationClass Owner, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); Owner = (PTOKEN_OWNER)TstAllocatePool( PagedPool, ReturnLength ); // // Query Owner SID // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query owner of simple token ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenOwner, // TokenInformationClass Owner, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // if (RtlEqualSid((Owner->Owner), PebblesSid) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query owner of simple token with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query owner of simple token with too small buffer ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenOwner, // TokenInformationClass Owner, // TokenInformation ReturnLength-1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); // // Query default owner of token with zero length buffer // DbgPrint("Se: Query Default Owner of token with zero length buffer..."); Status = NtQueryInformationToken( TokenWithDefaultOwner, // Handle TokenOwner, // TokenInformationClass Owner, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); Owner = (PTOKEN_OWNER)TstAllocatePool( PagedPool, ReturnLength ); // // Query default owner of token // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query default owner of token ... "); Status = NtQueryInformationToken( TokenWithDefaultOwner, // Handle TokenOwner, // TokenInformationClass Owner, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // if (RtlEqualSid((Owner->Owner), FlintstoneSid) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query default owner of token with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query default owner of token with too small buffer ... "); Status = NtQueryInformationToken( TokenWithDefaultOwner, // Handle TokenOwner, // TokenInformationClass Owner, // TokenInformation ReturnLength-1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); //////////////////////////////////////////////////////////////////////// // // // Query Default Dacl // // // //////////////////////////////////////////////////////////////////////// // // Query default dacl with zero length buffer // DbgPrint("Se: Query default DACL with zero length buffer ... "); Status = NtQueryInformationToken( TokenWithDefaultDacl, // Handle TokenDefaultDacl, // TokenInformationClass DefaultDacl, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); DefaultDacl = (PTOKEN_DEFAULT_DACL)TstAllocatePool( PagedPool, ReturnLength ); // // Query default dacl // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query default dacl ... "); Status = NtQueryInformationToken( TokenWithDefaultDacl, // Handle TokenDefaultDacl, // TokenInformationClass DefaultDacl, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // if (RtlValidAcl(DefaultDacl->DefaultDacl)) { if (DefaultDacl->DefaultDacl->AceCount == 0) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query default Dacl with too small buffer ... "); Status = NtQueryInformationToken( TokenWithDefaultDacl, // Handle TokenDefaultDacl, // TokenInformationClass DefaultDacl, // TokenInformation ReturnLength-1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); // // Query token with no default dacl // DbgPrint("Se: Query default dacl from token with none ... "); Status = NtQueryInformationToken( SimpleToken, // Handle TokenDefaultDacl, // TokenInformationClass DefaultDacl, // TokenInformation sizeof(TOKEN_DEFAULT_DACL), // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); //////////////////////////////////////////////////////////////////////// // // // Query Token Source // // // //////////////////////////////////////////////////////////////////////// // // Query Token Source with zero length buffer // DbgPrint("Se: Query Token Source with zero length buffer ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenSource, // TokenInformationClass &QueriedSource, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { if (ReturnLength == sizeof(TOKEN_SOURCE)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); DbgPrint("TOKEN_SOURCE data size is 0x%lx \n", sizeof(TOKEN_SOURCE)); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); // // Query token source // DbgPrint("Se: Query token source ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenSource, // TokenInformationClass &QueriedSource, // TokenInformation sizeof(TOKEN_SOURCE), // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value against TestSource // ValuesCompare = TRUE; if ( (QueriedSource.SourceName[0] != TestSource.SourceName[0]) || (QueriedSource.SourceName[1] != TestSource.SourceName[1]) || (QueriedSource.SourceName[2] != TestSource.SourceName[2]) || (QueriedSource.SourceName[3] != TestSource.SourceName[3]) || (QueriedSource.SourceName[4] != TestSource.SourceName[4]) || (QueriedSource.SourceName[5] != TestSource.SourceName[5]) || (QueriedSource.SourceName[6] != TestSource.SourceName[6]) || (QueriedSource.SourceName[7] != TestSource.SourceName[7]) ) { ValuesCompare = FALSE; } if ( !(QueriedSource.SourceIdentifier.QuadPart == TestSource.SourceIdentifier.QuadPart) ) { ValuesCompare = FALSE; } if ( ValuesCompare ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query token source with too small buffer ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenSource, // TokenInformationClass &QueriedSource, // TokenInformation ReturnLength - 1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); //////////////////////////////////////////////////////////////////////// // // // Query Token Type // // // //////////////////////////////////////////////////////////////////////// // // Query Token type with zero length buffer // DbgPrint("Se: Query Token type with zero length buffer ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenType, // TokenInformationClass &QueriedType, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { if (ReturnLength == sizeof(TOKEN_TYPE)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); DbgPrint("TOKEN_TYPE data size is 0x%lx \n", sizeof(TOKEN_TYPE)); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); // // Query token type // DbgPrint("Se: Query token type ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenType, // TokenInformationClass &QueriedType, // TokenInformation sizeof(TOKEN_TYPE), // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value against TestSource // if ( QueriedType == TokenPrimary ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); DbgPrint("Returned token type is: 0x%lx \n", QueriedType); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query token type with too small buffer ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenType, // TokenInformationClass &QueriedType, // TokenInformation ReturnLength - 1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); //////////////////////////////////////////////////////////////////////// // // // Query Impersonation Level // // // //////////////////////////////////////////////////////////////////////// // // Query Impersonation Level of primary token // DbgPrint("Se: Query Impersonation level of primary token ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenImpersonationLevel, // TokenInformationClass &QueriedImpersonationLevel, // TokenInformation sizeof(SECURITY_IMPERSONATION_LEVEL), // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_INVALID_INFO_CLASS) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_INVALID_INFO_CLASS); //////////////////////////////////////////////////////////////////////// // // // Query Token Statistics // // // //////////////////////////////////////////////////////////////////////// // // Query Token statistics with zero length buffer // DbgPrint("Se: Query Token statistics with zero length buffer ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenStatistics, // TokenInformationClass &QueriedStatistics, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { if (ReturnLength == sizeof(TOKEN_STATISTICS)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); DbgPrint("TOKEN_STATISTICS data size is 0x%lx \n", sizeof(TOKEN_STATISTICS)); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); // // Query token statistics // DbgPrint("Se: Query token statistics ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenStatistics, // TokenInformationClass &QueriedStatistics, // TokenInformation sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value against TestSource // if ( ( QueriedStatistics.TokenType == TokenPrimary) && ( QueriedStatistics.GroupCount == 4 ) && ( QueriedStatistics.PrivilegeCount == PRIVILEGE_COUNT) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); DbgPrint("Returned token type is: 0x%lx \n", QueriedStatistics.TokenType); DbgPrint("Returned group count is: 0x%lx \n", QueriedStatistics.GroupCount); DbgPrint("Returned privilege count is: 0x%lx \n", QueriedStatistics.PrivilegeCount); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query with too little buffer // (This relies upon the ReturnLength returned from previous call) // DbgPrint("Se: Query token statistics with too small buffer ... "); Status = NtQueryInformationToken( TokenWithPrivileges, // Handle TokenStatistics, // TokenInformationClass &QueriedStatistics, // TokenInformation ReturnLength - 1, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Set Token Test // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenSet() { BOOLEAN CompletionStatus = TRUE; ULONG InformationLength; ULONG ReturnLength; TOKEN_STATISTICS QueriedStatistics; TOKEN_PRIMARY_GROUP AssignedPrimaryGroup; PTOKEN_PRIMARY_GROUP QueriedPrimaryGroup; TOKEN_OWNER AssignedOwner; PTOKEN_OWNER QueriedOwner; TOKEN_DEFAULT_DACL AssignedDefaultDacl; PTOKEN_DEFAULT_DACL QueriedDefaultDacl; PSID TooBigSid; SID_IDENTIFIER_AUTHORITY BedrockAuthority = BEDROCK_AUTHORITY; DbgPrint("\n"); // // Set owner of a token to be an invalid group // DbgPrint("Se: Set default owner to be an invalid group ... "); AssignedOwner.Owner = NeandertholSid; InformationLength = (ULONG)sizeof(TOKEN_OWNER); Status = NtSetInformationToken( TokenWithGroups, // Handle TokenOwner, // TokenInformationClass &AssignedOwner, // TokenInformation InformationLength // TokenInformationLength ); if (Status == STATUS_INVALID_OWNER) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("InformationLength is: 0x%lx \n", InformationLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_INVALID_OWNER); // // Set owner of a token to be an ID not in the token // DbgPrint("Se: Set default owner to be an ID not in the token ... "); AssignedOwner.Owner = BarneySid; InformationLength = (ULONG)sizeof(TOKEN_OWNER); Status = NtSetInformationToken( TokenWithGroups, // Handle TokenOwner, // TokenInformationClass &AssignedOwner, // TokenInformation InformationLength // TokenInformationLength ); if (Status == STATUS_INVALID_OWNER) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("InformationLength is: 0x%lx \n", InformationLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_INVALID_OWNER); // // Set owner of a token to be a valid group // DbgPrint("Se: Set default owner to be a valid group ... "); AssignedOwner.Owner = FlintstoneSid; InformationLength = (ULONG)sizeof(TOKEN_OWNER); Status = NtSetInformationToken( TokenWithGroups, // Handle TokenOwner, // TokenInformationClass &AssignedOwner, // TokenInformation InformationLength // TokenInformationLength ); if (!NT_SUCCESS(Status)) { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("InformationLength is: 0x%lx \n", InformationLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query the Owner to see that it was set properly // Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenOwner, // TokenInformationClass QueriedOwner, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status != STATUS_BUFFER_TOO_SMALL) { DbgPrint("********** Failed Query of length ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); QueriedOwner = (PTOKEN_OWNER)TstAllocatePool( PagedPool, ReturnLength ); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenOwner, // TokenInformationClass QueriedOwner, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // if (RtlEqualSid((QueriedOwner->Owner), AssignedOwner.Owner) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed Comparison ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed Query Of Value ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Set Default Dacl // // Get a buffer for use in all Default Dacl assignment tests. // This will be initialized to different sizes for each test. // AssignedDefaultDacl.DefaultDacl = (PACL)TstAllocatePool( PagedPool, TOO_BIG_ACL_SIZE ); // // Assign a discretionary ACL to a token that doesn't yet have one // DbgPrint("Se: Set original discretionary ACL in token ... "); InformationLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL); RtlCreateAcl( AssignedDefaultDacl.DefaultDacl, 200, ACL_REVISION ); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenDefaultDacl, // TokenInformationClass &QueriedDefaultDacl, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(Status == STATUS_BUFFER_TOO_SMALL); if (ReturnLength != sizeof(TOKEN_DEFAULT_DACL)) { // // Wait a minute, this token has a default Dacl // DbgPrint("******** Failed - token has default dacl *********\n"); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } else { Status = NtSetInformationToken( TokenWithGroups, // Handle TokenDefaultDacl, // TokenInformationClass &AssignedDefaultDacl, // TokenInformation InformationLength // TokenInformationLength ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } } ASSERT(NT_SUCCESS(Status)); // // Replace a discretionary ACL in a token that already has one // Make it big to help with future "too big" tests... // // // find out how much space is available // Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenStatistics, // TokenInformationClass &QueriedStatistics, // TokenInformation (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(Status)); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenDefaultDacl, // TokenInformationClass &QueriedDefaultDacl, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(Status == STATUS_BUFFER_TOO_SMALL); if (ReturnLength > sizeof(TOKEN_STATISTICS)) { CurrentLength = ReturnLength - (ULONG)sizeof(TOKEN_STATISTICS); } else { CurrentLength = 0; } LengthAvailable = QueriedStatistics.DynamicAvailable + CurrentLength; DbgPrint("Se: Replace discretionary ACL in token ... "); InformationLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL); RtlCreateAcl( AssignedDefaultDacl.DefaultDacl, (ULONG)(LengthAvailable - 50), ACL_REVISION ); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenDefaultDacl, // TokenInformationClass &QueriedDefaultDacl, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (!(ReturnLength > sizeof(TOKEN_DEFAULT_DACL))) { // // Wait a minute, this token doesn't have a default Dacl // DbgPrint("******** Failed - No default dacl *********\n"); CompletionStatus = FALSE; } else { Status = NtSetInformationToken( TokenWithGroups, // Handle TokenDefaultDacl, // TokenInformationClass &AssignedDefaultDacl, // TokenInformation InformationLength // TokenInformationLength ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } } ASSERT(NT_SUCCESS(Status)); // // Assign a discretionary ACL that doesn't fit into the dynamic part of the // token. // // // find out how much space is available // Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenStatistics, // TokenInformationClass &QueriedStatistics, // TokenInformation (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(Status)); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenDefaultDacl, // TokenInformationClass &QueriedDefaultDacl, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(Status == STATUS_BUFFER_TOO_SMALL); if (ReturnLength > sizeof(TOKEN_STATISTICS)) { CurrentLength = ReturnLength - (ULONG)sizeof(TOKEN_STATISTICS); } else { CurrentLength = 0; } LengthAvailable = QueriedStatistics.DynamicAvailable + CurrentLength; DbgPrint("Se: Set too big discretionary ACL ... "); // // Now make sure our ACL is large enough to exceed the available // space. // RtlCreateAcl( AssignedDefaultDacl.DefaultDacl, TOO_BIG_ACL_SIZE, ACL_REVISION ); if (TOO_BIG_ACL_SIZE < LengthAvailable) { DbgPrint("********** Failed - Dynamic too big ************\n"); DbgPrint("Dynamic available is: 0x%lx \n", QueriedStatistics.DynamicAvailable); DbgPrint("Current default Dacl size is: 0x%lx \n", CurrentLength); DbgPrint("Big ACL size is: 0x%lx \n", TOO_BIG_ACL_SIZE); CompletionStatus = FALSE; } InformationLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL); Status = NtSetInformationToken( TokenWithGroups, // Handle TokenDefaultDacl, // TokenInformationClass &AssignedDefaultDacl, // TokenInformation InformationLength // TokenInformationLength ); if (Status == STATUS_ALLOTTED_SPACE_EXCEEDED) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Dynamic available is: 0x%lx \n", QueriedStatistics.DynamicAvailable); DbgPrint("Current default Dacl size is: 0x%lx \n", CurrentLength); DbgPrint("Big ACL size is: 0x%lx \n", TOO_BIG_ACL_SIZE); CompletionStatus = FALSE; } ASSERT(Status == STATUS_ALLOTTED_SPACE_EXCEEDED); // // Set primary group // DbgPrint("Se: Set primary group ... "); AssignedPrimaryGroup.PrimaryGroup = RubbleSid; InformationLength = (ULONG)sizeof(TOKEN_PRIMARY_GROUP); Status = NtSetInformationToken( TokenWithGroups, // Handle TokenPrimaryGroup, // TokenInformationClass &AssignedPrimaryGroup, // TokenInformation InformationLength // TokenInformationLength ); if (!NT_SUCCESS(Status)) { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("InformationLength is: 0x%lx \n", InformationLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Query the Primary Group to see that it was set properly // Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenPrimaryGroup, // TokenInformationClass QueriedPrimaryGroup, // TokenInformation 0, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status != STATUS_BUFFER_TOO_SMALL) { DbgPrint("********** Failed Query of length ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(!NT_SUCCESS(Status)); QueriedPrimaryGroup = (PTOKEN_PRIMARY_GROUP)TstAllocatePool( PagedPool, ReturnLength ); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenPrimaryGroup, // TokenInformationClass QueriedPrimaryGroup, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (NT_SUCCESS(Status)) { // // Check returned value // if (RtlEqualSid((QueriedPrimaryGroup->PrimaryGroup), AssignedPrimaryGroup.PrimaryGroup) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed Comparison ************\n"); DbgPrint("Unexpected value returned by query.\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed Query Of Value ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Required return length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Assign a primary group that doesn't fit into the dynamic part of the // token. // DbgPrint("Se: Set too big primary group ... "); // // First, find out how much space is available // Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenStatistics, // TokenInformationClass &QueriedStatistics, // TokenInformation (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(Status)); Status = NtQueryInformationToken( TokenWithGroups, // Handle TokenPrimaryGroup, // TokenInformationClass QueriedPrimaryGroup, // TokenInformation ReturnLength, // TokenInformationLength &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(Status)); CurrentLength = SeLengthSid(QueriedPrimaryGroup->PrimaryGroup); LengthAvailable = QueriedStatistics.DynamicAvailable + CurrentLength; // // Now make sure our fake group ID is large enough to exceed the available // space. // TooBigSid = (PSID)TstAllocatePool( PagedPool, RtlLengthRequiredSid( TOO_BIG_PRIMARY_GROUP_SIZE ) ); RtlInitializeSid( TooBigSid, &BedrockAuthority, TOO_BIG_PRIMARY_GROUP_SIZE ); if (SeLengthSid(TooBigSid) < LengthAvailable) { DbgPrint("********** Failed - Dynamic too big ************\n"); DbgPrint("Dynamic available is: 0x%lx \n", QueriedStatistics.DynamicAvailable); DbgPrint("Existing primary group length is: 0x%lx \n", CurrentLength); DbgPrint("Big SID size is: 0x%lx \n", SeLengthSid(TooBigSid)); CompletionStatus = FALSE; } AssignedPrimaryGroup.PrimaryGroup = TooBigSid; InformationLength = (ULONG)sizeof(TOKEN_PRIMARY_GROUP); Status = NtSetInformationToken( TokenWithGroups, // Handle TokenPrimaryGroup, // TokenInformationClass &AssignedPrimaryGroup, // TokenInformation InformationLength // TokenInformationLength ); if (Status == STATUS_ALLOTTED_SPACE_EXCEEDED) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Dynamic available is: 0x%lx \n", QueriedStatistics.DynamicAvailable); DbgPrint("Existing primary group length is: 0x%lx \n", CurrentLength); DbgPrint("Big SID size is: 0x%lx \n", SeLengthSid(TooBigSid)); CompletionStatus = FALSE; } ASSERT(Status == STATUS_ALLOTTED_SPACE_EXCEEDED); return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Adjust Privileges Test // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenAdjustPrivileges() { BOOLEAN CompletionStatus = TRUE; NTSTATUS Status; NTSTATUS IgnoreStatus; PTOKEN_PRIVILEGES NewState; PTOKEN_PRIVILEGES PreviousState; PTOKEN_PRIVILEGES PrePrivileges; PTOKEN_PRIVILEGES PostPrivileges; ULONG NewStateBufferLength = 200; ULONG PreviousStateBufferLength = 200; ULONG PrePrivilegesLength = 200; ULONG PostPrivilegesLength = 200; ULONG ReturnLength; ULONG IgnoreReturnLength; DbgPrint("\n"); PreviousState = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool, PreviousStateBufferLength ); PrePrivileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool, PrePrivilegesLength ); PostPrivileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool, PostPrivilegesLength ); NewState = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool, NewStateBufferLength ); ////////////////////////////////////////////////////////////////////// // // // Adjust privileges giving no instructions // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Adjust privileges with no instructions ... "); Status = NtAdjustPrivilegesToken( SimpleToken, // TokenHandle FALSE, // DisableAllPrivileges NULL, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); if (Status == STATUS_INVALID_PARAMETER) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_INVALID_PARAMETER); ////////////////////////////////////////////////////////////////////// // // // Enable privileges in token with no privileges // // // ////////////////////////////////////////////////////////////////////// NewState->PrivilegeCount = 1; NewState->Privileges[0].Luid = SecurityPrivilege; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; DbgPrint("Se: Enable privilege in token with none ... "); Status = NtAdjustPrivilegesToken( SimpleToken, // TokenHandle FALSE, // DisableAllPrivileges NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); if (Status == STATUS_NOT_ALL_ASSIGNED) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_NOT_ALL_ASSIGNED); ////////////////////////////////////////////////////////////////////// // // // Enable a privilege that isn't assigned // // // ////////////////////////////////////////////////////////////////////// NewState->PrivilegeCount = 1; NewState->Privileges[0].Luid = CreateTokenPrivilege; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; DbgPrint("Se: Enable unassigned privilege in token with some ... "); PrePrivileges->PrivilegeCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PrePrivileges, // TokenInformation PrePrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT(NT_SUCCESS(IgnoreStatus) ); Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle FALSE, // DisableAllPrivileges NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostPrivileges->PrivilegeCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PostPrivileges, // TokenInformation PostPrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_NOT_ALL_ASSIGNED) { // // Check the privilege values // if ( (PrePrivileges->Privileges[0].Attributes == PostPrivileges->Privileges[0].Attributes) && (PrePrivileges->Privileges[1].Attributes == PostPrivileges->Privileges[1].Attributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[0].Attributes, PostPrivileges->Privileges[0].Attributes); DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[1].Attributes, PostPrivileges->Privileges[1].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_NOT_ALL_ASSIGNED); ////////////////////////////////////////////////////////////////////// // // // Disable All Privileges (which they already are) // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable already disabled privileges ... "); PrePrivileges->PrivilegeCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PrePrivileges, // TokenInformation PrePrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT( PrePrivileges->Privileges[0].Attributes == 0 ); ASSERT( PrePrivileges->Privileges[1].Attributes == 0 ); ASSERT(NT_SUCCESS(IgnoreStatus) ); Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle TRUE, // DisableAllPrivileges NULL, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostPrivileges->PrivilegeCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PostPrivileges, // TokenInformation PostPrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the privilege values // if ( (PostPrivileges->Privileges[0].Attributes == 0) && (PostPrivileges->Privileges[1].Attributes == 0) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[0].Attributes, PostPrivileges->Privileges[0].Attributes); DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[1].Attributes, PostPrivileges->Privileges[1].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ////////////////////////////////////////////////////////////////////// // // // Enable currently disabled privileges // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable currently disabled privileges ... "); PrePrivileges->PrivilegeCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PrePrivileges, // TokenInformation PrePrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT( PrePrivileges->Privileges[0].Attributes == 0 ); ASSERT( PrePrivileges->Privileges[1].Attributes == 0 ); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->PrivilegeCount = 2; NewState->Privileges[0].Luid = SecurityPrivilege; NewState->Privileges[1].Luid = UnsolicitedInputPrivilege; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle FALSE, // DisableAllPrivileges NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostPrivileges->PrivilegeCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PostPrivileges, // TokenInformation PostPrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the privilege values // if ( (PostPrivileges->Privileges[0].Attributes == SE_PRIVILEGE_ENABLED) && (PostPrivileges->Privileges[1].Attributes == SE_PRIVILEGE_ENABLED) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[0].Attributes, PostPrivileges->Privileges[0].Attributes); DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[1].Attributes, PostPrivileges->Privileges[1].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ////////////////////////////////////////////////////////////////////// // // // Disable all enabled privileges // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable all enabled privileges ... "); PrePrivileges->PrivilegeCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PrePrivileges, // TokenInformation PrePrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT( PrePrivileges->Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ); ASSERT( PrePrivileges->Privileges[1].Attributes == SE_PRIVILEGE_ENABLED ); ASSERT(NT_SUCCESS(IgnoreStatus) ); Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle TRUE, // DisableAllPrivileges NULL, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostPrivileges->PrivilegeCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PostPrivileges, // TokenInformation PostPrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the privilege values // if ( (PostPrivileges->Privileges[0].Attributes == 0) && (PostPrivileges->Privileges[1].Attributes == 0) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[0].Attributes, PostPrivileges->Privileges[0].Attributes); DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[1].Attributes, PostPrivileges->Privileges[1].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ////////////////////////////////////////////////////////////////////// // // // Enable privileges requesting previous state with no return // // length buffer // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: PreviousState not NULL, ReturnLength NULL... "); NewState->PrivilegeCount = 2; NewState->Privileges[0].Luid = SecurityPrivilege; NewState->Privileges[1].Luid = UnsolicitedInputPrivilege; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle FALSE, // DisableAllPrivileges NewState, // NewState (OPTIONAL) 0, // BufferLength PreviousState, // PreviousState (OPTIONAL) NULL // ReturnLength ); if (Status == STATUS_ACCESS_VIOLATION) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(Status == STATUS_ACCESS_VIOLATION); ////////////////////////////////////////////////////////////////////// // // // Enable privileges without requesting previous state and // // providing no return length buffer // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: PreviousState and ReturnLength both NULL... "); NewState->PrivilegeCount = 2; NewState->Privileges[0].Luid = SecurityPrivilege; NewState->Privileges[1].Luid = UnsolicitedInputPrivilege; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle FALSE, // DisableAllPrivileges NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) NULL // ReturnLength ); if (Status == STATUS_SUCCESS) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ////////////////////////////////////////////////////////////////////// // // // Enable privileges requesting previous state with insufficient // // buffer // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Too small buffer for previous state ... "); // // Establish a known previous state first... // Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle TRUE, // DisableAllPrivileges NULL, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); NewState->PrivilegeCount = 2; NewState->Privileges[0].Luid = SecurityPrivilege; NewState->Privileges[1].Luid = UnsolicitedInputPrivilege; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle FALSE, // DisableAllPrivileges NewState, // NewState (OPTIONAL) 0, // BufferLength PreviousState, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG if (Status == STATUS_BUFFER_TOO_SMALL) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_BUFFER_TOO_SMALL); ////////////////////////////////////////////////////////////////////// // // // Enable one of the privileges requesting previous state // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable one requesting previous state ... "); PrePrivileges->PrivilegeCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PrePrivileges, // TokenInformation PrePrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT( PrePrivileges->Privileges[0].Attributes == 0 ); ASSERT( PrePrivileges->Privileges[1].Attributes == 0 ); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->PrivilegeCount = 1; NewState->Privileges[0].Luid = SecurityPrivilege; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle FALSE, // DisableAllPrivileges NewState, // NewState (OPTIONAL) PreviousStateBufferLength, // BufferLength PreviousState, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(Status)); ASSERT(PreviousState->PrivilegeCount == 1); PostPrivileges->PrivilegeCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PostPrivileges, // TokenInformation PostPrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the privilege values // if ( (PostPrivileges->Privileges[SECURITY_INDEX].Attributes == SE_PRIVILEGE_ENABLED) && (PostPrivileges->Privileges[UNSOLICITED_INDEX].Attributes == 0) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[0].Attributes, PostPrivileges->Privileges[0].Attributes); DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[1].Attributes, PostPrivileges->Privileges[1].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); DbgPrint("Change Count is: 0x%lx \n", PreviousState->PrivilegeCount); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ////////////////////////////////////////////////////////////////////// // // // Enable the other privilege requesting previous state // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable one requesting previous state ... "); PrePrivileges->PrivilegeCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PrePrivileges, // TokenInformation PrePrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT( PrePrivileges->Privileges[SECURITY_INDEX].Attributes == SE_PRIVILEGE_ENABLED ); ASSERT( PrePrivileges->Privileges[UNSOLICITED_INDEX].Attributes == 0 ); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->PrivilegeCount = 1; NewState->Privileges[0].Luid = UnsolicitedInputPrivilege; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle FALSE, // DisableAllPrivileges NewState, // NewState (OPTIONAL) PreviousStateBufferLength, // BufferLength PreviousState, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(Status)); ASSERT(PreviousState->PrivilegeCount == 1); PostPrivileges->PrivilegeCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PostPrivileges, // TokenInformation PostPrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the privilege values // if ( (PostPrivileges->Privileges[0].Attributes == SE_PRIVILEGE_ENABLED) && (PostPrivileges->Privileges[1].Attributes == SE_PRIVILEGE_ENABLED) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[0].Attributes, PostPrivileges->Privileges[0].Attributes); DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[1].Attributes, PostPrivileges->Privileges[1].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); DbgPrint("Change Count is: 0x%lx \n", PreviousState->PrivilegeCount); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ////////////////////////////////////////////////////////////////////// // // // Return privileges to their previous state // // Uses PreviousState from previous call // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Return privileges to previous state ... "); PrePrivileges->PrivilegeCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PrePrivileges, // TokenInformation PrePrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT( PrePrivileges->Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ); ASSERT( PrePrivileges->Privileges[1].Attributes == SE_PRIVILEGE_ENABLED ); ASSERT(NT_SUCCESS(IgnoreStatus) ); Status = NtAdjustPrivilegesToken( TokenWithPrivileges, // TokenHandle FALSE, // DisableAllPrivileges PreviousState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); ASSERT(PreviousState->PrivilegeCount == 1); PostPrivileges->PrivilegeCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithPrivileges, // TokenHandle TokenPrivileges, // TokenInformationClass PostPrivileges, // TokenInformation PostPrivilegesLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT ); ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the privilege values // if ( (PostPrivileges->Privileges[SECURITY_INDEX].Attributes == SE_PRIVILEGE_ENABLED) && (PostPrivileges->Privileges[UNSOLICITED_INDEX].Attributes == 0) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[0].Attributes, PostPrivileges->Privileges[0].Attributes); DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n", PrePrivileges->Privileges[1].Attributes, PostPrivileges->Privileges[1].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); //////////////////////////////////////////////////////////////// // // // Done with test // // // //////////////////////////////////////////////////////////////// TstDeallocatePool( PreviousState, PreviousStateBufferLength ); TstDeallocatePool( NewState, NewStateBufferLength ); TstDeallocatePool( PrePrivileges, PrePrivilegesLength ); TstDeallocatePool( PostPrivileges, PostPrivilegesLength ); return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Adjust Groups Test // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenAdjustGroups() { BOOLEAN CompletionStatus = TRUE; NTSTATUS Status; NTSTATUS IgnoreStatus; PTOKEN_GROUPS NewState; PTOKEN_GROUPS PreviousState; PTOKEN_GROUPS PreGroups; PTOKEN_GROUPS PostGroups; ULONG NewStateBufferLength = 600; ULONG PreviousStateBufferLength = 600; ULONG PreGroupsLength = 600; ULONG PostGroupsLength = 600; ULONG ReturnLength; ULONG IgnoreReturnLength; DbgPrint("\n"); PreviousState = (PTOKEN_GROUPS)TstAllocatePool( PagedPool, PreviousStateBufferLength ); PreGroups = (PTOKEN_GROUPS)TstAllocatePool( PagedPool, PreGroupsLength ); PostGroups = (PTOKEN_GROUPS)TstAllocatePool( PagedPool, PostGroupsLength ); NewState = (PTOKEN_GROUPS)TstAllocatePool( PagedPool, NewStateBufferLength ); ////////////////////////////////////////////////////////////////////// // // // Adjust groups giving no instructions // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Adjust groups with no instructions ... "); Status = NtAdjustGroupsToken( SimpleToken, // TokenHandle FALSE, // ResetToDefault NULL, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); if (Status == STATUS_INVALID_PARAMETER) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_INVALID_PARAMETER); ///////////////////////////////////////////////////////////////////////// // // // Disable unknown group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable unknown group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG if (IgnoreStatus != STATUS_SUCCESS) { DbgPrint(" \n IgnoreStatus = 0x%lx \n", IgnoreStatus); DbgPrint(" \n IgnoreReturnLength = 0x%lx \n", IgnoreReturnLength); } ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = RubbleSid; NewState->Groups[0].Attributes = DisabledGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_NOT_ALL_ASSIGNED) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_NOT_ALL_ASSIGNED); ///////////////////////////////////////////////////////////////////////// // // // Enable unknown group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable unknown group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = RubbleSid; NewState->Groups[0].Attributes = OptionalGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_NOT_ALL_ASSIGNED) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_NOT_ALL_ASSIGNED); ///////////////////////////////////////////////////////////////////////// // // // Disable mandatory group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable mandatory group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = WorldSid; NewState->Groups[0].Attributes = DisabledGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_CANT_DISABLE_MANDATORY) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_CANT_DISABLE_MANDATORY); ///////////////////////////////////////////////////////////////////////// // // // Enable mandatory group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable mandatory group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = WorldSid; NewState->Groups[0].Attributes = OptionalGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Disable optional group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable optional group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = ChildSid; NewState->Groups[0].Attributes = DisabledGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Disable already disabled group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable already disabled group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = ChildSid; NewState->Groups[0].Attributes = 0; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Enable optional group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable optional group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = ChildSid; NewState->Groups[0].Attributes = SE_GROUP_ENABLED; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Enable already enabled group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable already enabled group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = ChildSid; NewState->Groups[0].Attributes = SE_GROUP_ENABLED; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Disable optional and unknown group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable optional and unknown group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 2; NewState->Groups[0].Sid = ChildSid; NewState->Groups[1].Sid = RubbleSid; NewState->Groups[0].Attributes = DisabledGroupAttributes; NewState->Groups[1].Attributes = DisabledGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_NOT_ALL_ASSIGNED) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_NOT_ALL_ASSIGNED); ///////////////////////////////////////////////////////////////////////// // // // Enable optional and unknown group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable optional and unknown group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 2; NewState->Groups[0].Sid = ChildSid; NewState->Groups[1].Sid = RubbleSid; NewState->Groups[0].Attributes = OptionalGroupAttributes; NewState->Groups[1].Attributes = OptionalGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_NOT_ALL_ASSIGNED) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_NOT_ALL_ASSIGNED); ///////////////////////////////////////////////////////////////////////// // // // Disable optional and mandatory group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable optional and mandatory group ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 2; NewState->Groups[0].Sid = ChildSid; NewState->Groups[1].Sid = WorldSid; NewState->Groups[0].Attributes = DisabledGroupAttributes; NewState->Groups[1].Attributes = DisabledGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_CANT_DISABLE_MANDATORY) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_CANT_DISABLE_MANDATORY); ///////////////////////////////////////////////////////////////////////// // // // Enable optional and mandatory group // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Enable optional and mandatory group ... "); NewState->GroupCount = 1; NewState->Groups[0].Sid = ChildSid; NewState->Groups[0].Attributes = DisabledGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); ASSERT(Status == STATUS_SUCCESS); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 2; NewState->Groups[0].Sid = ChildSid; NewState->Groups[1].Sid = WorldSid; NewState->Groups[0].Attributes = OptionalGroupAttributes; NewState->Groups[1].Attributes = OptionalGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ////////////////////////////////////////////////////////////////////// // // // Disable optional group requesting previous state with // // insufficient buffer // // // ////////////////////////////////////////////////////////////////////// DbgPrint("Se: Too small buffer for previous state ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 1; NewState->Groups[0].Sid = ChildSid; NewState->Groups[0].Attributes = DisabledGroupAttributes; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) 0, // BufferLength PreviousState, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_BUFFER_TOO_SMALL) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_BUFFER_TOO_SMALL); ///////////////////////////////////////////////////////////////////////// // // // Disable optional requesting previous state // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Disable optional, requesting previous state ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); NewState->GroupCount = 2; NewState->Groups[0].Sid = NeandertholSid; NewState->Groups[1].Sid = ChildSid; NewState->Groups[0].Attributes = DisabledGroupAttributes; NewState->Groups[1].Attributes = DisabledGroupAttributes; PreviousState->GroupCount = 99; Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault NewState, // NewState (OPTIONAL) PreviousStateBufferLength, // BufferLength PreviousState, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); ASSERT( PreviousState->GroupCount == 2 ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) && (PreviousState->Groups[0].Attributes == OptionalGroupAttributes) && (PreviousState->Groups[1].Attributes == OptionalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); DbgPrint("Previous count is: 0x%lx \n", PreviousState->GroupCount); DbgPrint("Previous state of group 0 is: 0x%lx \n", PreviousState->Groups[0].Attributes); DbgPrint("Previous state of group 1 is: 0x%lx \n", PreviousState->Groups[1].Attributes); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Return group to previous state // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Return to previous state ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault PreviousState, // NewState (OPTIONAL) PreviousStateBufferLength, // BufferLength PreviousState, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) && (PreviousState->Groups[0].Attributes == DisabledGroupAttributes) && (PreviousState->Groups[1].Attributes == DisabledGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Return to previous state again // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Return to previous state again ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault PreviousState, // NewState (OPTIONAL) PreviousStateBufferLength, // BufferLength PreviousState, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) && (PreviousState->Groups[0].Attributes == OptionalGroupAttributes) && (PreviousState->Groups[1].Attributes == OptionalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Return to default state (capture previous state) // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Return to default state (w/previous state) ... "); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle TRUE, // ResetToDefault NULL, // NewState (OPTIONAL) PreviousStateBufferLength, // BufferLength PreviousState, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength); #endif //TOKEN_DEBUG PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) && (PreviousState->Groups[0].Attributes == DisabledGroupAttributes) && (PreviousState->Groups[1].Attributes == DisabledGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); ///////////////////////////////////////////////////////////////////////// // // // Return to default state (don't capture previous state) // // // ///////////////////////////////////////////////////////////////////////// DbgPrint("Se: Return to default state (no previous state) ... "); Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle FALSE, // ResetToDefault PreviousState, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); ASSERT(Status == STATUS_SUCCESS); PreGroups->GroupCount = 77; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PreGroups, // TokenInformation PreGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(PreGroups->GroupCount == GROUP_COUNT ); ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes); ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes); ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes); ASSERT(NT_SUCCESS(IgnoreStatus) ); Status = NtAdjustGroupsToken( TokenWithGroups, // TokenHandle TRUE, // ResetToDefault NULL, // NewState (OPTIONAL) 0, // BufferLength NULL, // PreviousState (OPTIONAL) &ReturnLength // ReturnLength ); PostGroups->GroupCount = 88; IgnoreStatus = NtQueryInformationToken( TokenWithGroups, // TokenHandle TokenGroups, // TokenInformationClass PostGroups, // TokenInformation PostGroupsLength, // TokenInformationLength &IgnoreReturnLength // ReturnLength ); #ifdef TOKEN_DEBUG DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength); #endif //TOKEN_DEBUG ASSERT(NT_SUCCESS(IgnoreStatus) ); if (Status == STATUS_SUCCESS) { // // Check the group values // ASSERT( PostGroups->GroupCount == GROUP_COUNT ); if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) && (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) && (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) ) { DbgPrint("Succeeded. \n"); } else { DbgPrint("********** Failed Value Check ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n", PreGroups->Groups[FLINTSTONE_INDEX].Attributes, PostGroups->Groups[FLINTSTONE_INDEX].Attributes); DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n", PreGroups->Groups[CHILD_INDEX].Attributes, PostGroups->Groups[CHILD_INDEX].Attributes); DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n", PreGroups->Groups[NEANDERTHOL_INDEX].Attributes, PostGroups->Groups[NEANDERTHOL_INDEX].Attributes); DbgPrint("Before/after World state: 0x%lx / 0x%lx \n", PreGroups->Groups[WORLD_INDEX].Attributes, PostGroups->Groups[WORLD_INDEX].Attributes); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); DbgPrint("Return Length is: 0x%lx \n", ReturnLength); CompletionStatus = FALSE; } ASSERT(Status == STATUS_SUCCESS); //////////////////////////////////////////////////////////////// // // // Done with test // // // //////////////////////////////////////////////////////////////// TstDeallocatePool( PreviousState, PreviousStateBufferLength ); TstDeallocatePool( NewState, NewStateBufferLength ); TstDeallocatePool( PreGroups, PreGroupsLength ); TstDeallocatePool( PostGroups, PostGroupsLength ); return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Compare duplicate to original token & display test results // // // //////////////////////////////////////////////////////////////// BOOLEAN TestpCompareDuplicateToken( IN NTSTATUS Status, IN HANDLE OldToken, IN OBJECT_ATTRIBUTES NewAttributes, IN BOOLEAN EffectiveOnly, IN TOKEN_TYPE NewType, IN HANDLE NewToken ) { BOOLEAN CompletionStatus = TRUE; ULONG OldReturnLength; ULONG NewReturnLength; PTOKEN_USER OldUserId; PTOKEN_USER NewUserId; TOKEN_SOURCE OldSource; TOKEN_SOURCE NewSource; TOKEN_STATISTICS OldStatistics; TOKEN_STATISTICS NewStatistics; BOOLEAN SomeNotCompared = FALSE; // // Appease the compiler Gods // NewAttributes = NewAttributes; NewType = NewType; EffectiveOnly = EffectiveOnly; // // If the status isn't success, don't bother comparing the tokens // if (!NT_SUCCESS(Status)) { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); return FALSE; } // // Compare the user IDs // Status = NtQueryInformationToken( OldToken, // Handle TokenUser, // TokenInformationClass OldUserId, // TokenInformation 0, // TokenInformationLength &OldReturnLength // ReturnLength ); ASSERT(Status == STATUS_BUFFER_TOO_SMALL); OldUserId = (PTOKEN_USER)TstAllocatePool( PagedPool, OldReturnLength ); Status = NtQueryInformationToken( OldToken, // Handle TokenUser, // TokenInformationClass OldUserId, // TokenInformation OldReturnLength, // TokenInformationLength &OldReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); Status = NtQueryInformationToken( NewToken, // Handle TokenUser, // TokenInformationClass NewUserId, // TokenInformation 0, // TokenInformationLength &NewReturnLength // ReturnLength ); ASSERT(Status == STATUS_BUFFER_TOO_SMALL); NewUserId = (PTOKEN_USER)TstAllocatePool( PagedPool, NewReturnLength ); Status = NtQueryInformationToken( NewToken, // Handle TokenUser, // TokenInformationClass NewUserId, // TokenInformation NewReturnLength, // TokenInformationLength &NewReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); if ( !RtlEqualSid(OldUserId->User.Sid, NewUserId->User.Sid) ) { if (CompletionStatus) { DbgPrint("*** Failed Value Comparison ***\n"); } DbgPrint("User IDs don't match.\n"); CompletionStatus = FALSE; } TstDeallocatePool( OldUserId, OldReturnLength ); TstDeallocatePool( NewUserId, NewReturnLength ); // // Check the token statistics // if (CompletionStatus) { Status = NtQueryInformationToken( OldToken, // Handle TokenStatistics, // TokenInformationClass &OldStatistics, // TokenInformation (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength &OldReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); Status = NtQueryInformationToken( NewToken, // Handle TokenStatistics, // TokenInformationClass &NewStatistics, // TokenInformation (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength &NewReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); // // Must have: // Different TokenId values // Same authenticationId value // Same ExpirationTime // Same token type // Same ImpersonationLevel (if correct token type) // Same DynamicCharged & DynamicAvailable // // GroupCount and PrivilegeCount are deferred to the group and // privilege comparison due to the difficulty involved with // taking EffectiveOnly into account. // // The new token must have a ModifiedId that is the same as the // original. // // // Token ID // if ( (OldStatistics.TokenId.HighPart == NewStatistics.TokenId.HighPart) && (OldStatistics.TokenId.LowPart == NewStatistics.TokenId.LowPart) ) { DbgPrint("*** Failed ***\n"); DbgPrint(" TokenIds are equal.\n"); DbgPrint(" Old TokenId is: (0x%xl, 0x%xl)\n", OldStatistics.TokenId.HighPart, OldStatistics.TokenId.LowPart); DbgPrint(" New TokenId is: (0x%xl, 0x%xl)\n", NewStatistics.TokenId.HighPart, NewStatistics.TokenId.LowPart); DbgPrint(" "); CompletionStatus = FALSE; } // // Authentication ID // if ( !RtlEqualLuid(&OldStatistics.AuthenticationId, &NewStatistics.AuthenticationId) ) { DbgPrint("*** Failed ***\n"); DbgPrint(" AuthenticationIds are not equal.\n"); DbgPrint("Original Authentication ID is: "); TestpPrintLuid(OldStatistics.AuthenticationId); DbgPrint("\n"); DbgPrint("New Authentication ID is: "); TestpPrintLuid(NewStatistics.AuthenticationId); DbgPrint("\n"); DbgPrint(" "); CompletionStatus = FALSE; } // // ExpirationTime // if ( (OldStatistics.ExpirationTime.HighPart != NewStatistics.ExpirationTime.HighPart) || (OldStatistics.ExpirationTime.LowPart != NewStatistics.ExpirationTime.LowPart) ) { DbgPrint("*** Failed ***\n"); DbgPrint(" ExpirationTimes differ.\n"); DbgPrint(" "); CompletionStatus = FALSE; } // // TokenType // if ( OldStatistics.TokenType != NewStatistics.TokenType ) { DbgPrint("*** Failed ***\n"); DbgPrint(" Token types are different.\n"); DbgPrint(" Old token type is: 0x%lx \n", OldStatistics.TokenType ); DbgPrint(" New token type is: 0x%lx \n", NewStatistics.TokenType ); DbgPrint(" "); CompletionStatus = FALSE; } // // ImpersonationLevel // if (NewStatistics.TokenType = TokenImpersonation) { if ( OldStatistics.ImpersonationLevel != NewStatistics.ImpersonationLevel ) { DbgPrint("*** Failed ***\n"); DbgPrint(" Impersonation levels are different.\n"); DbgPrint(" Old impersonation level is: 0x%lx \n", OldStatistics.ImpersonationLevel ); DbgPrint(" New impersonation level is: 0x%lx \n", NewStatistics.ImpersonationLevel ); DbgPrint(" "); CompletionStatus = FALSE; } } // // DynamicCharged // if ( OldStatistics.DynamicCharged != NewStatistics.DynamicCharged ) { DbgPrint("*** Failed ***\n"); DbgPrint(" DynamicCharges are different.\n"); DbgPrint(" Old value is: 0x%lx \n", OldStatistics.DynamicCharged ); DbgPrint(" New value is: 0x%lx \n", NewStatistics.DynamicCharged ); DbgPrint(" "); CompletionStatus = FALSE; } // // DynamicAvailable // if ( OldStatistics.DynamicAvailable != NewStatistics.DynamicAvailable ) { DbgPrint("*** Failed ***\n"); DbgPrint(" DynamicAvailable are different.\n"); DbgPrint(" Old value is: 0x%lx \n", OldStatistics.DynamicAvailable ); DbgPrint(" New value is: 0x%lx \n", NewStatistics.DynamicAvailable ); DbgPrint(" "); CompletionStatus = FALSE; } // // ModifiedId // if ( (NewStatistics.ModifiedId.HighPart != OldStatistics.ModifiedId.HighPart) || (NewStatistics.ModifiedId.LowPart != OldStatistics.ModifiedId.LowPart) ) { DbgPrint("*** Failed ***\n"); DbgPrint(" ModifiedIds different.\n"); DbgPrint(" Old ModifiedId is: (0x%xl, 0x%xl)\n", OldStatistics.ModifiedId.HighPart, OldStatistics.ModifiedId.LowPart); DbgPrint(" New ModifiedId is: (0x%xl, 0x%xl)\n", NewStatistics.ModifiedId.HighPart, NewStatistics.ModifiedId.LowPart); DbgPrint(" "); CompletionStatus = FALSE; } } // // Compare the group IDs // SomeNotCompared = TRUE; // // Compare the privileges // SomeNotCompared = TRUE; // // Compare the owner IDs // SomeNotCompared = TRUE; // // Compare the primary group IDs // SomeNotCompared = TRUE; // // Compare the default dacls // SomeNotCompared = TRUE; // // Compare the token source // if (CompletionStatus) { Status = NtQueryInformationToken( OldToken, // Handle TokenSource, // TokenInformationClass &OldSource, // TokenInformation (ULONG)sizeof(TOKEN_SOURCE), // TokenInformationLength &OldReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); Status = NtQueryInformationToken( NewToken, // Handle TokenSource, // TokenInformationClass &NewSource, // TokenInformation (ULONG)sizeof(TOKEN_SOURCE), // TokenInformationLength &NewReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); if ( (OldSource.SourceIdentifier.HighPart == NewSource.SourceIdentifier.HighPart) && (OldSource.SourceIdentifier.LowPart == NewSource.SourceIdentifier.LowPart) ) { if ( (OldSource.SourceName[0] != NewSource.SourceName[0]) || (OldSource.SourceName[1] != NewSource.SourceName[1]) || (OldSource.SourceName[2] != NewSource.SourceName[2]) || (OldSource.SourceName[3] != NewSource.SourceName[3]) || (OldSource.SourceName[4] != NewSource.SourceName[4]) || (OldSource.SourceName[5] != NewSource.SourceName[5]) || (OldSource.SourceName[6] != NewSource.SourceName[6]) || (OldSource.SourceName[7] != NewSource.SourceName[7]) ) { DbgPrint("*** Failed Value Comparison ***\n"); DbgPrint(" SourceName changed.\n"); CompletionStatus = FALSE; } } else { DbgPrint("*** Failed Value Comparison ***\n"); DbgPrint(" SourceIdentifier changed.\n"); DbgPrint(" Old SourceIdentifier is: (0x%xl, 0x%xl)\n", OldSource.SourceIdentifier.HighPart, OldSource.SourceIdentifier.LowPart); DbgPrint(" New SourceIdentifier is: (0x%xl, 0x%xl)\n", NewSource.SourceIdentifier.HighPart, NewSource.SourceIdentifier.LowPart); CompletionStatus = FALSE; } } ////////////////////////////////// Done ///////////////////////// if (SomeNotCompared) { DbgPrint("Incomplete\n"); DbgPrint(" Some fields not yet compared ... "); } if (CompletionStatus) { DbgPrint("Succeeded. \n"); } return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Duplicate Token Test // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenDuplicate() { BOOLEAN CompletionStatus = TRUE; BOOLEAN EffectiveOnly; TOKEN_TYPE NewType; HANDLE NewToken; OBJECT_ATTRIBUTES NewAttributes; SECURITY_QUALITY_OF_SERVICE ImpersonationLevel; SECURITY_QUALITY_OF_SERVICE IdentificationLevel; DbgPrint("\n"); // // Initialize variables // ImpersonationLevel.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE); ImpersonationLevel.ImpersonationLevel = SecurityImpersonation; ImpersonationLevel.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; ImpersonationLevel.EffectiveOnly = FALSE; IdentificationLevel.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE); IdentificationLevel.ImpersonationLevel = SecurityImpersonation; IdentificationLevel.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; IdentificationLevel.EffectiveOnly = FALSE; InitializeObjectAttributes( &NewAttributes, NULL, OBJ_INHERIT, NULL, NULL ); //////////////////////////////////////////////////////////// // // // Duplicate the simple token // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Duplicate primary token ... "); EffectiveOnly = FALSE; NewType = TokenImpersonation; NewAttributes.SecurityQualityOfService = &ImpersonationLevel; Status = NtDuplicateToken( SimpleToken, // ExistingTokenHandle 0, // DesiredAccess &NewAttributes, // ObjectAttributes EffectiveOnly, // EffectiveOnly NewType, // TokenType &NewToken // NewTokenHandle ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtClose( NewToken ); ASSERT(NT_SUCCESS(NewToken)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); return FALSE; } //////////////////////////////////////////////////////////// // // // Duplicate the full impersonation token // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Duplicate full impersonation token ... "); EffectiveOnly = FALSE; NewType = TokenImpersonation; NewAttributes.SecurityQualityOfService = &ImpersonationLevel; Status = NtDuplicateToken( ImpersonationToken, // ExistingTokenHandle 0, // DesiredAccess &NewAttributes, // ObjectAttributes EffectiveOnly, // EffectiveOnly NewType, // TokenType &NewToken // NewTokenHandle ); // // Check to see that the duplicate is really a duplicate of // the original and display the test results. // if (!TestpCompareDuplicateToken( Status, ImpersonationToken, NewAttributes, EffectiveOnly, NewType, NewToken ) ) { CompletionStatus = FALSE; } if (NT_SUCCESS(Status)) { Status = NtClose( NewToken ); ASSERT(NT_SUCCESS(Status)); } //////////////////////////////////////////////////////////// // // // Duplicate the full token, effective only // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Duplicate full token, effective only ... "); EffectiveOnly = TRUE; NewType = TokenImpersonation; NewAttributes.SecurityQualityOfService = &ImpersonationLevel; Status = NtDuplicateToken( ImpersonationToken, // ExistingTokenHandle 0, // DesiredAccess &NewAttributes, // ObjectAttributes EffectiveOnly, // EffectiveOnly NewType, // TokenType &NewToken // NewTokenHandle ); // // Check to see that the duplicate is really a duplicate of // the original and display the test results. // if (!TestpCompareDuplicateToken( Status, ImpersonationToken, NewAttributes, EffectiveOnly, NewType, NewToken ) ) { CompletionStatus = FALSE; } if (NT_SUCCESS(Status)) { Status = NtClose( NewToken ); ASSERT(NT_SUCCESS(Status)); } return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Assign Primary Token Test // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenAssignPrimary() { BOOLEAN CompletionStatus = TRUE; ULONG ReturnLength; TOKEN_STATISTICS OriginalTokenStatistics; TOKEN_STATISTICS NewTokenStatistics; TOKEN_STATISTICS AssignedTokenStatistics; TOKEN_USER UserId; TOKEN_PRIMARY_GROUP PrimaryGroup; PTOKEN_GROUPS GroupIds; PTOKEN_PRIVILEGES Privileges; TOKEN_DEFAULT_DACL DefaultDacl; TOKEN_OWNER Owner; PROCESS_ACCESS_TOKEN PrimaryTokenInfo; DbgPrint("\n"); //////////////////////////////////////////////////////////// // // // Assign a valid primary token // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Assign new primary token ... "); // // Get information about the current token // Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_ALL_ACCESS, &ProcessToken ); ASSERT (NT_SUCCESS(Status)); Status = NtQueryInformationToken( ProcessToken, // Handle TokenStatistics, // TokenInformationClass &OriginalTokenStatistics, // TokenInformation sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); // // Create a token with default DACL for use // GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool, GROUP_IDS_LENGTH ); Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool, PRIVILEGES_LENGTH ); DefaultDacl.DefaultDacl = (PACL)TstAllocatePool( PagedPool, DEFAULT_DACL_LENGTH ); GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid; GroupIds->Groups[CHILD_INDEX].Sid = ChildSid; GroupIds->Groups[SYSTEM_INDEX].Sid = LocalSystemSid; GroupIds->Groups[WORLD_INDEX].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[SYSTEM_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Owner.Owner = FlintstoneSid; Privileges->PrivilegeCount = PRIVILEGE_COUNT; Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege; Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege; Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION); ASSERT(NT_SUCCESS(Status) ); Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &SystemAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges &Owner, // Owner &PrimaryGroup, // Primary Group &DefaultDacl, // Default Dacl &TestSource // TokenSource ); ASSERT(NT_SUCCESS(Status)); // // Make sure key data is different than what is already on the process. // Status = NtQueryInformationToken( Token, // Handle TokenStatistics, // TokenInformationClass &NewTokenStatistics, // TokenInformation sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); ASSERT( (OriginalTokenStatistics.TokenId.HighPart != NewTokenStatistics.TokenId.HighPart) || (OriginalTokenStatistics.TokenId.LowPart != NewTokenStatistics.TokenId.LowPart) ); // // Assign the new token // PrimaryTokenInfo.Token = Token; PrimaryTokenInfo.Thread = NtCurrentThread(); Status = NtSetInformationProcess( NtCurrentProcess(), ProcessAccessToken, (PVOID)&PrimaryTokenInfo, (ULONG)sizeof(PROCESS_ACCESS_TOKEN) ); if (!NT_SUCCESS(Status)) { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } else { Status = NtClose( Token ); ASSERT(NT_SUCCESS(Status)); // // Get information about the assigned token // Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &Token ); ASSERT (NT_SUCCESS(Status)); Status = NtQueryInformationToken( Token, // Handle TokenStatistics, // TokenInformationClass &AssignedTokenStatistics, // TokenInformation sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); Status = NtClose( Token ); ASSERT(NT_SUCCESS(Status)); // // Information about assigned token and the new token // should be the same // ASSERT(AssignedTokenStatistics.TokenType == TokenPrimary); if ( (NewTokenStatistics.TokenId.HighPart == AssignedTokenStatistics.TokenId.HighPart) && (NewTokenStatistics.TokenId.LowPart == AssignedTokenStatistics.TokenId.LowPart) ) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Token ID mismatch.\n"); DbgPrint("New token ID is: (0x%lx, 0x%lx) \n", NewTokenStatistics.TokenId.HighPart, NewTokenStatistics.TokenId.LowPart); DbgPrint("Assigned token ID is: (0x%lx, 0x%lx) \n", AssignedTokenStatistics.TokenId.HighPart, AssignedTokenStatistics.TokenId.LowPart); CompletionStatus = FALSE; } } // // Change back to the original token // PrimaryTokenInfo.Token = ProcessToken; PrimaryTokenInfo.Thread = NtCurrentThread(); Status = NtSetInformationProcess( NtCurrentProcess(), ProcessAccessToken, (PVOID)&PrimaryTokenInfo, (ULONG)sizeof(PROCESS_ACCESS_TOKEN) ); ASSERT(NT_SUCCESS(Status)); Status = NtClose( ProcessToken ); ASSERT(NT_SUCCESS(Status)); //////////////////////////////////////////////////////////// // // // Attempt to assign an impersonation token as primary // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Assign impersonation token as primary ... "); // // Create an impersonation token // GroupIds->GroupCount = GROUP_COUNT; GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid; GroupIds->Groups[CHILD_INDEX].Sid = ChildSid; GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid; GroupIds->Groups[WORLD_INDEX].Sid = WorldSid; GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes; GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes; GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes; UserId.User.Sid = PebblesSid; UserId.User.Attributes = 0; Owner.Owner = FlintstoneSid; Privileges->PrivilegeCount = PRIVILEGE_COUNT; Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege; Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege; Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION); ASSERT(NT_SUCCESS(Status) ); Status = NtCreateToken( &Token, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &ImpersonationTokenAttributes, // ObjectAttributes TokenImpersonation, // TokenType &OriginalAuthenticationId, // Authentication LUID &NoExpiration, // Expiration Time &UserId, // Owner ID GroupIds, // Group IDs Privileges, // Privileges &Owner, // Owner &PrimaryGroup, // Primary Group &DefaultDacl, // Default Dacl &TestSource // TokenSource ); ASSERT(NT_SUCCESS(Status)); // // Assign the new token // PrimaryTokenInfo.Token = Token; PrimaryTokenInfo.Thread = NtCurrentThread(); Status = NtSetInformationProcess( NtCurrentProcess(), ProcessAccessToken, (PVOID)&PrimaryTokenInfo, (ULONG)sizeof(PROCESS_ACCESS_TOKEN) ); if (Status == STATUS_BAD_TOKEN_TYPE) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } Status = NtClose( Token ); ASSERT(NT_SUCCESS(Status)); return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Impersonation Test (with open test) // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenImpersonation() { BOOLEAN CompletionStatus = TRUE; HANDLE OpenedToken; HANDLE NewToken; DbgPrint("\n"); //////////////////////////////////////////////////////////// // // // Terminate impersonation using NtSetInformationThread() // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Revert to self (specify NULL handle) ... "); NewToken = NULL; Status = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } //////////////////////////////////////////////////////////// // // // Attempt to assign a primary token as an impersonation // // token. // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Assigning primary token as impersonation token ... "); NewToken = TokenWithGroups; Status = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) ); if (Status == STATUS_BAD_TOKEN_TYPE) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } //////////////////////////////////////////////////////////// // // // Assign a valid impersonation token // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Assign valid impersonation token ... "); NewToken = ImpersonationToken; Status = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } //////////////////////////////////////////////////////////// // // // Open the impersonation token // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Open an impersonation token ... "); Status = NtOpenThreadToken( NtCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &OpenedToken ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); Status = NtClose( OpenedToken ); ASSERT(NT_SUCCESS(Status)); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } //////////////////////////////////////////////////////////// // // // Open a non-existent impersonation token // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Open a non-existent impersonation token ... "); // // Clear any existing impersonation token. // NewToken = NULL; Status = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) ); ASSERT(NT_SUCCESS(Status)); Status = NtOpenThreadToken( NtCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &OpenedToken ); if (Status == STATUS_NO_TOKEN) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } //////////////////////////////////////////////////////////// // // // Open an anonymous impersonation token // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Open an anonymous impersonation token ... "); // // Assign an anonymous impersonation token // NewToken = AnonymousToken; Status = NtSetInformationThread( ThreadHandle, ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) ); ASSERT(NT_SUCCESS(Status)); Status = NtOpenThreadToken( ThreadHandle, TOKEN_ALL_ACCESS, TRUE, &OpenedToken ); if (Status == STATUS_CANT_OPEN_ANONYMOUS) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } //////////////////////////////////////////////////////////// // // // Change the impersonation of a thread // // // //////////////////////////////////////////////////////////// DbgPrint("Se: Change the impersonation token ... "); NewToken = NULL; Status = NtSetInformationThread( ThreadHandle, ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) ); ASSERT(NT_SUCCESS(Status)); NewToken = AnonymousToken; Status = NtSetInformationThread( ThreadHandle, ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) ); ASSERT(NT_SUCCESS(Status)); NewToken = ImpersonationToken; Status = NtSetInformationThread( ThreadHandle, ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) ); if (NT_SUCCESS(Status)) { DbgPrint("Succeeded.\n"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } Status = NtTerminateThread( ThreadHandle, (NTSTATUS)0 ); ASSERT(NT_SUCCESS(Status)); return CompletionStatus; } //////////////////////////////////////////////////////////////// // // // Main Program Entry // // // //////////////////////////////////////////////////////////////// BOOLEAN CTToken() // Common Test for Token object { BOOLEAN Result = TRUE; DbgPrint("Se: Initialization..."); TestTokenInitialize(); DbgPrint("Se: Token Creation Test... Test"); if (!TestTokenCreate()) { Result = FALSE; } DbgPrint("Se: Token Open Test (with primary token)... Test"); if (!TestTokenOpenPrimary()) { Result = FALSE; } DbgPrint("Se: Token Query Test... Test"); if (!TestTokenQuery()) { Result = FALSE; } DbgPrint("Se: Token Set Test... Test"); if (!TestTokenSet()) { Result = FALSE; } DbgPrint("Se: Token Adjust Privileges Test... Test"); if (!TestTokenAdjustPrivileges()) {Result = FALSE; } DbgPrint("Se: Token Adjust Group Test... Test"); if (!TestTokenAdjustGroups()) { Result = FALSE; } DbgPrint("Se: Token Duplication Test... Test"); if (!TestTokenDuplicate()) { Result = FALSE; } DbgPrint("Se: Primary Token Assignment Test... Test"); if (!TestTokenAssignPrimary()) { Result = FALSE; } DbgPrint("Se: Impersonation Test (and impersonation open)... Test"); if (!TestTokenImpersonation()) { Result = FALSE; } DbgPrint("\n"); DbgPrint("\n"); DbgPrint(" ********************\n"); DbgPrint(" ** **\n"); if (Result) { DbgPrint("Se: ** Test Succeeded **\n"); } else { DbgPrint("Se: ** Test Failed **\n"); } DbgPrint(" ** **\n"); DbgPrint(" ********************\n"); DbgPrint("\n"); DbgPrint("\n"); return Result; }