Something went wrong. Try again.
Reactos
Something went wrong. Try again.
34 kB · 1108 lines
C++
at master
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109////////////////////////////////////////////////////////////////////// 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.**************************************************************************/NTSTATUSUDFGetSecurity( 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**************************************************************************/NTSTATUSUDFCommonGetSecurity( 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.**************************************************************************/NTSTATUSUDFSetSecurity( 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**************************************************************************/NTSTATUSUDFCommonSetSecurity( 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
NTSTATUSUDFReadSecurity( 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_SECURITYNTSTATUSUDFConvertToSelfRelative( 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()
NTSTATUSUDFInheritAcl( 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()
NTSTATUSUDFBuildEmptyAcl( 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()
NTSTATUSUDFBuildFullControlAcl( 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
NTSTATUSUDFAssignAcl( 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()
VOIDUDFDeassignAcl( 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()
NTSTATUSUDFWriteSecurity( 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_DESCRIPTORUDFLookUpAcl( IN PVCB Vcb, PFILE_OBJECT FileObject, // OPTIONAL IN PtrUDFFCB Fcb ){ UDFAssignAcl(Vcb, FileObject, Fcb, Fcb->NTRequiredFCB); return (Fcb->NTRequiredFCB->SecurityDesc);} // end UDFLookUpAcl()
NTSTATUSUDFCheckAccessRights( PFILE_OBJECT FileObject, // OPTIONAL PACCESS_STATE AccessState, PtrUDFFCB Fcb, PtrUDFCCB Ccb, // OPTIONAL ACCESS_MASK DesiredAccess, USHORT ShareAccess ){ NTSTATUS RC; BOOLEAN ROCheck = FALSE;#ifdef UDF_ENABLE_SECURITY BOOLEAN SecurityCheck; 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_BUILDtreat_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) { if (!SeSinglePrivilegeCheck(SeExports->SeSecurityPrivilege, UserMode)) 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()
NTSTATUSUDFSetAccessRights( 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()