windows-nt/Source/XPSP1/NT/base/ntos/io/iomgr/arcsec.c
2020-09-26 16:20:57 +08:00

345 lines
9.2 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}