From 010910bc344569f1b6fdec6c4b936ac8e44d8f72 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Fri, 11 May 2007 18:15:13 +0000 Subject: [PATCH] - Add missing ACE structures to ntifs.h. - Add missing SeLengthSid to ntifs.h. - Implement CmpHiveRootSecurityDescriptor and use it in CmpInitializeSystemHive and CmInitSystem1 to properly secure system-created hives. - Implement CmpInitializeHardwareConfiguration and call it. Its job is to populate the hardware hive, but FreeLDR already does this, so it doesn't do much at the moment. svn path=/trunk/; revision=26701 --- reactos/include/ddk/ntifs.h | 39 ++++++++ reactos/ntoskrnl/cm/cm.h | 60 +++++++++++++ reactos/ntoskrnl/cm/registry.c | 86 ++++++------------ reactos/ntoskrnl/config/cmconfig.c | 78 ++++++++++++++++ reactos/ntoskrnl/config/cmse.c | 138 +++++++++++++++++++++++++++++ reactos/ntoskrnl/ntoskrnl.rbuild | 1 + 6 files changed, 344 insertions(+), 58 deletions(-) create mode 100644 reactos/ntoskrnl/config/cmse.c diff --git a/reactos/include/ddk/ntifs.h b/reactos/include/ddk/ntifs.h index 4614a46f7a3..36c2c0d4a51 100644 --- a/reactos/include/ddk/ntifs.h +++ b/reactos/include/ddk/ntifs.h @@ -1724,6 +1724,41 @@ typedef struct _ACE_HEADER USHORT AceSize; } ACE_HEADER, *PACE_HEADER; +typedef struct _ACCESS_ALLOWED_ACE +{ + ACE_HEADER Header; + ACCESS_MASK Mask; + ULONG SidStart; +} ACCESS_ALLOWED_ACE, *PACCESS_ALLOWED_ACE; + +typedef struct _ACCESS_DENIED_ACE +{ + ACE_HEADER Header; + ACCESS_MASK Mask; + ULONG SidStart; +} ACCESS_DENIED_ACE, *PACCESS_DENIED_ACE; + +typedef struct _SYSTEM_AUDIT_ACE +{ + ACE_HEADER Header; + ACCESS_MASK Mask; + ULONG SidStart; +} SYSTEM_AUDIT_ACE, *PSYSTEM_AUDIT_ACE; + +typedef struct _SYSTEM_ALARM_ACE +{ + ACE_HEADER Header; + ACCESS_MASK Mask; + ULONG SidStart; +} SYSTEM_ALARM_ACE, *PSYSTEM_ALARM_ACE; + +typedef struct _SYSTEM_MANDATORY_LABEL_ACE +{ + ACE_HEADER Header; + ACCESS_MASK Mask; + ULONG SidStart; +} SYSTEM_MANDATORY_LABEL_ACE, *PSYSTEM_MANDATORY_LABEL_ACE; + typedef struct _TUNNEL { FAST_MUTEX Mutex; PRTL_SPLAY_LINKS Cache; @@ -4306,6 +4341,10 @@ SeCreateClientSecurityFromSubjectContext ( #endif /* (VER_PRODUCTBUILD >= 2195) */ + +#define SeLengthSid( Sid ) \ + (8 + (4 * ((SID *)Sid)->SubAuthorityCount)) + #define SeDeleteClientSecurity(C) { \ if (SeTokenType((C)->ClientToken) == TokenPrimary) { \ PsDereferencePrimaryToken( (C)->ClientToken ); \ diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 8c1e86742c2..a81d563ed56 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -418,6 +418,66 @@ CmpFileFlush( PHHIVE RegistryHive, ULONG FileType); +VOID +CmiCheckKey(BOOLEAN Verbose, + HANDLE Key); + +BOOLEAN +INIT_FUNCTION +CmImportSystemHive(PCHAR ChunkBase, + ULONG ChunkSize, + OUT PEREGISTRY_HIVE *RegistryHive); + +BOOLEAN +INIT_FUNCTION +CmImportHardwareHive(PCHAR ChunkBase, + ULONG ChunkSize, + OUT PEREGISTRY_HIVE *RegistryHive); + +NTSTATUS +NTAPI +CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock); + +NTSTATUS +NTAPI +CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock); + +NTSTATUS +NTAPI +CmpInitializeMachineDependentConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock); + +NTSTATUS +NTAPI +CmpInitializeHive(PEREGISTRY_HIVE *RegistryHive, + ULONG OperationType, + ULONG HiveFlags, + ULONG FileType, + PVOID HiveData OPTIONAL, + HANDLE Primary, + HANDLE Log, + HANDLE External, + PUNICODE_STRING FileName OPTIONAL, + ULONG CheckFlags); + +USHORT +NTAPI +CmpCopyName(IN PHHIVE Hive, + IN PWCHAR Destination, + IN PUNICODE_STRING Source); + +USHORT +NTAPI +CmpNameSize(IN PHHIVE Hive, + IN PUNICODE_STRING Name); + +NTSTATUS +NTAPI +CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock); + +PSECURITY_DESCRIPTOR +NTAPI +CmpHiveRootSecurityDescriptor(VOID); + #if 0 static __inline PVOID xHvGetCell(char *file, int line, PHHIVE Hive, HCELL_INDEX Cell) { diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index de2753d6501..c35689b0fed 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -49,60 +49,6 @@ KTIMER CmiHiveSyncTimer; static GENERIC_MAPPING CmiKeyMapping = {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS}; - - -VOID -CmiCheckKey(BOOLEAN Verbose, - HANDLE Key); - -BOOLEAN -INIT_FUNCTION -CmImportSystemHive(PCHAR ChunkBase, - ULONG ChunkSize, - OUT PEREGISTRY_HIVE *RegistryHive); - -BOOLEAN -INIT_FUNCTION -CmImportHardwareHive(PCHAR ChunkBase, - ULONG ChunkSize, - OUT PEREGISTRY_HIVE *RegistryHive); - -NTSTATUS -NTAPI -CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock); - -NTSTATUS -NTAPI -CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock); - -NTSTATUS -NTAPI -CmpInitializeMachineDependentConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock); - -NTSTATUS -NTAPI -CmpInitializeHive(PEREGISTRY_HIVE *RegistryHive, - ULONG OperationType, - ULONG HiveFlags, - ULONG FileType, - PVOID HiveData OPTIONAL, - HANDLE Primary, - HANDLE Log, - HANDLE External, - PUNICODE_STRING FileName OPTIONAL, - ULONG CheckFlags); - -USHORT -NTAPI -CmpCopyName(IN PHHIVE Hive, - IN PWCHAR Destination, - IN PUNICODE_STRING Source); - -USHORT -NTAPI -CmpNameSize(IN PHHIVE Hive, - IN PUNICODE_STRING Name); - static VOID STDCALL CmiHiveSyncDpcRoutine(PKDPC Dpc, PVOID DeferredContext, @@ -253,6 +199,7 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock) UNICODE_STRING KeyName; PEREGISTRY_HIVE SystemHive; UNICODE_STRING HiveName = RTL_CONSTANT_STRING(L"SYSTEM"); + PSECURITY_DESCRIPTOR SecurityDescriptor; PAGED_CODE(); /* Setup the ansi string */ @@ -309,9 +256,16 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock) Allocate = TRUE; } + /* Create the default security descriptor */ + SecurityDescriptor = CmpHiveRootSecurityDescriptor(); + /* Attach it to the system key */ RtlInitUnicodeString(&KeyName, REG_SYSTEM_KEY_NAME); - Status = CmpLinkHiveToMaster(&KeyName, NULL, SystemHive, Allocate, NULL); + Status = CmpLinkHiveToMaster(&KeyName, + NULL, + SystemHive, + Allocate, + SecurityDescriptor); if (!NT_SUCCESS(Status)) return FALSE; /* Success! */ @@ -495,6 +449,7 @@ CmInitSystem1(VOID) PEREGISTRY_HIVE HardwareHive; PVOID BaseAddress; ULONG Length; + PSECURITY_DESCRIPTOR SecurityDescriptor; PAGED_CODE(); /* Initialize the hive list */ @@ -559,13 +514,16 @@ CmInitSystem1(VOID) KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 3, 0, 0); } + /* Create the default security descriptor */ + SecurityDescriptor = CmpHiveRootSecurityDescriptor(); + /* Create '\Registry\Machine' key. */ RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, - NULL); + SecurityDescriptor); Status = NtCreateKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, @@ -588,7 +546,7 @@ CmInitSystem1(VOID) &KeyName, OBJ_CASE_INSENSITIVE, NULL, - NULL); + SecurityDescriptor); Status = NtCreateKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, @@ -642,13 +600,25 @@ CmInitSystem1(VOID) /* Attach it to the machine key */ RtlInitUnicodeString(&KeyName, REG_HARDWARE_KEY_NAME); - Status = CmpLinkHiveToMaster(&KeyName, NULL, HardwareHive, FALSE, NULL); + Status = CmpLinkHiveToMaster(&KeyName, + NULL, + HardwareHive, + FALSE, + SecurityDescriptor); if (!NT_SUCCESS(Status)) { /* Bugcheck */ KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 12, Status, 0); } + /* Fill out the Hardware key with the ARC Data from the Loader */ + Status = CmpInitializeHardwareConfiguration(KeLoaderBlock); + if (!NT_SUCCESS(Status)) + { + /* Bugcheck */ + KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 13, Status, 0); + } + /* Initialize machine-dependent information into the registry */ Status = CmpInitializeMachineDependentConfiguration(KeLoaderBlock); if (!NT_SUCCESS(Status)) diff --git a/reactos/ntoskrnl/config/cmconfig.c b/reactos/ntoskrnl/config/cmconfig.c index cdad7d38dcf..3040eca9f3c 100644 --- a/reactos/ntoskrnl/config/cmconfig.c +++ b/reactos/ntoskrnl/config/cmconfig.c @@ -194,3 +194,81 @@ CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, return Status; } +NTSTATUS +NTAPI +CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + ULONG Disposition; + UNICODE_STRING KeyName; + + /* Setup the key name */ + RtlInitUnicodeString(&KeyName, + L"\\Registry\\Machine\\Hardware\\DeviceMap"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Create the device map key */ + Status = NtCreateKey(&KeyHandle, + KEY_READ | KEY_WRITE, + &ObjectAttributes, + 0, + NULL, + 0, + &Disposition); + if (!NT_SUCCESS(Status)) return Status; + NtClose(KeyHandle); + + /* Nobody should've created this key yet! */ + //ASSERT(Disposition == REG_CREATED_NEW_KEY); + + /* Setup the key name */ + RtlInitUnicodeString(&KeyName, + L"\\Registry\\Machine\\Hardware\\Description"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Create the description key */ + Status = NtCreateKey(&KeyHandle, + KEY_READ | KEY_WRITE, + &ObjectAttributes, + 0, + NULL, + 0, + &Disposition); + if (!NT_SUCCESS(Status)) return Status; + + /* Nobody should've created this key yet! */ + //ASSERT(Disposition == REG_CREATED_NEW_KEY); + + /* Allocate the configuration data buffer */ + CmpConfigurationData = ExAllocatePoolWithTag(PagedPool, + CmpConfigurationAreaSize, + TAG_CM); + if (!CmpConfigurationData) return STATUS_INSUFFICIENT_RESOURCES; + + /* Check if we got anything from NTLDR */ + if (LoaderBlock->ConfigurationRoot) + { + ASSERTMSG("NTLDR ARC Hardware Tree Not Supported!\n", FALSE); + } + else + { + /* Nothing else to do */ + Status = STATUS_SUCCESS; + } + + /* Close our handle, free the buffer and return status */ + ExFreePool(CmpConfigurationData); + NtClose(KeyHandle); + return Status; +} + diff --git a/reactos/ntoskrnl/config/cmse.c b/reactos/ntoskrnl/config/cmse.c new file mode 100644 index 00000000000..c8299608fc6 --- /dev/null +++ b/reactos/ntoskrnl/config/cmse.c @@ -0,0 +1,138 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/config/cmse.c + * PURPOSE: Configuration Manager - Security Subsystem Interface + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include "ntoskrnl.h" +#include "cm.h" +#define NDEBUG +#include "debug.h" + +/* GLOBALS *******************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PSECURITY_DESCRIPTOR +NTAPI +CmpHiveRootSecurityDescriptor(VOID) +{ + NTSTATUS Status; + PSECURITY_DESCRIPTOR SecurityDescriptor; + PACL Acl, AclCopy; + PSID Sid[3]; + SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; + SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; + ULONG AceLength, AclLength, SidLength; + PACE_HEADER AceHeader; + ULONG i; + PAGED_CODE(); + + /* Phase 1: Allocate SIDs */ + SidLength = RtlLengthRequiredSid(1); + Sid[0] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM); + Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM); + Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM); + SidLength = RtlLengthRequiredSid(2); + Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM); + + /* Make sure all SIDs were allocated */ + if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3])) + { + /* Bugcheck */ + KEBUGCHECKEX(REGISTRY_ERROR, 2, 1, 0, 0); + } + + /* Phase 2: Initialize all SIDs */ + Status = RtlInitializeSid(Sid[0], &WorldAuthority, 1); + Status |= RtlInitializeSid(Sid[1], &NtAuthority, 1); + Status |= RtlInitializeSid(Sid[2], &NtAuthority, 1); + Status |= RtlInitializeSid(Sid[3], &NtAuthority, 2); + if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 2, 2, 0, 0); + + /* Phase 2: Setup SID Sub Authorities */ + *RtlSubAuthoritySid(Sid[0], 0) = SECURITY_WORLD_RID; + *RtlSubAuthoritySid(Sid[1], 0) = SECURITY_RESTRICTED_CODE_RID; + *RtlSubAuthoritySid(Sid[2], 0) = SECURITY_LOCAL_SYSTEM_RID; + *RtlSubAuthoritySid(Sid[3], 0) = SECURITY_BUILTIN_DOMAIN_RID; + *RtlSubAuthoritySid(Sid[3], 1) = DOMAIN_ALIAS_RID_ADMINS; + + /* Make sure all SIDs are valid */ + ASSERT(RtlValidSid(Sid[0])); + ASSERT(RtlValidSid(Sid[1])); + ASSERT(RtlValidSid(Sid[2])); + ASSERT(RtlValidSid(Sid[3])); + + /* Phase 3: Calculate ACL Length */ + AclLength = sizeof(ACL); + for (i = 0; i < 4; i++) + { + /* This is what MSDN says to do */ + AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart); + AceLength += SeLengthSid(Sid[i]); + AclLength += AceLength; + } + + /* Phase 3: Allocate the ACL */ + Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CM); + if (!Acl) KEBUGCHECKEX(REGISTRY_ERROR, 2, 3, 0, 0); + + /* Phase 4: Create the ACL */ + Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION); + if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 2, 4, Status, 0); + + /* Phase 5: Build the ACL */ + Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[0]); + Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[1]); + Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[2]); + Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[3]); + if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 2, 5, Status, 0); + + /* Phase 5: Make the ACEs inheritable */ + Status = RtlGetAce(Acl, 0,( PVOID*)&AceHeader); + ASSERT(NT_SUCCESS(Status)); + AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; + Status = RtlGetAce(Acl, 1, (PVOID*)&AceHeader); + ASSERT(NT_SUCCESS(Status)); + AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; + Status = RtlGetAce(Acl, 2, (PVOID*)&AceHeader); + ASSERT(NT_SUCCESS(Status)); + AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; + Status = RtlGetAce(Acl, 3, (PVOID*)&AceHeader); + ASSERT(NT_SUCCESS(Status)); + AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; + + /* Phase 6: Allocate the security descriptor and make space for the ACL */ + SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, + sizeof(SECURITY_DESCRIPTOR) + + AclLength, + TAG_CM); + if (!SecurityDescriptor) KEBUGCHECKEX(REGISTRY_ERROR, 2, 6, 0, 0); + + /* Phase 6: Make a copy of the ACL */ + AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1); + RtlCopyMemory(AclCopy, Acl, AclLength); + + /* Phase 7: Create the security descriptor */ + Status = RtlCreateSecurityDescriptor(SecurityDescriptor, + SECURITY_DESCRIPTOR_REVISION); + if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 2, 7, Status, 0); + + /* Phase 8: Set the ACL as a DACL */ + Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, + TRUE, + AclCopy, + FALSE); + if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 2, 8, Status, 0); + + /* Free the SIDs and original ACL */ + for (i = 0; i < 4; i++) ExFreePool(Sid[i]); + ExFreePool(Acl); + + /* Return the security descriptor */ + return SecurityDescriptor; +} diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 4144176bed0..2cf63485ad6 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -98,6 +98,7 @@ cmmapvw.c cmname.c cmparse.c + cmse.c cmsecach.c cmsysini.c cmvalue.c