mirror of
https://github.com/reactos/reactos.git
synced 2024-08-19 18:02:55 +00:00
1110 lines
33 KiB
C++
1110 lines
33 KiB
C++
////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
|
|
// All rights reserved
|
|
// This file was released under the GPLv2 on June 2015.
|
|
////////////////////////////////////////////////////////////////////
|
|
/*************************************************************************
|
|
*
|
|
* File: SecurSup.cpp
|
|
*
|
|
* Module: UDF File System Driver (Kernel mode execution only)
|
|
*
|
|
* Description:
|
|
* Contains code to handle the "Get/Set Security" dispatch entry points.
|
|
*
|
|
*************************************************************************/
|
|
|
|
#include "udffs.h"
|
|
|
|
// define the file specific bug-check id
|
|
#define UDF_BUG_CHECK_ID UDF_FILE_SECURITY
|
|
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
|
|
NTSTATUS UDFConvertToSelfRelative(
|
|
IN OUT PSECURITY_DESCRIPTOR* SecurityDesc);
|
|
|
|
/*UCHAR FullControlSD[] = {
|
|
0x01, 0x00, 0x04, 0x80, 0x4c, 0x00, 0x00, 0x00,
|
|
0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x38, 0x00,
|
|
0x02, 0x00, 0x00, 0x00, 0x00, 0x09, 0x18, 0x00,
|
|
0x00, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00,
|
|
0xff, 0x01, 0x1f, 0x00, 0x01, 0x01, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
|
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
|
0x00, 0x00, 0x00, 0x00
|
|
};*/
|
|
|
|
/*************************************************************************
|
|
*
|
|
* Function: UDFGetSecurity()
|
|
*
|
|
* Description:
|
|
*
|
|
* Expected Interrupt Level (for execution) :
|
|
*
|
|
* IRQL_PASSIVE_LEVEL
|
|
*
|
|
* Return Value: Irrelevant.
|
|
*
|
|
*************************************************************************/
|
|
NTSTATUS
|
|
UDFGetSecurity(
|
|
IN PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
|
IN PIRP Irp) // I/O Request Packet
|
|
{
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
|
PtrUDFIrpContext PtrIrpContext = NULL;
|
|
BOOLEAN AreWeTopLevel = FALSE;
|
|
|
|
UDFPrint(("UDFGetSecurity\n"));
|
|
// BrutePoint();
|
|
|
|
FsRtlEnterFileSystem();
|
|
ASSERT(DeviceObject);
|
|
ASSERT(Irp);
|
|
|
|
// set the top level context
|
|
AreWeTopLevel = UDFIsIrpTopLevel(Irp);
|
|
ASSERT(!UDFIsFSDevObj(DeviceObject));
|
|
// Call the common Lock Control routine, with blocking allowed if
|
|
// synchronous
|
|
_SEH2_TRY {
|
|
|
|
// get an IRP context structure and issue the request
|
|
PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
|
|
if(PtrIrpContext) {
|
|
RC = UDFCommonGetSecurity(PtrIrpContext, Irp);
|
|
} else {
|
|
RC = STATUS_INSUFFICIENT_RESOURCES;
|
|
Irp->IoStatus.Status = RC;
|
|
Irp->IoStatus.Information = 0;
|
|
// complete the IRP
|
|
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
|
|
}
|
|
|
|
} __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
|
|
|
|
RC = UDFExceptionHandler(PtrIrpContext, Irp);
|
|
|
|
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
|
|
}
|
|
|
|
if (AreWeTopLevel) {
|
|
IoSetTopLevelIrp(NULL);
|
|
}
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
return(RC);
|
|
} // end UDFGetSecurity()
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
* Function: UDFCommonGetSecurity()
|
|
*
|
|
* Description:
|
|
* This is the common routine for getting Security (ACL) called
|
|
* by both the fsd and fsp threads
|
|
*
|
|
* Expected Interrupt Level (for execution) :
|
|
*
|
|
* IRQL_PASSIVE_LEVEL
|
|
*
|
|
* Return Value: Irrelevant
|
|
*
|
|
*************************************************************************/
|
|
NTSTATUS
|
|
UDFCommonGetSecurity(
|
|
IN PtrUDFIrpContext PtrIrpContext,
|
|
IN PIRP Irp)
|
|
{
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION IrpSp = NULL;
|
|
BOOLEAN PostRequest = FALSE;
|
|
BOOLEAN CanWait = FALSE;
|
|
PtrUDFNTRequiredFCB NtReqFcb = NULL;
|
|
BOOLEAN AcquiredFCB = FALSE;
|
|
PFILE_OBJECT FileObject = NULL;
|
|
PtrUDFFCB Fcb = NULL;
|
|
PtrUDFCCB Ccb = NULL;
|
|
PVOID PtrSystemBuffer = NULL;
|
|
ULONG BufferLength = 0;
|
|
|
|
UDFPrint(("UDFCommonGetSecurity\n"));
|
|
|
|
_SEH2_TRY {
|
|
|
|
// First, get a pointer to the current I/O stack location.
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
ASSERT(IrpSp);
|
|
|
|
FileObject = IrpSp->FileObject;
|
|
ASSERT(FileObject);
|
|
|
|
// Get the FCB and CCB pointers.
|
|
Ccb = (PtrUDFCCB)(FileObject->FsContext2);
|
|
ASSERT(Ccb);
|
|
Fcb = Ccb->Fcb;
|
|
ASSERT(Fcb);
|
|
|
|
/* if(!Fcb->Vcb->ReadSecurity)
|
|
try_return(RC = STATUS_NOT_IMPLEMENTED);*/
|
|
|
|
NtReqFcb = Fcb->NTRequiredFCB;
|
|
CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
|
|
|
|
// Acquire the FCB resource shared
|
|
UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
|
|
if (!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) {
|
|
// if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), CanWait)) {
|
|
PostRequest = TRUE;
|
|
try_return(RC = STATUS_PENDING);
|
|
}
|
|
AcquiredFCB = TRUE;
|
|
|
|
PtrSystemBuffer = UDFGetCallersBuffer(PtrIrpContext, Irp);
|
|
if(!PtrSystemBuffer)
|
|
try_return(RC = STATUS_INVALID_USER_BUFFER);
|
|
BufferLength = IrpSp->Parameters.QuerySecurity.Length;
|
|
|
|
if(!NtReqFcb->SecurityDesc) {
|
|
RC = UDFAssignAcl(Fcb->Vcb, FileObject, Fcb, NtReqFcb);
|
|
if(!NT_SUCCESS(RC))
|
|
try_return(RC);
|
|
}
|
|
|
|
_SEH2_TRY {
|
|
RC = SeQuerySecurityDescriptorInfo(&(IrpSp->Parameters.QuerySecurity.SecurityInformation),
|
|
(PSECURITY_DESCRIPTOR)PtrSystemBuffer,
|
|
&BufferLength,
|
|
&(NtReqFcb->SecurityDesc) );
|
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
|
RC = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
try_exit: NOTHING;
|
|
|
|
} _SEH2_FINALLY {
|
|
|
|
// Release the FCB resources if acquired.
|
|
if (AcquiredFCB) {
|
|
UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
|
|
UDFReleaseResource(&(NtReqFcb->MainResource));
|
|
AcquiredFCB = FALSE;
|
|
}
|
|
|
|
if (PostRequest) {
|
|
// Perform appropriate post related processing here
|
|
RC = UDFPostRequest(PtrIrpContext, Irp);
|
|
} else
|
|
if(!AbnormalTermination()) {
|
|
Irp->IoStatus.Status = RC;
|
|
Irp->IoStatus.Information = BufferLength;
|
|
// Free up the Irp Context
|
|
UDFReleaseIrpContext(PtrIrpContext);
|
|
// complete the IRP
|
|
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
|
|
}
|
|
|
|
} // end of "__finally" processing
|
|
|
|
return(RC);
|
|
}
|
|
|
|
#ifndef UDF_READ_ONLY_BUILD
|
|
/*************************************************************************
|
|
*
|
|
* Function: UDFSetSecurity()
|
|
*
|
|
* Description:
|
|
*
|
|
* Expected Interrupt Level (for execution) :
|
|
*
|
|
* IRQL_PASSIVE_LEVEL
|
|
*
|
|
* Return Value: Irrelevant.
|
|
*
|
|
*************************************************************************/
|
|
NTSTATUS
|
|
UDFSetSecurity(
|
|
IN PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
|
IN PIRP Irp) // I/O Request Packet
|
|
{
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
|
PtrUDFIrpContext PtrIrpContext = NULL;
|
|
BOOLEAN AreWeTopLevel = FALSE;
|
|
|
|
UDFPrint(("UDFSetSecurity\n"));
|
|
// BrutePoint();
|
|
|
|
FsRtlEnterFileSystem();
|
|
ASSERT(DeviceObject);
|
|
ASSERT(Irp);
|
|
|
|
// set the top level context
|
|
AreWeTopLevel = UDFIsIrpTopLevel(Irp);
|
|
// Call the common Lock Control routine, with blocking allowed if
|
|
// synchronous
|
|
_SEH2_TRY {
|
|
|
|
// get an IRP context structure and issue the request
|
|
PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
|
|
if(PtrIrpContext) {
|
|
RC = UDFCommonSetSecurity(PtrIrpContext, Irp);
|
|
} else {
|
|
RC = STATUS_INSUFFICIENT_RESOURCES;
|
|
Irp->IoStatus.Status = RC;
|
|
Irp->IoStatus.Information = 0;
|
|
// complete the IRP
|
|
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
|
|
}
|
|
|
|
} __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
|
|
|
|
RC = UDFExceptionHandler(PtrIrpContext, Irp);
|
|
|
|
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
|
|
}
|
|
|
|
if (AreWeTopLevel) {
|
|
IoSetTopLevelIrp(NULL);
|
|
}
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
return(RC);
|
|
} // end UDFSetSecurity()
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
* Function: UDFCommonSetSecurity()
|
|
*
|
|
* Description:
|
|
* This is the common routine for getting Security (ACL) called
|
|
* by both the fsd and fsp threads
|
|
*
|
|
* Expected Interrupt Level (for execution) :
|
|
*
|
|
* IRQL_PASSIVE_LEVEL
|
|
*
|
|
* Return Value: Irrelevant
|
|
*
|
|
*************************************************************************/
|
|
NTSTATUS
|
|
UDFCommonSetSecurity(
|
|
IN PtrUDFIrpContext PtrIrpContext,
|
|
IN PIRP Irp)
|
|
{
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION IrpSp = NULL;
|
|
BOOLEAN PostRequest = FALSE;
|
|
BOOLEAN CanWait = FALSE;
|
|
PtrUDFNTRequiredFCB NtReqFcb = NULL;
|
|
BOOLEAN AcquiredFCB = FALSE;
|
|
PFILE_OBJECT FileObject = NULL;
|
|
PtrUDFFCB Fcb = NULL;
|
|
PtrUDFCCB Ccb = NULL;
|
|
ACCESS_MASK DesiredAccess = 0;
|
|
|
|
UDFPrint(("UDFCommonSetSecurity\n"));
|
|
|
|
_SEH2_TRY {
|
|
|
|
// First, get a pointer to the current I/O stack location.
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
ASSERT(IrpSp);
|
|
|
|
FileObject = IrpSp->FileObject;
|
|
ASSERT(FileObject);
|
|
|
|
// Get the FCB and CCB pointers.
|
|
Ccb = (PtrUDFCCB)(FileObject->FsContext2);
|
|
ASSERT(Ccb);
|
|
Fcb = Ccb->Fcb;
|
|
ASSERT(Fcb);
|
|
|
|
if(!Fcb->Vcb->WriteSecurity)
|
|
try_return(RC = STATUS_NOT_IMPLEMENTED);
|
|
|
|
NtReqFcb = Fcb->NTRequiredFCB;
|
|
CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
|
|
|
|
// Acquire the FCB resource exclusive
|
|
UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
|
|
if (!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) {
|
|
PostRequest = TRUE;
|
|
try_return(RC = STATUS_PENDING);
|
|
}
|
|
AcquiredFCB = TRUE;
|
|
|
|
//OWNER_SECURITY_INFORMATION
|
|
if(IrpSp->Parameters.SetSecurity.SecurityInformation & OWNER_SECURITY_INFORMATION)
|
|
DesiredAccess |= WRITE_OWNER;
|
|
//GROUP_SECURITY_INFORMATION
|
|
if(IrpSp->Parameters.SetSecurity.SecurityInformation & GROUP_SECURITY_INFORMATION)
|
|
DesiredAccess |= WRITE_OWNER;
|
|
//DACL_SECURITY_INFORMATION
|
|
if(IrpSp->Parameters.SetSecurity.SecurityInformation & DACL_SECURITY_INFORMATION)
|
|
DesiredAccess |= WRITE_DAC;
|
|
//SACL_SECURITY_INFORMATION
|
|
if(IrpSp->Parameters.SetSecurity.SecurityInformation & SACL_SECURITY_INFORMATION)
|
|
DesiredAccess |= ACCESS_SYSTEM_SECURITY;
|
|
|
|
_SEH2_TRY {
|
|
UDFConvertToSelfRelative(&(NtReqFcb->SecurityDesc));
|
|
|
|
KdDump(NtReqFcb->SecurityDesc, RtlLengthSecurityDescriptor(NtReqFcb->SecurityDesc));
|
|
UDFPrint(("\n"));
|
|
|
|
RC = SeSetSecurityDescriptorInfo(/*FileObject*/ NULL,
|
|
&(IrpSp->Parameters.SetSecurity.SecurityInformation),
|
|
IrpSp->Parameters.SetSecurity.SecurityDescriptor,
|
|
&(NtReqFcb->SecurityDesc),
|
|
NonPagedPool,
|
|
IoGetFileObjectGenericMapping() );
|
|
|
|
KdDump(NtReqFcb->SecurityDesc, RtlLengthSecurityDescriptor(NtReqFcb->SecurityDesc));
|
|
|
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
|
RC = STATUS_INVALID_PARAMETER;
|
|
}
|
|
if(NT_SUCCESS(RC)) {
|
|
NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_SD_MODIFIED;
|
|
|
|
UDFNotifyFullReportChange( Fcb->Vcb, Fcb->FileInfo,
|
|
FILE_NOTIFY_CHANGE_SECURITY,
|
|
FILE_ACTION_MODIFIED);
|
|
}
|
|
|
|
try_exit: NOTHING;
|
|
|
|
} _SEH2_FINALLY {
|
|
|
|
// Release the FCB resources if acquired.
|
|
if (AcquiredFCB) {
|
|
UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
|
|
UDFReleaseResource(&(NtReqFcb->MainResource));
|
|
AcquiredFCB = FALSE;
|
|
}
|
|
|
|
if (PostRequest) {
|
|
// Perform appropriate post related processing here
|
|
RC = UDFPostRequest(PtrIrpContext, Irp);
|
|
} else
|
|
if(!AbnormalTermination()) {
|
|
Irp->IoStatus.Status = RC;
|
|
Irp->IoStatus.Information = 0;
|
|
// Free up the Irp Context
|
|
UDFReleaseIrpContext(PtrIrpContext);
|
|
// complete the IRP
|
|
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
|
|
}
|
|
|
|
} // end of "__finally" processing
|
|
|
|
return(RC);
|
|
} // ens UDFCommonSetSecurity()
|
|
|
|
#endif //UDF_READ_ONLY_BUILD
|
|
#endif //UDF_ENABLE_SECURITY
|
|
|
|
NTSTATUS
|
|
UDFReadSecurity(
|
|
IN PVCB Vcb,
|
|
IN PtrUDFFCB Fcb,
|
|
IN PSECURITY_DESCRIPTOR* SecurityDesc
|
|
)
|
|
{
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
PUDF_FILE_INFO FileInfo = NULL;
|
|
PUDF_FILE_INFO SDirInfo = NULL;
|
|
PUDF_FILE_INFO AclInfo = NULL;
|
|
NTSTATUS RC;
|
|
ULONG NumberBytesRead;
|
|
PERESOURCE Res1 = NULL;
|
|
|
|
UDFPrint(("UDFReadSecurity\n"));
|
|
|
|
_SEH2_TRY {
|
|
|
|
FileInfo = Fcb->FileInfo;
|
|
ASSERT(FileInfo);
|
|
if(!FileInfo) {
|
|
UDFPrint((" Volume Security\n"));
|
|
try_return(RC = STATUS_NO_SECURITY_ON_OBJECT);
|
|
}
|
|
if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
|
|
UDFPrint((" No Security on blank volume\n"));
|
|
try_return(RC = STATUS_NO_SECURITY_ON_OBJECT);
|
|
}
|
|
|
|
// Open Stream Directory
|
|
RC = UDFOpenStreamDir__(Vcb, FileInfo, &SDirInfo);
|
|
|
|
if(RC == STATUS_NOT_FOUND)
|
|
try_return(RC = STATUS_NO_SECURITY_ON_OBJECT);
|
|
if(!NT_SUCCESS(RC)) {
|
|
if(UDFCleanUpFile__(Vcb, SDirInfo)) {
|
|
if(SDirInfo) MyFreePool__(SDirInfo);
|
|
}
|
|
SDirInfo = NULL;
|
|
try_return(RC);
|
|
}
|
|
// Acquire SDir exclusively if Fcb present
|
|
if(SDirInfo->Fcb) {
|
|
BrutePoint();
|
|
UDF_CHECK_PAGING_IO_RESOURCE(SDirInfo->Fcb->NTRequiredFCB);
|
|
UDFAcquireResourceExclusive(Res1 = &(SDirInfo->Fcb->NTRequiredFCB->MainResource),TRUE);
|
|
}
|
|
|
|
// Open Acl Stream
|
|
RC = UDFOpenFile__(Vcb,
|
|
FALSE,TRUE,&(UDFGlobalData.AclName),
|
|
SDirInfo,&AclInfo,NULL);
|
|
if(RC == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
try_return(RC = STATUS_NO_SECURITY_ON_OBJECT);
|
|
if(!NT_SUCCESS(RC)) {
|
|
if(UDFCleanUpFile__(Vcb, AclInfo)) {
|
|
if(AclInfo) MyFreePool__(AclInfo);
|
|
}
|
|
AclInfo = NULL;
|
|
try_return(RC);
|
|
}
|
|
|
|
NumberBytesRead = (ULONG)UDFGetFileSize(AclInfo);
|
|
(*SecurityDesc) = DbgAllocatePool(NonPagedPool, NumberBytesRead);
|
|
if(!(*SecurityDesc))
|
|
try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
|
|
RC = UDFReadFile__(Vcb, AclInfo, 0, NumberBytesRead,
|
|
FALSE, (PCHAR)(*SecurityDesc), &NumberBytesRead);
|
|
if(!NT_SUCCESS(RC))
|
|
try_return(RC);
|
|
|
|
RC = RtlValidSecurityDescriptor(*SecurityDesc);
|
|
|
|
try_exit: NOTHING;
|
|
|
|
} _SEH2_FINALLY {
|
|
|
|
if(AclInfo) {
|
|
UDFCloseFile__(Vcb, AclInfo);
|
|
if(UDFCleanUpFile__(Vcb, AclInfo))
|
|
MyFreePool__(AclInfo);
|
|
}
|
|
|
|
if(SDirInfo) {
|
|
UDFCloseFile__(Vcb, SDirInfo);
|
|
if(UDFCleanUpFile__(Vcb, SDirInfo))
|
|
MyFreePool__(SDirInfo);
|
|
}
|
|
|
|
if(!NT_SUCCESS(RC) && (*SecurityDesc)) {
|
|
DbgFreePool(*SecurityDesc);
|
|
(*SecurityDesc) = NULL;
|
|
}
|
|
if(Res1)
|
|
UDFReleaseResource(Res1);
|
|
}
|
|
|
|
return RC;
|
|
#else
|
|
return STATUS_NO_SECURITY_ON_OBJECT;
|
|
#endif //UDF_ENABLE_SECURITY
|
|
|
|
} // end UDFReadSecurity()
|
|
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
NTSTATUS
|
|
UDFConvertToSelfRelative(
|
|
IN OUT PSECURITY_DESCRIPTOR* SecurityDesc
|
|
)
|
|
{
|
|
NTSTATUS RC;
|
|
SECURITY_INFORMATION SecurityInformation;
|
|
PSECURITY_DESCRIPTOR NewSD;
|
|
ULONG Len;
|
|
|
|
UDFPrint((" UDFConvertToSelfRelative\n"));
|
|
|
|
if(!(*SecurityDesc))
|
|
return STATUS_NO_SECURITY_ON_OBJECT;
|
|
|
|
SecurityInformation = FULL_SECURITY_INFORMATION;
|
|
Len = RtlLengthSecurityDescriptor(*SecurityDesc);
|
|
ASSERT(Len <= 1024);
|
|
NewSD = (PSECURITY_DESCRIPTOR)DbgAllocatePool(NonPagedPool, Len);
|
|
if(!NewSD)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
_SEH2_TRY {
|
|
RC = SeQuerySecurityDescriptorInfo(&SecurityInformation, NewSD, &Len, SecurityDesc);
|
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
|
RC = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if(NT_SUCCESS(RC)) {
|
|
DbgFreePool(*SecurityDesc);
|
|
*SecurityDesc = NewSD;
|
|
} else {
|
|
DbgFreePool(NewSD);
|
|
}
|
|
return RC;
|
|
} // end UDFConvertToSelfRelative()
|
|
|
|
NTSTATUS
|
|
UDFInheritAcl(
|
|
IN PVCB Vcb,
|
|
IN PSECURITY_DESCRIPTOR* ParentSecurityDesc,
|
|
IN OUT PSECURITY_DESCRIPTOR* SecurityDesc
|
|
)
|
|
{
|
|
NTSTATUS RC;
|
|
SECURITY_INFORMATION SecurityInformation;
|
|
ULONG Len;
|
|
|
|
UDFPrint((" UDFInheritAcl\n"));
|
|
|
|
if(!(*ParentSecurityDesc)) {
|
|
*SecurityDesc = NULL;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
SecurityInformation = FULL_SECURITY_INFORMATION;
|
|
Len = RtlLengthSecurityDescriptor(*ParentSecurityDesc);
|
|
*SecurityDesc = (PSECURITY_DESCRIPTOR)DbgAllocatePool(NonPagedPool, Len);
|
|
if(!(*SecurityDesc))
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
_SEH2_TRY {
|
|
RC = SeQuerySecurityDescriptorInfo(&SecurityInformation, *SecurityDesc, &Len, ParentSecurityDesc);
|
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
|
RC = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if(!NT_SUCCESS(RC)) {
|
|
DbgFreePool(*SecurityDesc);
|
|
*SecurityDesc = NULL;
|
|
}
|
|
return RC;
|
|
} // end UDFInheritAcl()
|
|
|
|
NTSTATUS
|
|
UDFBuildEmptyAcl(
|
|
IN PVCB Vcb,
|
|
IN PSECURITY_DESCRIPTOR* SecurityDesc
|
|
)
|
|
{
|
|
NTSTATUS RC;
|
|
ULONG Len = 2 * (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(ULONG)*4 /*RtlLengthSid(SeExports->SeWorldSid)*/);
|
|
|
|
UDFPrint((" UDFBuildEmptyAcl\n"));
|
|
// Create Security Descriptor
|
|
(*SecurityDesc) = (PSECURITY_DESCRIPTOR)DbgAllocatePool(NonPagedPool,
|
|
sizeof(SECURITY_DESCRIPTOR) + Len);
|
|
if(!(*SecurityDesc))
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RC = RtlCreateSecurityDescriptor(*SecurityDesc, SECURITY_DESCRIPTOR_REVISION);
|
|
|
|
if(!NT_SUCCESS(RC)) {
|
|
DbgFreePool(*SecurityDesc);
|
|
*((PULONG)SecurityDesc) = NULL;
|
|
}
|
|
return RC;
|
|
} // end UDFBuildEmptyAcl()
|
|
|
|
NTSTATUS
|
|
UDFBuildFullControlAcl(
|
|
IN PVCB Vcb,
|
|
IN PSECURITY_DESCRIPTOR* SecurityDesc
|
|
)
|
|
{
|
|
NTSTATUS RC;
|
|
PACL Acl;
|
|
ULONG Len = sizeof(ACL) + 2*(sizeof(ACCESS_ALLOWED_ACE) + sizeof(ULONG)*4 /*- sizeof(ULONG)*/ /*+ RtlLengthSid(SeExports->SeWorldSid)*/);
|
|
|
|
UDFPrint((" UDFBuildFullControlAcl\n"));
|
|
// Create Security Descriptor
|
|
RC = UDFBuildEmptyAcl(Vcb, SecurityDesc);
|
|
if(!NT_SUCCESS(RC))
|
|
return RC;
|
|
|
|
// Set Owner
|
|
RC = RtlSetOwnerSecurityDescriptor(*SecurityDesc, SeExports->SeWorldSid, FALSE);
|
|
if(!NT_SUCCESS(RC)) {
|
|
DbgFreePool(*SecurityDesc);
|
|
*((PULONG)SecurityDesc) = NULL;
|
|
return RC;
|
|
}
|
|
|
|
// Set Group
|
|
RC = RtlSetGroupSecurityDescriptor(*SecurityDesc, SeExports->SeWorldSid, FALSE);
|
|
if(!NT_SUCCESS(RC)) {
|
|
DbgFreePool(*SecurityDesc);
|
|
*((PULONG)SecurityDesc) = NULL;
|
|
return RC;
|
|
}
|
|
|
|
// Create empty Acl
|
|
Acl = (PACL)DbgAllocatePool(NonPagedPool, Len);
|
|
if(!Acl) {
|
|
DbgFreePool(*SecurityDesc);
|
|
*((PULONG)SecurityDesc) = NULL;
|
|
return RC;
|
|
}
|
|
RtlZeroMemory(Acl, Len);
|
|
|
|
RC = RtlCreateAcl(Acl, Len, ACL_REVISION);
|
|
if(!NT_SUCCESS(RC)) {
|
|
DbgFreePool(Acl);
|
|
DbgFreePool(*SecurityDesc);
|
|
*((PULONG)SecurityDesc) = NULL;
|
|
return RC;
|
|
}
|
|
|
|
// Add (All)(All) access for Everyone
|
|
/* RC = RtlAddAccessAllowedAce(Acl, ACL_REVISION,
|
|
GENERIC_ALL,
|
|
SeExports->SeWorldSid);*/
|
|
|
|
RC = RtlAddAccessAllowedAce(Acl, ACL_REVISION,
|
|
FILE_ALL_ACCESS,
|
|
SeExports->SeWorldSid);
|
|
|
|
if(!NT_SUCCESS(RC)) {
|
|
DbgFreePool(Acl);
|
|
DbgFreePool(*SecurityDesc);
|
|
*((PULONG)SecurityDesc) = NULL;
|
|
return RC;
|
|
}
|
|
|
|
// Add Acl to Security Descriptor
|
|
RC = RtlSetDaclSecurityDescriptor(*SecurityDesc, TRUE, Acl, FALSE);
|
|
if(!NT_SUCCESS(RC)) {
|
|
DbgFreePool(Acl);
|
|
DbgFreePool(*SecurityDesc);
|
|
*((PULONG)SecurityDesc) = NULL;
|
|
return RC;
|
|
}
|
|
|
|
RC = UDFConvertToSelfRelative(SecurityDesc);
|
|
|
|
DbgFreePool(Acl);
|
|
|
|
return RC;
|
|
} // end UDFBuildFullControlAcl()
|
|
|
|
#endif // UDF_ENABLE_SECURITY
|
|
|
|
NTSTATUS
|
|
UDFAssignAcl(
|
|
IN PVCB Vcb,
|
|
IN PFILE_OBJECT FileObject, // OPTIONAL
|
|
IN PtrUDFFCB Fcb,
|
|
IN PtrUDFNTRequiredFCB NtReqFcb
|
|
)
|
|
{
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
// SECURITY_INFORMATION SecurityInformation;
|
|
|
|
// UDFPrint((" UDFAssignAcl\n"));
|
|
if(!NtReqFcb->SecurityDesc) {
|
|
|
|
PSECURITY_DESCRIPTOR ExplicitSecurity = NULL;
|
|
|
|
if(UDFIsAStreamDir(Fcb->FileInfo) || UDFIsAStream(Fcb->FileInfo)) {
|
|
// Stream/SDir security
|
|
NtReqFcb->SecurityDesc = Fcb->FileInfo->ParentFile->Dloc->CommonFcb->SecurityDesc;
|
|
return STATUS_SUCCESS;
|
|
} else
|
|
if(!Fcb->FileInfo) {
|
|
// Volume security
|
|
if(Vcb->RootDirFCB &&
|
|
Vcb->RootDirFCB->FileInfo &&
|
|
Vcb->RootDirFCB->FileInfo->Dloc &&
|
|
Vcb->RootDirFCB->FileInfo->Dloc->CommonFcb) {
|
|
RC = UDFInheritAcl(Vcb, &(Vcb->RootDirFCB->FileInfo->Dloc->CommonFcb->SecurityDesc), &ExplicitSecurity);
|
|
} else {
|
|
NtReqFcb->SecurityDesc = NULL;
|
|
RC = STATUS_NO_SECURITY_ON_OBJECT;
|
|
}
|
|
return RC;
|
|
}
|
|
|
|
RC = UDFReadSecurity(Vcb, Fcb, &ExplicitSecurity);
|
|
if(RC == STATUS_NO_SECURITY_ON_OBJECT) {
|
|
if(!Fcb->FileInfo->ParentFile) {
|
|
RC = UDFBuildFullControlAcl(Vcb, &ExplicitSecurity);
|
|
} else {
|
|
RC = UDFInheritAcl(Vcb, &(Fcb->FileInfo->ParentFile->Dloc->CommonFcb->SecurityDesc), &ExplicitSecurity);
|
|
}
|
|
/* if(NT_SUCCESS(RC)) {
|
|
NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_SD_MODIFIED;
|
|
}*/
|
|
}
|
|
if(NT_SUCCESS(RC)) {
|
|
|
|
// SecurityInformation = FULL_SECURITY_INFORMATION;
|
|
NtReqFcb->SecurityDesc = ExplicitSecurity;
|
|
|
|
/* RC = SeSetSecurityDescriptorInfo(FileObject,
|
|
&SecurityInformation,
|
|
ExplicitSecurity,
|
|
&(NtReqFcb->SecurityDesc),
|
|
NonPagedPool,
|
|
IoGetFileObjectGenericMapping() );*/
|
|
|
|
}
|
|
}
|
|
#endif //UDF_ENABLE_SECURITY
|
|
return RC;
|
|
} // end UDFAssignAcl()
|
|
|
|
|
|
VOID
|
|
UDFDeassignAcl(
|
|
IN PtrUDFNTRequiredFCB NtReqFcb,
|
|
IN BOOLEAN AutoInherited
|
|
)
|
|
{
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
// NTSTATUS RC = STATUS_SUCCESS;
|
|
|
|
// UDFPrint((" UDFDeassignAcl\n"));
|
|
if(!NtReqFcb->SecurityDesc)
|
|
return;
|
|
|
|
if(AutoInherited) {
|
|
NtReqFcb->SecurityDesc = NULL;
|
|
return;
|
|
}
|
|
|
|
SeDeassignSecurity(&(NtReqFcb->SecurityDesc));
|
|
NtReqFcb->SecurityDesc = NULL; // HA BCRK CLU4
|
|
#endif //UDF_ENABLE_SECURITY
|
|
return;
|
|
} // end UDFDeassignAcl()
|
|
|
|
NTSTATUS
|
|
UDFWriteSecurity(
|
|
IN PVCB Vcb,
|
|
IN PtrUDFFCB Fcb,
|
|
IN PSECURITY_DESCRIPTOR* SecurityDesc
|
|
)
|
|
{
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
PUDF_FILE_INFO FileInfo = NULL;
|
|
PUDF_FILE_INFO SDirInfo = NULL;
|
|
PUDF_FILE_INFO AclInfo = NULL;
|
|
PERESOURCE Res1 = NULL;
|
|
NTSTATUS RC;
|
|
ULONG NumberBytesRead;
|
|
|
|
// UDFPrint(("UDFWriteSecurity\n"));
|
|
|
|
#if !defined(UDF_READ_ONLY_BUILD)
|
|
|
|
if(!Vcb->WriteSecurity ||
|
|
(Vcb->VCBFlags & (UDF_VCB_FLAGS_VOLUME_READ_ONLY |
|
|
UDF_VCB_FLAGS_MEDIA_READ_ONLY)))
|
|
|
|
#endif //!defined(UDF_READ_ONLY_BUILD)
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
#if !defined(UDF_READ_ONLY_BUILD)
|
|
|
|
_SEH2_TRY {
|
|
|
|
FileInfo = Fcb->FileInfo;
|
|
ASSERT(FileInfo);
|
|
if(!FileInfo) {
|
|
UDFPrint((" Volume Security\n"));
|
|
try_return(RC = STATUS_SUCCESS);
|
|
}
|
|
|
|
if(!(Fcb->NTRequiredFCB->NtReqFCBFlags & UDF_NTREQ_FCB_SD_MODIFIED))
|
|
try_return(RC = STATUS_SUCCESS);
|
|
|
|
// Open Stream Directory
|
|
RC = UDFOpenStreamDir__(Vcb, FileInfo, &SDirInfo);
|
|
|
|
if(RC == STATUS_NOT_FOUND) {
|
|
RC = UDFCreateStreamDir__(Vcb, FileInfo, &SDirInfo);
|
|
}
|
|
if(!NT_SUCCESS(RC)) {
|
|
if(UDFCleanUpFile__(Vcb, SDirInfo)) {
|
|
if(SDirInfo) MyFreePool__(SDirInfo);
|
|
}
|
|
SDirInfo = NULL;
|
|
try_return(RC);
|
|
}
|
|
// Acquire SDir exclusively if Fcb present
|
|
if(SDirInfo->Fcb) {
|
|
BrutePoint();
|
|
UDF_CHECK_PAGING_IO_RESOURCE(SDirInfo->Fcb->NTRequiredFCB);
|
|
UDFAcquireResourceExclusive(Res1 = &(SDirInfo->Fcb->NTRequiredFCB->MainResource),TRUE);
|
|
}
|
|
|
|
// Open Acl Stream
|
|
RC = UDFOpenFile__(Vcb,
|
|
FALSE,TRUE,&(UDFGlobalData.AclName),
|
|
SDirInfo,&AclInfo,NULL);
|
|
if(RC == STATUS_OBJECT_NAME_NOT_FOUND) {
|
|
RC = UDFCreateFile__(Vcb, FALSE, &(UDFGlobalData.AclName),
|
|
0, 0, FALSE, FALSE, SDirInfo, &AclInfo);
|
|
}
|
|
if(!NT_SUCCESS(RC)) {
|
|
if(UDFCleanUpFile__(Vcb, AclInfo)) {
|
|
if(AclInfo) MyFreePool__(AclInfo);
|
|
}
|
|
AclInfo = NULL;
|
|
try_return(RC);
|
|
}
|
|
|
|
if(!(*SecurityDesc)) {
|
|
UDFFlushFile__(Vcb, AclInfo);
|
|
RC = UDFUnlinkFile__(Vcb, AclInfo, TRUE);
|
|
try_return(RC);
|
|
}
|
|
NumberBytesRead = RtlLengthSecurityDescriptor(*SecurityDesc);
|
|
|
|
RC = UDFWriteFile__(Vcb, AclInfo, 0, NumberBytesRead,
|
|
FALSE, (PCHAR)(*SecurityDesc), &NumberBytesRead);
|
|
if(!NT_SUCCESS(RC))
|
|
try_return(RC);
|
|
|
|
Fcb->NTRequiredFCB->NtReqFCBFlags &= ~UDF_NTREQ_FCB_SD_MODIFIED;
|
|
|
|
try_exit: NOTHING;
|
|
|
|
} _SEH2_FINALLY {
|
|
|
|
if(AclInfo) {
|
|
UDFCloseFile__(Vcb, AclInfo);
|
|
if(UDFCleanUpFile__(Vcb, AclInfo))
|
|
MyFreePool__(AclInfo);
|
|
}
|
|
|
|
if(SDirInfo) {
|
|
UDFCloseFile__(Vcb, SDirInfo);
|
|
if(UDFCleanUpFile__(Vcb, SDirInfo))
|
|
MyFreePool__(SDirInfo);
|
|
}
|
|
if(Res1)
|
|
UDFReleaseResource(Res1);
|
|
}
|
|
|
|
return RC;
|
|
|
|
#endif //!defined(UDF_READ_ONLY_BUILD)
|
|
#endif //UDF_ENABLE_SECURITY
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // end UDFWriteSecurity()
|
|
|
|
PSECURITY_DESCRIPTOR
|
|
UDFLookUpAcl(
|
|
IN PVCB Vcb,
|
|
PFILE_OBJECT FileObject, // OPTIONAL
|
|
IN PtrUDFFCB Fcb
|
|
)
|
|
{
|
|
UDFAssignAcl(Vcb, FileObject, Fcb, Fcb->NTRequiredFCB);
|
|
return (Fcb->NTRequiredFCB->SecurityDesc);
|
|
} // end UDFLookUpAcl()
|
|
|
|
|
|
NTSTATUS
|
|
UDFCheckAccessRights(
|
|
PFILE_OBJECT FileObject, // OPTIONAL
|
|
PACCESS_STATE AccessState,
|
|
PtrUDFFCB Fcb,
|
|
PtrUDFCCB Ccb, // OPTIONAL
|
|
ACCESS_MASK DesiredAccess,
|
|
USHORT ShareAccess
|
|
)
|
|
{
|
|
NTSTATUS RC;
|
|
BOOLEAN SecurityCheck = TRUE;
|
|
BOOLEAN ROCheck = FALSE;
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
PSECURITY_DESCRIPTOR SecDesc;
|
|
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
|
ACCESS_MASK LocalAccessMask;
|
|
#endif //UDF_ENABLE_SECURITY
|
|
|
|
// Check attr compatibility
|
|
ASSERT(Fcb);
|
|
ASSERT(Fcb->Vcb);
|
|
#ifdef UDF_READ_ONLY_BUILD
|
|
goto treat_as_ro;
|
|
#endif //UDF_READ_ONLY_BUILD
|
|
|
|
if(Fcb->FCBFlags & UDF_FCB_READ_ONLY) {
|
|
ROCheck = TRUE;
|
|
} else
|
|
if((Fcb->Vcb->origIntegrityType == INTEGRITY_TYPE_OPEN) &&
|
|
Ccb && !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN) &&
|
|
(Fcb->Vcb->CompatFlags & UDF_VCB_IC_DIRTY_RO)) {
|
|
AdPrint(("force R/O on dirty\n"));
|
|
ROCheck = TRUE;
|
|
}
|
|
if(ROCheck) {
|
|
#ifdef UDF_READ_ONLY_BUILD
|
|
treat_as_ro:
|
|
#endif //UDF_READ_ONLY_BUILD
|
|
ACCESS_MASK DesiredAccessMask = 0;
|
|
|
|
if(Fcb->Vcb->CompatFlags & UDF_VCB_IC_WRITE_IN_RO_DIR) {
|
|
if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
|
|
DesiredAccessMask = (FILE_WRITE_EA |
|
|
DELETE);
|
|
} else {
|
|
DesiredAccessMask = (FILE_WRITE_DATA |
|
|
FILE_APPEND_DATA |
|
|
FILE_WRITE_EA |
|
|
DELETE);
|
|
}
|
|
} else {
|
|
DesiredAccessMask = (FILE_WRITE_DATA |
|
|
FILE_APPEND_DATA |
|
|
FILE_WRITE_EA |
|
|
FILE_DELETE_CHILD |
|
|
FILE_ADD_SUBDIRECTORY |
|
|
FILE_ADD_FILE |
|
|
DELETE);
|
|
}
|
|
if(DesiredAccess & DesiredAccessMask)
|
|
return STATUS_ACCESS_DENIED;
|
|
}
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
// Check Security
|
|
// NOTE: we should not perform security check if an empty DesiredAccess
|
|
// was specified. AFAIU, SeAccessCheck() will return FALSE in this case.
|
|
SecDesc = UDFLookUpAcl(Fcb->Vcb, FileObject, Fcb);
|
|
if(SecDesc && DesiredAccess) {
|
|
SeCaptureSubjectContext(&SubjectContext);
|
|
SecurityCheck =
|
|
SeAccessCheck(SecDesc,
|
|
&SubjectContext,
|
|
FALSE,
|
|
DesiredAccess,
|
|
Ccb ? Ccb->PreviouslyGrantedAccess : 0,
|
|
NULL,
|
|
IoGetFileObjectGenericMapping(),
|
|
UserMode,
|
|
Ccb ? &(Ccb->PreviouslyGrantedAccess) : &LocalAccessMask,
|
|
&RC);
|
|
SeReleaseSubjectContext(&SubjectContext);
|
|
|
|
if(!SecurityCheck) {
|
|
return RC;
|
|
} else
|
|
#endif //UDF_ENABLE_SECURITY
|
|
if(DesiredAccess & ACCESS_SYSTEM_SECURITY) {
|
|
SecurityCheck = SeSinglePrivilegeCheck(SeExports->SeSecurityPrivilege, UserMode);
|
|
if(!SecurityCheck)
|
|
return STATUS_ACCESS_DENIED;
|
|
Ccb->PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
|
|
}
|
|
#ifdef UDF_ENABLE_SECURITY
|
|
}
|
|
#endif //UDF_ENABLE_SECURITY
|
|
if(FileObject) {
|
|
if (Fcb->OpenHandleCount) {
|
|
// The FCB is currently in use by some thread.
|
|
// We must check whether the requested access/share access
|
|
// conflicts with the existing open operations.
|
|
RC = IoCheckShareAccess(DesiredAccess, ShareAccess, FileObject,
|
|
&(Fcb->NTRequiredFCB->FCBShareAccess), TRUE);
|
|
#ifndef UDF_ENABLE_SECURITY
|
|
if(Ccb)
|
|
Ccb->PreviouslyGrantedAccess |= DesiredAccess;
|
|
IoUpdateShareAccess(FileObject, &(Fcb->NTRequiredFCB->FCBShareAccess));
|
|
#endif //UDF_ENABLE_SECURITY
|
|
} else {
|
|
IoSetShareAccess(DesiredAccess, ShareAccess, FileObject, &(Fcb->NTRequiredFCB->FCBShareAccess));
|
|
#ifndef UDF_ENABLE_SECURITY
|
|
if(Ccb)
|
|
Ccb->PreviouslyGrantedAccess = DesiredAccess;
|
|
#endif //UDF_ENABLE_SECURITY
|
|
RC = STATUS_SUCCESS;
|
|
}
|
|
} else {
|
|
// we get here if given file was opened for internal purposes
|
|
RC = STATUS_SUCCESS;
|
|
}
|
|
return RC;
|
|
} // end UDFCheckAccessRights()
|
|
|
|
NTSTATUS
|
|
UDFSetAccessRights(
|
|
PFILE_OBJECT FileObject,
|
|
PACCESS_STATE AccessState,
|
|
PtrUDFFCB Fcb,
|
|
PtrUDFCCB Ccb,
|
|
ACCESS_MASK DesiredAccess,
|
|
USHORT ShareAccess
|
|
)
|
|
{
|
|
#ifndef UDF_ENABLE_SECURITY
|
|
ASSERT(Ccb);
|
|
ASSERT(Fcb->FileInfo);
|
|
|
|
return UDFCheckAccessRights(FileObject, AccessState, Fcb, Ccb, DesiredAccess, ShareAccess);
|
|
|
|
#else //UDF_ENABLE_SECURITY
|
|
|
|
NTSTATUS RC;
|
|
// Set Security on Object
|
|
PSECURITY_DESCRIPTOR SecDesc;
|
|
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
|
BOOLEAN AutoInherit;
|
|
|
|
ASSERT(Ccb);
|
|
ASSERT(Fcb->FileInfo);
|
|
|
|
SecDesc = UDFLookUpAcl(Fcb->Vcb, FileObject, Fcb);
|
|
AutoInherit = UDFIsAStreamDir(Fcb->FileInfo) || UDFIsAStream(Fcb->FileInfo);
|
|
|
|
if(SecDesc && !AutoInherit) {
|
|
// Get caller's User/Primary Group info
|
|
SeCaptureSubjectContext(&SubjectContext);
|
|
RC = SeAssignSecurity(
|
|
Fcb->FileInfo->ParentFile->Dloc->CommonFcb->SecurityDesc,
|
|
// NULL,
|
|
AccessState->SecurityDescriptor,
|
|
&(Fcb->NTRequiredFCB->SecurityDesc),
|
|
UDFIsADirectory(Fcb->FileInfo),
|
|
&SubjectContext,
|
|
IoGetFileObjectGenericMapping(),
|
|
NonPagedPool);
|
|
SeReleaseSubjectContext(&SubjectContext);
|
|
UDFConvertToSelfRelative(&(Fcb->NTRequiredFCB->SecurityDesc));
|
|
|
|
if(!NT_SUCCESS(RC)) {
|
|
Clean_Up_SD:
|
|
UDFDeassignAcl(Fcb->NTRequiredFCB, AutoInherit);
|
|
return RC;
|
|
}
|
|
}
|
|
|
|
RC = UDFCheckAccessRights(FileObject, AccessState, Fcb, Ccb, DesiredAccess, ShareAccess);
|
|
if(!NT_SUCCESS(RC))
|
|
goto Clean_Up_SD;
|
|
return RC;
|
|
|
|
#endif //UDF_ENABLE_SECURITY
|
|
|
|
} // end UDFSetAccessRights()
|
|
|