/*++ Copyright (c) 1989 Microsoft Corporation Module Name: ctaccess.c Abstract: Common access validation test routines These routines are used in both kernel and user mode tests. This test assumes the security runtime library routines are functioning correctly. Author: Robert Reichel (robertre) 12/14/90 Environment: Test of access validation routines Revision History: v1: robertre Created --*/ #include "tsecomm.c" // Mode dependent macros and routines. // // Define the local macros and procedure for this module // // // Return a pointer to the first Ace in an Acl (even if the Acl is empty). // // PACE_HEADER // FirstAce ( // IN PACL Acl // ); // #define FirstAce(Acl) ((PVOID)((PUCHAR)(Acl) + sizeof(ACL))) // // Return a pointer to the next Ace in a sequence (even if the input // Ace is the one in the sequence). // // PACE_HEADER // NextAce ( // IN PACE_HEADER Ace // ); // #define NextAce(Ace) ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize)) VOID DumpAcl ( IN PACL Acl ); //////////////////////////////////////////////////////////////// // // // 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) // // definitions related to TokenWithGroups // #define FLINTSTONE_INDEX (0L) #define CHILD_INDEX (1L) #define NEANDERTHOL_INDEX (2L) #define WORLD_INDEX (3L) #define GROUP_COUNT (4L) // // Definitions related to TokenWithPrivileges // #define UNSOLICITED_INDEX (0L) #define SECURITY_INDEX (1L) #define PRIVILEGE_COUNT (2L) // // Access types // #define SET_WIDGET_COLOR 0x00000001 #define SET_WIDGET_SIZE 0x00000002 #define GET_WIDGET_COLOR 0x00000004 #define GET_WIDGET_SIZE 0x00000008 #define START_WIDGET 0x00000010 #define STOP_WIDGET 0x00000020 #define GIVE_WIDGET 0x00000040 #define TAKE_WIDGET 0x00000080 NTSTATUS Status; HANDLE SimpleToken; HANDLE TokenWithGroups; HANDLE TokenWithDefaultOwner; HANDLE TokenWithPrivileges; HANDLE TokenWithDefaultDacl; HANDLE Token; HANDLE ImpersonationToken; HANDLE PrimaryToken; 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 DummyAuthenticationId; LUID SystemAuthenticationId = SYSTEM_LUID; TOKEN_SOURCE TestSource = {"SE: TEST", 0}; PSID Owner; PSID Group; PACL Dacl; PSID TempOwner; PSID TempGroup; PACL TempDacl; //////////////////////////////////////////////////////////////// // // // Initialization Routine // // // //////////////////////////////////////////////////////////////// BOOLEAN TestTokenInitialize() { TSeVariableInitialization(); // Initialize global variables 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 ); InitializeObjectAttributes( &PrimaryTokenAttributes, NULL, OBJ_INHERIT, NULL, NULL ); 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 ); // // Use a dummy authentication ID for a while. // DummyAuthenticationId = FredLuid; // // Use a token source specific to security test // NtAllocateLocallyUniqueId( &(TestSource.SourceIdentifier) ); DbgPrint("Done.\n"); return TRUE; } BOOLEAN CreateDAclToken() { BOOLEAN CompletionStatus = TRUE; TOKEN_USER UserId; TOKEN_PRIMARY_GROUP PrimaryGroup; PTOKEN_GROUPS GroupIds; PTOKEN_PRIVILEGES Privileges; TOKEN_DEFAULT_DACL DefaultDacl; TOKEN_OWNER Owner; PSECURITY_DESCRIPTOR Widget1SecurityDescriptor; NTSTATUS AccessStatus; ACCESS_MASK GrantedAccess; PACCESS_ALLOWED_ACE AllowBarneySetColor; PACCESS_ALLOWED_ACE AllowFredSetColor; PACCESS_DENIED_ACE DenyPebblesSetColor; PACCESS_ALLOWED_ACE AllowPebblesSetColor; PACCESS_DENIED_ACE DenyFredSetColor; PACCESS_ALLOWED_ACE AllowBarneySetSize; PACCESS_ALLOWED_ACE AllowPebblesSetSize; PACCESS_ALLOWED_ACE AllowPebblesGetColor; PACCESS_ALLOWED_ACE AllowPebblesGetSize; USHORT AllowBarneySetColorLength; USHORT AllowFredSetColorLength; USHORT DenyPebblesSetColorLength; USHORT AllowPebblesSetColorLength; USHORT DenyFredSetColorLength; USHORT AllowBarneySetSizeLength; USHORT AllowPebblesSetSizeLength; USHORT AllowPebblesGetColorLength; USHORT AllowPebblesGetSizeLength; 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 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[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION); ASSERT(NT_SUCCESS(Status) ); Status = NtCreateToken( &PrimaryToken, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &PrimaryTokenAttributes, // ObjectAttributes TokenPrimary, // TokenType &DummyAuthenticationId, // 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"); } 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[UNSOLICITED_INDEX].Attributes = 0; Privileges->Privileges[SECURITY_INDEX].Attributes = 0; PrimaryGroup.PrimaryGroup = FlintstoneSid; Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION); ASSERT(NT_SUCCESS(Status) ); Status = NtCreateToken( &ImpersonationToken, // Handle (TOKEN_ALL_ACCESS), // DesiredAccess &ImpersonationTokenAttributes, // ObjectAttributes TokenImpersonation, // TokenType &DummyAuthenticationId, // 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"); } else { DbgPrint("********** Failed ************\n"); DbgPrint("Status is: 0x%lx \n", Status); CompletionStatus = FALSE; } ASSERT(NT_SUCCESS(Status)); // // Attach tokens to process // NtSetInformationProcess( NtCurrentProcess(), ProcessAccessToken, &PrimaryToken, sizeof( PHANDLE )); NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, &ImpersonationToken, sizeof( PHANDLE )); // Create some ACEs // AllowBarneySetColor AllowBarneySetColorLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) + SeLengthSid( BarneySid )); AllowBarneySetColor = (PVOID) TstAllocatePool ( PagedPool, AllowBarneySetColorLength ); AllowBarneySetColor->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; AllowBarneySetColor->Header.AceSize = AllowBarneySetColorLength; AllowBarneySetColor->Header.AceFlags = 0; AllowBarneySetColor->Mask = SET_WIDGET_COLOR; RtlCopySid( SeLengthSid( BarneySid ), &(AllowBarneySetColor->SidStart), BarneySid ); // DenyPebblesSetColor DenyPebblesSetColorLength = (USHORT)(sizeof( ACCESS_DENIED_ACE ) - sizeof( ULONG ) + SeLengthSid( BarneySid )); DenyPebblesSetColor = (PVOID) TstAllocatePool ( PagedPool, DenyPebblesSetColorLength ); DenyPebblesSetColor->Header.AceType = ACCESS_DENIED_ACE_TYPE; DenyPebblesSetColor->Header.AceSize = DenyPebblesSetColorLength; DenyPebblesSetColor->Header.AceFlags = 0; DenyPebblesSetColor->Mask = SET_WIDGET_COLOR; RtlCopySid( SeLengthSid( PebblesSid ), &(DenyPebblesSetColor->SidStart), PebblesSid ); // AllowFredSetColor AllowFredSetColorLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) + SeLengthSid( FredSid )); AllowFredSetColor = (PVOID) TstAllocatePool ( PagedPool, AllowFredSetColorLength ); AllowFredSetColor->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; AllowFredSetColor->Header.AceSize = AllowFredSetColorLength; AllowFredSetColor->Header.AceFlags = 0; AllowFredSetColor->Mask = SET_WIDGET_COLOR; RtlCopySid( SeLengthSid( FredSid ), &(AllowFredSetColor->SidStart), FredSid ); // AllowPebblesSetColor AllowPebblesSetColorLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) + SeLengthSid( PebblesSid )); AllowPebblesSetColor = (PVOID) TstAllocatePool ( PagedPool, AllowPebblesSetColorLength ); AllowPebblesSetColor->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; AllowPebblesSetColor->Header.AceSize = AllowPebblesSetColorLength; AllowPebblesSetColor->Header.AceFlags = 0; AllowPebblesSetColor->Mask = SET_WIDGET_COLOR; RtlCopySid( SeLengthSid( PebblesSid ), &(AllowPebblesSetColor->SidStart), PebblesSid ); // DenyFredSetColor DenyFredSetColorLength = (USHORT)(sizeof( ACCESS_DENIED_ACE ) - sizeof( ULONG ) + SeLengthSid( FredSid )); DenyFredSetColor = (PVOID) TstAllocatePool ( PagedPool, DenyFredSetColorLength ); DenyFredSetColor->Header.AceType = ACCESS_DENIED_ACE_TYPE; DenyFredSetColor->Header.AceSize = DenyFredSetColorLength; DenyFredSetColor->Header.AceFlags = 0; DenyFredSetColor->Mask = SET_WIDGET_COLOR; RtlCopySid( SeLengthSid( FredSid ), &(DenyFredSetColor->SidStart), FredSid ); // AllowBarneySetSize AllowBarneySetSizeLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) + SeLengthSid( BarneySid )); AllowBarneySetSize = (PVOID) TstAllocatePool ( PagedPool, AllowBarneySetSizeLength ); AllowBarneySetSize->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; AllowBarneySetSize->Header.AceSize = AllowBarneySetSizeLength; AllowBarneySetSize->Header.AceFlags = 0; AllowBarneySetSize->Mask = SET_WIDGET_SIZE; RtlCopySid( SeLengthSid( BarneySid ), &(AllowBarneySetSize->SidStart), BarneySid ); // AllowPebblesSetSize AllowPebblesSetSizeLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) + SeLengthSid( PebblesSid )); AllowPebblesSetSize = (PVOID) TstAllocatePool ( PagedPool, AllowPebblesSetSizeLength ); AllowPebblesSetSize->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; AllowPebblesSetSize->Header.AceSize = AllowPebblesSetSizeLength; AllowPebblesSetSize->Header.AceFlags = 0; AllowPebblesSetSize->Mask = SET_WIDGET_SIZE; RtlCopySid( SeLengthSid( PebblesSid ), &(AllowPebblesSetSize->SidStart), PebblesSid ); // AllowPebblesGetSize AllowPebblesGetSizeLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) + SeLengthSid( PebblesSid )); AllowPebblesGetSize = (PVOID) TstAllocatePool ( PagedPool, AllowPebblesGetSizeLength ); AllowPebblesGetSize->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; AllowPebblesGetSize->Header.AceSize = AllowPebblesGetSizeLength; AllowPebblesGetSize->Header.AceFlags = 0; AllowPebblesGetSize->Mask = SET_WIDGET_SIZE; RtlCopySid( SeLengthSid( PebblesSid ), &(AllowPebblesGetSize->SidStart), PebblesSid ); // AllowPebblesGetColor AllowPebblesGetColorLength = (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ) + SeLengthSid( PebblesSid )); AllowPebblesGetColor = (PVOID) TstAllocatePool ( PagedPool, AllowPebblesGetColorLength ); AllowPebblesGetColor->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; AllowPebblesGetColor->Header.AceSize = AllowPebblesGetColorLength; AllowPebblesGetColor->Header.AceFlags = 0; AllowPebblesGetColor->Mask = SET_WIDGET_COLOR; RtlCopySid( SeLengthSid( PebblesSid ), &(AllowPebblesGetColor->SidStart), PebblesSid ); // // Create some ACLs that we can put into a Security Descriptor // DbgBreakPoint(); // // Dacl // // +----------------+ +----------------+ +----------------+ // | 1st ACE | | 2nd ACE | | 3rd ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessDenied | | AccessAllowed | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | FRED | // +----------------+ +----------------+ +----------------+ // | SetWidgeColor | | SetWidgeColor | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // Dacl = (PACL) TstAllocatePool ( PagedPool, 2048 ); RtlCreateAcl( Dacl, 2048, ACL_REVISION); RtlAddAce ( Dacl, ACL_REVISION, 0, AllowBarneySetColor, AllowBarneySetColorLength ); RtlAddAce ( Dacl, ACL_REVISION, 1, DenyPebblesSetColor, DenyPebblesSetColorLength ); RtlAddAce ( Dacl, ACL_REVISION, 2, DenyFredSetColor, AllowFredSetColorLength ); DumpAcl (Dacl); // Create a security descriptor // // Owner = Pebbles // Group = Flintstone // Dacl = Dacl // Sacl = NULL // Widget1SecurityDescriptor = (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 ); RtlCreateSecurityDescriptor( Widget1SecurityDescriptor, 1 ); RtlSetOwnerSecurityDescriptor( Widget1SecurityDescriptor, PebblesSid, FALSE ); RtlSetGroupSecurityDescriptor( Widget1SecurityDescriptor, FlintstoneSid, FALSE ); RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor, TRUE, Dacl, FALSE ); RtlSetSaclSecurityDescriptor( Widget1SecurityDescriptor, FALSE, NULL, NULL ); // See if Pebbles is allowed SET_WIDGET_COLOR (should be denied) Status = NtAccessCheck( Widget1SecurityDescriptor, PrimaryToken, (ACCESS_MASK) SET_WIDGET_COLOR, &GrantedAccess, &AccessStatus ); // DbgBreakPoint(); ASSERT(NT_SUCCESS(Status)); ASSERT(!NT_SUCCESS(AccessStatus)); ASSERT(GrantedAccess == NULL); // Update Dacl to be the following: // // Dacl2 // // +----------------+ +----------------+ +----------------+ // | 1st ACE | | 2nd ACE | | 3rd ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessAllowed | | AccessDenied | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | FRED | // +----------------+ +----------------+ +----------------+ // | SetWidgeColor | | SetWidgeColor | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // // Delete 2nd Ace RtlDeleteAce (Dacl, 1); RtlAddAce ( Dacl, ACL_REVISION, 1, AllowPebblesSetColor, AllowPebblesSetColorLength ); RtlDeleteAce ( Dacl, 2 ); RtlAddAce ( Dacl, ACL_REVISION, 1, DenyFredSetColor, DenyFredSetColorLength ); // Change the security descriptor to use updated Dacl // // Owner = Pebbles // Group = Flintstone // Dacl = Dacl2 // Sacl = NULL // RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor, TRUE, Dacl, FALSE ); // See if Pebbles is allowed SET_WIDGET_COLOR (should be permitted) Status = NtAccessCheck( Widget1SecurityDescriptor, PrimaryToken, (ACCESS_MASK) SET_WIDGET_COLOR, &GrantedAccess, &AccessStatus ); ASSERT(NT_SUCCESS(Status)); ASSERT(NT_SUCCESS(AccessStatus)); ASSERT(GrantedAccess == (ACCESS_MASK)SET_WIDGET_COLOR); // // Dacl3 // // +----------------+ +----------------+ +----------------+ // | 1st ACE | | 2nd ACE | | 3rd ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessAllowed | | AccessDenied | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | FRED | // +----------------+ +----------------+ +----------------+ // | SetWidgeColor | | SetWidgeColor | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // // +----------------+ +----------------+ // | 4th ACE | | 5th ACE | // +----------------+ +----------------+ // | AccessAllowed | | AccessAllowed | // +----------------+ +----------------+ // | BARNEY | | PEBBLES | // +----------------+ +----------------+ // | SetWidgeSize | | SetWidgeSize | // +----------------+ +----------------+ // RtlAddAce ( Dacl, ACL_REVISION, MAXULONG, AllowBarneySetSize, AllowBarneySetSizeLength ); RtlAddAce ( Dacl, ACL_REVISION, MAXULONG, AllowPebblesSetSize, AllowPebblesSetSizeLength ); // Change the security descriptor to use Dacl3 // // Owner = Pebbles // Group = Flintstone // Dacl = Dacl3 // Sacl = NULL // RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor, TRUE, Dacl, FALSE ); // Request MAXIMUM_ACCESS for Pebbles. Should get back SetWidgetSize // and SetWidgetColor Status = NtAccessCheck( Widget1SecurityDescriptor, PrimaryToken, (ACCESS_MASK) MAXIMUM_ALLOWED, &GrantedAccess, &AccessStatus ); ASSERT(NT_SUCCESS(Status)); ASSERT(NT_SUCCESS(AccessStatus)); ASSERT(GrantedAccess == (ACCESS_MASK) (SET_WIDGET_COLOR | SET_WIDGET_SIZE)); // // Dacl4 // // +----------------+ +----------------+ +----------------+ // | 1st ACE | | 2nd ACE | | 3rd ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessAllowed | | AccessDenied | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | FRED | // +----------------+ +----------------+ +----------------+ // | SetWidgeColor | | SetWidgeColor | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // // +----------------+ +----------------+ +----------------+ // | 4th ACE | | 5th ACE | | 6th ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessAllowed | | AccessDenied | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | PEBBLES | // +----------------+ +----------------+ +----------------+ // | SetWidgeSize | | SetWidgeSize | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // RtlAddAce ( Dacl, ACL_REVISION, MAXULONG, DenyPebblesSetColor, DenyPebblesSetColorLength ); RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor, TRUE, Dacl, FALSE ); // Request MAXIMUM_ACCESS for Pebbles. Should get back SetWidgetSize // and SetWidgetColor Status = NtAccessCheck( Widget1SecurityDescriptor, PrimaryToken, (ACCESS_MASK) MAXIMUM_ALLOWED, &GrantedAccess, &AccessStatus ); ASSERT(NT_SUCCESS(Status)); ASSERT(NT_SUCCESS(AccessStatus)); ASSERT(GrantedAccess == (ACCESS_MASK) (SET_WIDGET_COLOR | SET_WIDGET_SIZE)); // // Dacl5 // // +----------------+ +----------------+ +----------------+ // | 1st ACE | | 2nd ACE | | 3rd ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessDenied | | AccessDenied | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | FRED | // +----------------+ +----------------+ +----------------+ // | SetWidgeColor | | SetWidgeColor | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // // +----------------+ +----------------+ +----------------+ // | 4th ACE | | 5th ACE | | 6th ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessAllowed | | AccessAllowed | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | PEBBLES | // +----------------+ +----------------+ +----------------+ // | SetWidgeSize | | SetWidgeSize | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // RtlDeleteAce (Dacl, 1); RtlAddAce ( Dacl, ACL_REVISION, 1, DenyPebblesSetColor, DenyPebblesSetColorLength ); RtlDeleteAce (Dacl, 5); RtlAddAce ( Dacl, ACL_REVISION, MAXULONG, AllowPebblesSetColor, AllowPebblesSetColorLength ); DumpAcl ( Dacl ); RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor, TRUE, Dacl, FALSE ); // Request MAXIMUM_ACCESS for Pebbles. Should get back SetWidgetSize Status = NtAccessCheck( Widget1SecurityDescriptor, PrimaryToken, (ACCESS_MASK) MAXIMUM_ALLOWED, &GrantedAccess, &AccessStatus ); ASSERT(NT_SUCCESS(Status)); ASSERT(NT_SUCCESS(AccessStatus)); ASSERT(GrantedAccess == (ACCESS_MASK) SET_WIDGET_SIZE); // // Dacl6 // // +----------------+ +----------------+ +----------------+ // | 1st ACE | | 2nd ACE | | 3rd ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessDenied | | AccessDenied | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | FRED | // +----------------+ +----------------+ +----------------+ // | SetWidgeColor | | SetWidgeColor | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // // +----------------+ +----------------+ +----------------+ // | 4th ACE | | 5th ACE | | 6th ACE | // +----------------+ +----------------+ +----------------+ // | AccessAllowed | | AccessAllowed | | AccessAllowed | // +----------------+ +----------------+ +----------------+ // | BARNEY | | PEBBLES | | PEBBLES | // +----------------+ +----------------+ +----------------+ // | SetWidgeSize | | SetWidgeSize | | SetWidgeColor | // +----------------+ +----------------+ +----------------+ // // +----------------+ +----------------+ // | 7th ACE | | 8th ACE | // +----------------+ +----------------+ // | AccessAllowed | | AccessAllowed | // +----------------+ +----------------+ // | PEBBLES | | PEBBLES | // +----------------+ +----------------+ // | GetWidgeSize | | GetWidgeColor | // +----------------+ +----------------+ // RtlAddAce ( Dacl, ACL_REVISION, MAXULONG, AllowPebblesGetSize, AllowPebblesGetSizeLength ); RtlAddAce ( Dacl, ACL_REVISION, MAXULONG, AllowPebblesGetColor, AllowPebblesGetColorLength ); DumpAcl ( Dacl ); RtlSetDaclSecurityDescriptor( Widget1SecurityDescriptor, TRUE, Dacl, FALSE ); // Request MAXIMUM_ACCESS for Pebbles. Should get back SetWidgetSize Status = NtAccessCheck( Widget1SecurityDescriptor, PrimaryToken, (ACCESS_MASK) MAXIMUM_ALLOWED, &GrantedAccess, &AccessStatus ); ASSERT(NT_SUCCESS(Status)); ASSERT(NT_SUCCESS(AccessStatus)); ASSERT(GrantedAccess == (ACCESS_MASK) SET_WIDGET_SIZE); return(TRUE); } ///////////////////////////////////////////////////////////////////// // // // // // Main test entry point // // // // // ///////////////////////////////////////////////////////////////////// BOOLEAN CTAccess() { BOOLEAN Result = TRUE; if (!TSeVariableInitialization()) { DbgPrint("Se: Failed to initialize global test variables.\n"); return FALSE; } DbgPrint("Se: Initialization..."); TestTokenInitialize(); CreateDAclToken(); } // // Debug support routine // typedef struct _STANDARD_ACE { ACE_HEADER Header; ACCESS_MASK Mask; PSID Sid; } STANDARD_ACE; typedef STANDARD_ACE *PSTANDARD_ACE; VOID DumpAcl ( IN PACL Acl ) /*++ Routine Description: This routine dumps via (DbgPrint) an Acl for debug purposes. It is specialized to dump standard aces. Arguments: Acl - Supplies the Acl to dump Return Value: None --*/ { ULONG i; PSTANDARD_ACE Ace; DbgPrint("DumpAcl @ %8lx", Acl); // // Check if the Acl is null // if (Acl == NULL) { return; } // // Dump the Acl header // DbgPrint(" Revision: %02x", Acl->AclRevision); DbgPrint(" Size: %04x", Acl->AclSize); DbgPrint(" AceCount: %04x\n", Acl->AceCount); // // Now for each Ace we want do dump it // for (i = 0, Ace = FirstAce(Acl); i < Acl->AceCount; i++, Ace = NextAce(Ace) ) { // // print out the ace header // DbgPrint(" AceHeader: %08lx ", *(PULONG)Ace); // // special case on the standard ace types // if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) || (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) || (Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) || (Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE)) { // // The following array is indexed by ace types and must // follow the allowed, denied, audit, alarm seqeuence // static PCHAR AceTypes[] = { "Access Allowed", "Access Denied ", "System Audit ", "System Alarm " }; DbgPrint(AceTypes[Ace->Header.AceType]); DbgPrint("\nAccess Mask: %08lx ", Ace->Mask); } else { DbgPrint("Unknown Ace Type\n"); } DbgPrint("\n"); DbgPrint("AceSize = %d\n",Ace->Header.AceSize); DbgPrint("Ace Flags = "); if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) { DbgPrint("OBJECT_INHERIT_ACE\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) { DbgPrint("CONTAINER_INHERIT_ACE\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) { DbgPrint("NO_PROPAGATE_INHERIT_ACE\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) { DbgPrint("INHERIT_ONLY_ACE\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) { DbgPrint("SUCCESSFUL_ACCESS_ACE_FLAG\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) { DbgPrint("FAILED_ACCESS_ACE_FLAG\n"); DbgPrint(" "); } DbgPrint("\n"); } }