345 lines
9.2 KiB
C
345 lines
9.2 KiB
C
/*++
|
||
|
||
Copyright (c) 1989-1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
arcsec.c
|
||
|
||
Abstract:
|
||
|
||
This module contains subroutines for protecting the system
|
||
partition on an ARC system.
|
||
|
||
Author:
|
||
|
||
Jim Kelly (JimK) 13-Jan-1993
|
||
|
||
Environment:
|
||
|
||
Kernel mode - system initialization
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "iomgr.h"
|
||
|
||
//
|
||
// Define procedures local to this module.
|
||
//
|
||
|
||
NTSTATUS
|
||
IopApplySystemPartitionProt(
|
||
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT,IopProtectSystemPartition)
|
||
#pragma alloc_text(INIT,IopApplySystemPartitionProt)
|
||
#endif
|
||
|
||
//
|
||
// This name must match the name use by the DISK MANAGER utility.
|
||
// The Disk Manager creates and sets the value of this registry
|
||
// key. We only look at it.
|
||
//
|
||
|
||
#define IOP_SYSTEM_PART_PROT_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa"
|
||
#define IOP_SYSTEM_PART_PROT_VALUE L"Protect System Partition"
|
||
|
||
BOOLEAN
|
||
IopProtectSystemPartition(
|
||
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine assigns protection to the system partition of an
|
||
ARC system, if necessary. If this is not an ARC system, or
|
||
the system partition does not need to be protected, then this
|
||
routine does nothing.
|
||
|
||
|
||
Arguments:
|
||
|
||
LoaderBlock - Supplies a pointer to the loader parameter block that was
|
||
created by the OS Loader.
|
||
|
||
Return Value:
|
||
|
||
The function value is a BOOLEAN indicating whether or not protection
|
||
has been appropriately applied. TRUE indicates no errors were
|
||
encountered. FALSE indicates an error was encountered.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// We only entertain the possibility of assigning protection
|
||
// to the system partition if we are an ARC system. For the
|
||
// time being, the best way to determine if you are an ARC
|
||
// system is to see if you aren't and X86 machine. DavidRo
|
||
// believes that at some point in the future we will have
|
||
// ARC compliant X86 machines. At that point in time, we
|
||
// will need to change the following #ifdef's into something
|
||
// that does a run-time determination.
|
||
//
|
||
|
||
#ifdef i386 // if (!ARC-Compliant system)
|
||
|
||
|
||
//
|
||
// Nothing to do for non-ARC systems
|
||
//
|
||
|
||
return(TRUE);
|
||
|
||
|
||
#else // ARC-COMPLIANT system
|
||
|
||
NTSTATUS status;
|
||
NTSTATUS tmpStatus;
|
||
HANDLE keyHandle;
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
UNICODE_STRING keyName;
|
||
UNICODE_STRING valueName;
|
||
ULONG resultLength;
|
||
ULONG keyBuffer[sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( ULONG )];
|
||
PKEY_VALUE_PARTIAL_INFORMATION keyValue;
|
||
|
||
//
|
||
// This is an ARC system. Attempt to retrieve information from the registry
|
||
// indicating whether or not we should protect the system partition.
|
||
//
|
||
|
||
RtlInitUnicodeString( &keyName, IOP_SYSTEM_PART_PROT_KEY );
|
||
InitializeObjectAttributes( &objectAttributes,
|
||
&keyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL );
|
||
status = NtOpenKey( &keyHandle, KEY_READ, &objectAttributes);
|
||
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
keyValue = (PKEY_VALUE_PARTIAL_INFORMATION) &keyBuffer[0];
|
||
RtlInitUnicodeString( &valueName, IOP_SYSTEM_PART_PROT_VALUE );
|
||
status = NtQueryValueKey( keyHandle,
|
||
&valueName,
|
||
KeyValuePartialInformation,
|
||
keyValue,
|
||
sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( ULONG ),
|
||
&resultLength );
|
||
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
PBOOLEAN applyIt;
|
||
|
||
//
|
||
// The appropriate information was located in the registry. Now
|
||
// determine whether or not is indicates that protection is to be
|
||
// applied.
|
||
//
|
||
|
||
applyIt = &(keyValue->Data[0]);
|
||
|
||
if (*applyIt) {
|
||
status = IopApplySystemPartitionProt( LoaderBlock );
|
||
}
|
||
}
|
||
|
||
tmpStatus = NtClose( keyHandle );
|
||
ASSERT(NT_SUCCESS( tmpStatus ));
|
||
}
|
||
|
||
|
||
return TRUE;
|
||
|
||
#endif // ARC-COMPLIANT system
|
||
}
|
||
|
||
NTSTATUS
|
||
IopApplySystemPartitionProt(
|
||
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine applies protection to the system partition that
|
||
prevents all users except administrators from accessing the
|
||
partition.
|
||
|
||
|
||
This routine is only used during system initialization.
|
||
As such, all memory allocations are expected to succeed.
|
||
Success is tested only with assertions.
|
||
|
||
|
||
Arguments:
|
||
|
||
LoaderBlock - Supplies a pointer to the loader parameter block that was
|
||
created by the OS Loader.
|
||
|
||
Return Value:
|
||
|
||
The function value is the final status from attempting to set the system
|
||
partition protection.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS status;
|
||
PACL dacl;
|
||
SECURITY_DESCRIPTOR securityDescriptor;
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
ULONG length;
|
||
CHAR ArcNameFmt[12];
|
||
|
||
ArcNameFmt[0] = '\\';
|
||
ArcNameFmt[1] = 'A';
|
||
ArcNameFmt[2] = 'r';
|
||
ArcNameFmt[3] = 'c';
|
||
ArcNameFmt[4] = 'N';
|
||
ArcNameFmt[5] = 'a';
|
||
ArcNameFmt[6] = 'm';
|
||
ArcNameFmt[7] = 'e';
|
||
ArcNameFmt[8] = '\\';
|
||
ArcNameFmt[9] = '%';
|
||
ArcNameFmt[10] = 's';
|
||
ArcNameFmt[11] = '\0';
|
||
|
||
ASSERT( ARGUMENT_PRESENT( LoaderBlock ) );
|
||
ASSERT( ARGUMENT_PRESENT( LoaderBlock->ArcHalDeviceName ) );
|
||
|
||
//
|
||
// Build an appropriate discretionary ACL.
|
||
//
|
||
|
||
length = (ULONG) sizeof( ACL ) +
|
||
( 2 * ((ULONG) sizeof( ACCESS_ALLOWED_ACE ))) +
|
||
SeLengthSid( SeLocalSystemSid ) +
|
||
SeLengthSid( SeAliasAdminsSid ) +
|
||
8; // The 8 is just for good measure
|
||
|
||
dacl = (PACL) ExAllocatePool( PagedPool, length );
|
||
if (!dacl) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
status = RtlCreateAcl( dacl, length, ACL_REVISION2 );
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
status = RtlAddAccessAllowedAce( dacl,
|
||
ACL_REVISION2,
|
||
GENERIC_ALL,
|
||
SeLocalSystemSid );
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
status = RtlAddAccessAllowedAce( dacl,
|
||
ACL_REVISION2,
|
||
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | READ_CONTROL,
|
||
SeAliasAdminsSid );
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
//
|
||
// Put it in a security descriptor so that it may be applied to
|
||
// the system partition device.
|
||
//
|
||
|
||
status = RtlCreateSecurityDescriptor( &securityDescriptor,
|
||
SECURITY_DESCRIPTOR_REVISION );
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
status = RtlSetDaclSecurityDescriptor( &securityDescriptor,
|
||
TRUE,
|
||
dacl,
|
||
FALSE );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!NT_SUCCESS( status )) {
|
||
ExFreePool( dacl );
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Open the ARC boot device and apply the ACL.
|
||
//
|
||
|
||
{
|
||
NTSTATUS tmpStatus;
|
||
UCHAR deviceNameBuffer[256];
|
||
STRING deviceNameString;
|
||
UNICODE_STRING deviceNameUnicodeString;
|
||
HANDLE deviceHandle;
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
|
||
//
|
||
// Begin by formulating the ARC name of the boot device in the ARC
|
||
// name space.
|
||
//
|
||
|
||
sprintf( deviceNameBuffer,
|
||
ArcNameFmt,
|
||
LoaderBlock->ArcHalDeviceName );
|
||
|
||
RtlInitAnsiString( &deviceNameString, deviceNameBuffer );
|
||
|
||
status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
|
||
&deviceNameString,
|
||
TRUE );
|
||
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
InitializeObjectAttributes( &objectAttributes,
|
||
&deviceNameUnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL );
|
||
|
||
status = ZwOpenFile( &deviceHandle,
|
||
WRITE_DAC,
|
||
&objectAttributes,
|
||
&ioStatusBlock,
|
||
TRUE,
|
||
0 );
|
||
|
||
RtlFreeUnicodeString( &deviceNameUnicodeString );
|
||
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
|
||
//
|
||
// Apply the ACL built above to the system partition device
|
||
// object.
|
||
//
|
||
|
||
status = ZwSetSecurityObject( deviceHandle,
|
||
DACL_SECURITY_INFORMATION,
|
||
&securityDescriptor );
|
||
|
||
tmpStatus = NtClose( deviceHandle );
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Free the memory used to hold the ACL.
|
||
//
|
||
|
||
ExFreePool( dacl );
|
||
|
||
return status;
|
||
}
|