windows-nt/Source/XPSP1/NT/base/fs/rdr2/bowser/bowsecur.c
2020-09-26 16:20:57 +08:00

509 lines
11 KiB
C

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
fsctl.c
Abstract:
This module implements the NtDeviceIoControlFile API's for the NT datagram
receiver (bowser).
Author:
Eyal Schwartz (EyalS) Dec-9-1998
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Extern defined from #include <ob.h>.
// Couldn't include ob.h due to redefinition conflicts. We had attempted to change ntos\makefil0
// so as to include it in ntsrv.h, but decided we shouldn't expose it. This does the job.
//
NTSTATUS
ObGetObjectSecurity(
IN PVOID Object,
OUT PSECURITY_DESCRIPTOR *SecurityDescriptor,
OUT PBOOLEAN MemoryAllocated
);
VOID
ObReleaseObjectSecurity(
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN BOOLEAN MemoryAllocated
);
// defines //
// pool tag
#define BOW_SECURITY_POOL_TAG ( (ULONG)'seLB' )
// local prototypes //
NTSTATUS
BowserBuildDeviceAcl(
OUT PACL *DeviceAcl
);
NTSTATUS
BowserCreateAdminSecurityDescriptor(
IN PDEVICE_OBJECT pDevice
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(SECUR, BowserBuildDeviceAcl)
#pragma alloc_text(SECUR, BowserCreateAdminSecurityDescriptor)
#pragma alloc_text(SECUR, BowserInitializeSecurity)
#pragma alloc_text(SECUR, BowserSecurityCheck )
#endif
SECURITY_DESCRIPTOR
*g_pBowSecurityDescriptor = NULL;
// function implementation //
NTSTATUS
BowserBuildDeviceAcl(
OUT PACL *DeviceAcl
)
/*++
Routine Description:
This routine builds an ACL which gives Administrators and LocalSystem
principals full access. All other principals have no access.
Lifted form \nt\private\ntos\afd\init.c!AfdBuildDeviceAcl()
Arguments:
DeviceAcl - Output pointer to the new ACL.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{
PGENERIC_MAPPING GenericMapping;
PSID AdminsSid;
PSID SystemSid;
ULONG AclLength;
NTSTATUS Status;
ACCESS_MASK AccessMask = GENERIC_ALL;
PACL NewAcl;
//
// Enable access to all the globally defined SIDs
//
GenericMapping = IoGetFileObjectGenericMapping();
RtlMapGenericMask( &AccessMask, GenericMapping );
// SeEnableAccessToExports();
AdminsSid = SeExports->SeAliasAdminsSid;
SystemSid = SeExports->SeLocalSystemSid;
AclLength = sizeof( ACL ) +
2 * sizeof( ACCESS_ALLOWED_ACE ) +
RtlLengthSid( AdminsSid ) +
RtlLengthSid( SystemSid ) -
2 * sizeof( ULONG );
NewAcl = ExAllocatePoolWithTag(
PagedPool,
AclLength,
BOW_SECURITY_POOL_TAG
);
if (NewAcl == NULL) {
return( STATUS_INSUFFICIENT_RESOURCES );
}
Status = RtlCreateAcl (NewAcl, AclLength, ACL_REVISION );
if (!NT_SUCCESS( Status )) {
ExFreePool(
NewAcl
);
return( Status );
}
Status = RtlAddAccessAllowedAce (
NewAcl,
ACL_REVISION,
AccessMask,
AdminsSid
);
ASSERT( NT_SUCCESS( Status ));
Status = RtlAddAccessAllowedAce (
NewAcl,
ACL_REVISION,
AccessMask,
SystemSid
);
ASSERT( NT_SUCCESS( Status ));
*DeviceAcl = NewAcl;
return( STATUS_SUCCESS );
} // BowBuildDeviceAcl
NTSTATUS
BowserCreateAdminSecurityDescriptor(
IN PDEVICE_OBJECT pDevice
)
/*++
Routine Description:
This routine creates a security descriptor which gives access
only to Administrtors and LocalSystem. This descriptor is used
to access check raw endpoint opens and exclisive access to transport
addresses.
LIfted form \nt\private\ntos\afd\init.c!AfdCreateAdminSecurityDescriptor()
Arguments:
None.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{
PACL rawAcl = NULL;
NTSTATUS status;
BOOLEAN memoryAllocated = FALSE;
PSECURITY_DESCRIPTOR BowSecurityDescriptor;
ULONG BowSecurityDescriptorLength;
CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
PSECURITY_DESCRIPTOR localSecurityDescriptor =
(PSECURITY_DESCRIPTOR) &buffer;
PSECURITY_DESCRIPTOR localBowAdminSecurityDescriptor;
SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
#if 1
//
// this is the way AFD gets the object SD (the preferred way).
//
status = ObGetObjectSecurity(
pDevice,
&BowSecurityDescriptor,
&memoryAllocated
);
if (!NT_SUCCESS(status)) {
KdPrint((
"Bowser: Unable to get security descriptor, error: %x\n",
status
));
ASSERT(memoryAllocated == FALSE);
return(status);
}
#else
//
// Get a pointer to the security descriptor from the our device object.
// If we can't access ob api's due to include dependencies, we'll use it directly.
// ** Need to verify it is legal (I doubt it)**
// Need to dump this as soon as we can fix ntos\makefil0 to include ob.h in
// the generated ntsrv.h
//
BowSecurityDescriptor = pDevice->SecurityDescriptor;
if ( !BowSecurityDescriptor )
{
KdPrint((
"Bowser: Unable to get security descriptor, error: %x\n",
status
));
return STATUS_INVALID_SECURITY_DESCR;
}
#endif
//
// Build a local security descriptor with an ACL giving only
// administrators and system access.
//
status = BowserBuildDeviceAcl(&rawAcl);
if (!NT_SUCCESS(status)) {
KdPrint(("Bowser: Unable to create Raw ACL, error: %x\n", status));
goto error_exit;
}
(VOID) RtlCreateSecurityDescriptor(
localSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION
);
(VOID) RtlSetDaclSecurityDescriptor(
localSecurityDescriptor,
TRUE,
rawAcl,
FALSE
);
//
// Make a copy of the Bow descriptor. This copy will be the raw descriptor.
//
BowSecurityDescriptorLength = RtlLengthSecurityDescriptor(
BowSecurityDescriptor
);
localBowAdminSecurityDescriptor = ExAllocatePoolWithTag (
PagedPool,
BowSecurityDescriptorLength,
BOW_SECURITY_POOL_TAG
);
if (localBowAdminSecurityDescriptor == NULL) {
KdPrint(("Bowser: couldn't allocate security descriptor\n"));
goto error_exit;
}
RtlMoveMemory(
localBowAdminSecurityDescriptor,
BowSecurityDescriptor,
BowSecurityDescriptorLength
);
g_pBowSecurityDescriptor = localBowAdminSecurityDescriptor;
//
// Now apply the local descriptor to the raw descriptor.
//
status = SeSetSecurityDescriptorInfo(
NULL,
&securityInformation,
localSecurityDescriptor,
&g_pBowSecurityDescriptor,
PagedPool,
IoGetFileObjectGenericMapping()
);
if (!NT_SUCCESS(status)) {
KdPrint(("Bowser: SeSetSecurity failed, %lx\n", status));
ASSERT (g_pBowSecurityDescriptor==localBowAdminSecurityDescriptor);
ExFreePool (g_pBowSecurityDescriptor);
g_pBowSecurityDescriptor = NULL;
goto error_exit;
}
if (g_pBowSecurityDescriptor!=localBowAdminSecurityDescriptor) {
ExFreePool (localBowAdminSecurityDescriptor);
}
status = STATUS_SUCCESS;
error_exit:
#if 1
//
// see remark above
//
ObReleaseObjectSecurity(
BowSecurityDescriptor,
memoryAllocated
);
#endif
if (rawAcl!=NULL) {
ExFreePool(
rawAcl
);
}
return(status);
}
NTSTATUS
BowserInitializeSecurity(
IN PDEVICE_OBJECT pDevice
)
/*++
Routine Description (BowserInitializeSecurity):
Initialize Bowser security.
- Create default bowser security descriptor based on device sercurity
Arguments:
device: opened device
Return Value:
Remarks:
None.
--*/
{
NTSTATUS Status;
if ( g_pBowSecurityDescriptor )
{
return STATUS_SUCCESS;
}
ASSERT(pDevice);
Status = BowserCreateAdminSecurityDescriptor ( pDevice );
return Status;
}
BOOLEAN
BowserSecurityCheck (
PIRP Irp,
PIO_STACK_LOCATION IrpSp,
PNTSTATUS Status
)
/*++
Routine Description:
Lifted as is from \\index1\src\nt\private\ntos\afd\create.c!AfdPerformSecurityCheck
Compares security context of the endpoint creator to that
of the administrator and local system.
Note: This is currently called only on IOCTL Irps. IOCRTLs don't have a create security
context (only creates...), thus we should always capture the security context rather
then attempting to extract it from the IrpSp.
Arguments:
Irp - Pointer to I/O request packet.
IrpSp - pointer to the IO stack location to use for this request.
Status - returns status generated by access check on failure.
Return Value:
TRUE - the socket creator has admin or local system privilige
FALSE - the socket creator is just a plain user
--*/
{
BOOLEAN accessGranted;
PACCESS_STATE accessState;
PIO_SECURITY_CONTEXT securityContext;
SECURITY_SUBJECT_CONTEXT SubjectContext;
PSECURITY_SUBJECT_CONTEXT pSubjectContext = &SubjectContext;
ACCESS_MASK grantedAccess;
PGENERIC_MAPPING GenericMapping;
ACCESS_MASK AccessMask = GENERIC_ALL;
PAGED_CODE();
ASSERT (g_pBowSecurityDescriptor);
//
// Get security context from process.
//
SeCaptureSubjectContext(&SubjectContext);
SeLockSubjectContext(pSubjectContext);
//
// Build access evaluation:
// Enable access to all the globally defined SIDs
//
GenericMapping = IoGetFileObjectGenericMapping();
RtlMapGenericMask( &AccessMask, GenericMapping );
//
// AccessCheck test
//
accessGranted = SeAccessCheck(
g_pBowSecurityDescriptor,
pSubjectContext,
TRUE,
AccessMask,
0,
NULL,
IoGetFileObjectGenericMapping(),
(KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
? UserMode
: Irp->RequestorMode),
&grantedAccess,
Status
);
//
// Verify consistency.
//
#if DBG
if (accessGranted) {
ASSERT (NT_SUCCESS (*Status));
}
else {
ASSERT (!NT_SUCCESS (*Status));
}
#endif
//
// Unlock & Release security subject context
//
SeUnlockSubjectContext(pSubjectContext);
SeReleaseSubjectContext(pSubjectContext);
return accessGranted;
}