1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
10 * Module: UDF File System Driver (Kernel mode execution only)
13 * Contains code to handle the "Get/Set Security" dispatch entry points.
15 *************************************************************************/
19 // define the file specific bug-check id
20 #define UDF_BUG_CHECK_ID UDF_FILE_SECURITY
22 #ifdef UDF_ENABLE_SECURITY
24 NTSTATUS
UDFConvertToSelfRelative(
25 IN OUT PSECURITY_DESCRIPTOR
* SecurityDesc
);
27 /*UCHAR FullControlSD[] = {
28 0x01, 0x00, 0x04, 0x80, 0x4c, 0x00, 0x00, 0x00,
29 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x38, 0x00,
31 0x02, 0x00, 0x00, 0x00, 0x00, 0x09, 0x18, 0x00,
32 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x00,
33 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
34 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00,
35 0xff, 0x01, 0x1f, 0x00, 0x01, 0x01, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
39 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
40 0x00, 0x00, 0x00, 0x00
43 /*************************************************************************
45 * Function: UDFGetSecurity()
49 * Expected Interrupt Level (for execution) :
53 * Return Value: Irrelevant.
55 *************************************************************************/
58 IN PDEVICE_OBJECT DeviceObject
, // the logical volume device object
59 IN PIRP Irp
) // I/O Request Packet
61 NTSTATUS RC
= STATUS_SUCCESS
;
62 PtrUDFIrpContext PtrIrpContext
= NULL
;
63 BOOLEAN AreWeTopLevel
= FALSE
;
65 UDFPrint(("UDFGetSecurity\n"));
68 FsRtlEnterFileSystem();
72 // set the top level context
73 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
74 ASSERT(!UDFIsFSDevObj(DeviceObject
));
75 // Call the common Lock Control routine, with blocking allowed if
79 // get an IRP context structure and issue the request
80 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
82 RC
= UDFCommonGetSecurity(PtrIrpContext
, Irp
);
84 RC
= STATUS_INSUFFICIENT_RESOURCES
;
85 Irp
->IoStatus
.Status
= RC
;
86 Irp
->IoStatus
.Information
= 0;
88 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
91 } __except (UDFExceptionFilter(PtrIrpContext
, GetExceptionInformation())) {
93 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
95 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
99 IoSetTopLevelIrp(NULL
);
102 FsRtlExitFileSystem();
105 } // end UDFGetSecurity()
108 /*************************************************************************
110 * Function: UDFCommonGetSecurity()
113 * This is the common routine for getting Security (ACL) called
114 * by both the fsd and fsp threads
116 * Expected Interrupt Level (for execution) :
120 * Return Value: Irrelevant
122 *************************************************************************/
124 UDFCommonGetSecurity(
125 IN PtrUDFIrpContext PtrIrpContext
,
128 NTSTATUS RC
= STATUS_SUCCESS
;
129 PIO_STACK_LOCATION IrpSp
= NULL
;
130 BOOLEAN PostRequest
= FALSE
;
131 BOOLEAN CanWait
= FALSE
;
132 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
133 BOOLEAN AcquiredFCB
= FALSE
;
134 PFILE_OBJECT FileObject
= NULL
;
135 PtrUDFFCB Fcb
= NULL
;
136 PtrUDFCCB Ccb
= NULL
;
137 PVOID PtrSystemBuffer
= NULL
;
138 ULONG BufferLength
= 0;
140 UDFPrint(("UDFCommonGetSecurity\n"));
144 // First, get a pointer to the current I/O stack location.
145 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
148 FileObject
= IrpSp
->FileObject
;
151 // Get the FCB and CCB pointers.
152 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
157 /* if(!Fcb->Vcb->ReadSecurity)
158 try_return(RC = STATUS_NOT_IMPLEMENTED);*/
160 NtReqFcb
= Fcb
->NTRequiredFCB
;
161 CanWait
= ((PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_CAN_BLOCK
) ? TRUE
: FALSE
);
163 // Acquire the FCB resource shared
164 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
165 if (!UDFAcquireResourceExclusive(&(NtReqFcb
->MainResource
), CanWait
)) {
166 // if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), CanWait)) {
168 try_return(RC
= STATUS_PENDING
);
172 PtrSystemBuffer
= UDFGetCallersBuffer(PtrIrpContext
, Irp
);
174 try_return(RC
= STATUS_INVALID_USER_BUFFER
);
175 BufferLength
= IrpSp
->Parameters
.QuerySecurity
.Length
;
177 if(!NtReqFcb
->SecurityDesc
) {
178 RC
= UDFAssignAcl(Fcb
->Vcb
, FileObject
, Fcb
, NtReqFcb
);
184 RC
= SeQuerySecurityDescriptorInfo(&(IrpSp
->Parameters
.QuerySecurity
.SecurityInformation
),
185 (PSECURITY_DESCRIPTOR
)PtrSystemBuffer
,
187 &(NtReqFcb
->SecurityDesc
) );
188 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
189 RC
= STATUS_BUFFER_TOO_SMALL
;
196 // Release the FCB resources if acquired.
198 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
199 UDFReleaseResource(&(NtReqFcb
->MainResource
));
204 // Perform appropriate post related processing here
205 RC
= UDFPostRequest(PtrIrpContext
, Irp
);
207 if(!AbnormalTermination()) {
208 Irp
->IoStatus
.Status
= RC
;
209 Irp
->IoStatus
.Information
= BufferLength
;
210 // Free up the Irp Context
211 UDFReleaseIrpContext(PtrIrpContext
);
213 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
216 } // end of "__finally" processing
221 #ifndef UDF_READ_ONLY_BUILD
222 /*************************************************************************
224 * Function: UDFSetSecurity()
228 * Expected Interrupt Level (for execution) :
232 * Return Value: Irrelevant.
234 *************************************************************************/
237 IN PDEVICE_OBJECT DeviceObject
, // the logical volume device object
238 IN PIRP Irp
) // I/O Request Packet
240 NTSTATUS RC
= STATUS_SUCCESS
;
241 PtrUDFIrpContext PtrIrpContext
= NULL
;
242 BOOLEAN AreWeTopLevel
= FALSE
;
244 UDFPrint(("UDFSetSecurity\n"));
247 FsRtlEnterFileSystem();
248 ASSERT(DeviceObject
);
251 // set the top level context
252 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
253 // Call the common Lock Control routine, with blocking allowed if
257 // get an IRP context structure and issue the request
258 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
260 RC
= UDFCommonSetSecurity(PtrIrpContext
, Irp
);
262 RC
= STATUS_INSUFFICIENT_RESOURCES
;
263 Irp
->IoStatus
.Status
= RC
;
264 Irp
->IoStatus
.Information
= 0;
266 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
269 } __except (UDFExceptionFilter(PtrIrpContext
, GetExceptionInformation())) {
271 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
273 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
277 IoSetTopLevelIrp(NULL
);
280 FsRtlExitFileSystem();
283 } // end UDFSetSecurity()
286 /*************************************************************************
288 * Function: UDFCommonSetSecurity()
291 * This is the common routine for getting Security (ACL) called
292 * by both the fsd and fsp threads
294 * Expected Interrupt Level (for execution) :
298 * Return Value: Irrelevant
300 *************************************************************************/
302 UDFCommonSetSecurity(
303 IN PtrUDFIrpContext PtrIrpContext
,
306 NTSTATUS RC
= STATUS_SUCCESS
;
307 PIO_STACK_LOCATION IrpSp
= NULL
;
308 BOOLEAN PostRequest
= FALSE
;
309 BOOLEAN CanWait
= FALSE
;
310 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
311 BOOLEAN AcquiredFCB
= FALSE
;
312 PFILE_OBJECT FileObject
= NULL
;
313 PtrUDFFCB Fcb
= NULL
;
314 PtrUDFCCB Ccb
= NULL
;
315 ACCESS_MASK DesiredAccess
= 0;
317 UDFPrint(("UDFCommonSetSecurity\n"));
321 // First, get a pointer to the current I/O stack location.
322 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
325 FileObject
= IrpSp
->FileObject
;
328 // Get the FCB and CCB pointers.
329 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
334 if(!Fcb
->Vcb
->WriteSecurity
)
335 try_return(RC
= STATUS_NOT_IMPLEMENTED
);
337 NtReqFcb
= Fcb
->NTRequiredFCB
;
338 CanWait
= ((PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_CAN_BLOCK
) ? TRUE
: FALSE
);
340 // Acquire the FCB resource exclusive
341 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
342 if (!UDFAcquireResourceExclusive(&(NtReqFcb
->MainResource
), CanWait
)) {
344 try_return(RC
= STATUS_PENDING
);
348 //OWNER_SECURITY_INFORMATION
349 if(IrpSp
->Parameters
.SetSecurity
.SecurityInformation
& OWNER_SECURITY_INFORMATION
)
350 DesiredAccess
|= WRITE_OWNER
;
351 //GROUP_SECURITY_INFORMATION
352 if(IrpSp
->Parameters
.SetSecurity
.SecurityInformation
& GROUP_SECURITY_INFORMATION
)
353 DesiredAccess
|= WRITE_OWNER
;
354 //DACL_SECURITY_INFORMATION
355 if(IrpSp
->Parameters
.SetSecurity
.SecurityInformation
& DACL_SECURITY_INFORMATION
)
356 DesiredAccess
|= WRITE_DAC
;
357 //SACL_SECURITY_INFORMATION
358 if(IrpSp
->Parameters
.SetSecurity
.SecurityInformation
& SACL_SECURITY_INFORMATION
)
359 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
362 UDFConvertToSelfRelative(&(NtReqFcb
->SecurityDesc
));
364 KdDump(NtReqFcb
->SecurityDesc
, RtlLengthSecurityDescriptor(NtReqFcb
->SecurityDesc
));
367 RC
= SeSetSecurityDescriptorInfo(/*FileObject*/ NULL
,
368 &(IrpSp
->Parameters
.SetSecurity
.SecurityInformation
),
369 IrpSp
->Parameters
.SetSecurity
.SecurityDescriptor
,
370 &(NtReqFcb
->SecurityDesc
),
372 IoGetFileObjectGenericMapping() );
374 KdDump(NtReqFcb
->SecurityDesc
, RtlLengthSecurityDescriptor(NtReqFcb
->SecurityDesc
));
376 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
377 RC
= STATUS_INVALID_PARAMETER
;
380 NtReqFcb
->NtReqFCBFlags
|= UDF_NTREQ_FCB_SD_MODIFIED
;
382 UDFNotifyFullReportChange( Fcb
->Vcb
, Fcb
->FileInfo
,
383 FILE_NOTIFY_CHANGE_SECURITY
,
384 FILE_ACTION_MODIFIED
);
391 // Release the FCB resources if acquired.
393 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
394 UDFReleaseResource(&(NtReqFcb
->MainResource
));
399 // Perform appropriate post related processing here
400 RC
= UDFPostRequest(PtrIrpContext
, Irp
);
402 if(!AbnormalTermination()) {
403 Irp
->IoStatus
.Status
= RC
;
404 Irp
->IoStatus
.Information
= 0;
405 // Free up the Irp Context
406 UDFReleaseIrpContext(PtrIrpContext
);
408 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
411 } // end of "__finally" processing
414 } // ens UDFCommonSetSecurity()
416 #endif //UDF_READ_ONLY_BUILD
417 #endif //UDF_ENABLE_SECURITY
423 IN PSECURITY_DESCRIPTOR
* SecurityDesc
426 #ifdef UDF_ENABLE_SECURITY
427 PUDF_FILE_INFO FileInfo
= NULL
;
428 PUDF_FILE_INFO SDirInfo
= NULL
;
429 PUDF_FILE_INFO AclInfo
= NULL
;
431 ULONG NumberBytesRead
;
432 PERESOURCE Res1
= NULL
;
434 UDFPrint(("UDFReadSecurity\n"));
438 FileInfo
= Fcb
->FileInfo
;
441 UDFPrint((" Volume Security\n"));
442 try_return(RC
= STATUS_NO_SECURITY_ON_OBJECT
);
444 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
445 UDFPrint((" No Security on blank volume\n"));
446 try_return(RC
= STATUS_NO_SECURITY_ON_OBJECT
);
449 // Open Stream Directory
450 RC
= UDFOpenStreamDir__(Vcb
, FileInfo
, &SDirInfo
);
452 if(RC
== STATUS_NOT_FOUND
)
453 try_return(RC
= STATUS_NO_SECURITY_ON_OBJECT
);
454 if(!NT_SUCCESS(RC
)) {
455 if(UDFCleanUpFile__(Vcb
, SDirInfo
)) {
456 if(SDirInfo
) MyFreePool__(SDirInfo
);
461 // Acquire SDir exclusively if Fcb present
464 UDF_CHECK_PAGING_IO_RESOURCE(SDirInfo
->Fcb
->NTRequiredFCB
);
465 UDFAcquireResourceExclusive(Res1
= &(SDirInfo
->Fcb
->NTRequiredFCB
->MainResource
),TRUE
);
469 RC
= UDFOpenFile__(Vcb
,
470 FALSE
,TRUE
,&(UDFGlobalData
.AclName
),
471 SDirInfo
,&AclInfo
,NULL
);
472 if(RC
== STATUS_OBJECT_NAME_NOT_FOUND
)
473 try_return(RC
= STATUS_NO_SECURITY_ON_OBJECT
);
474 if(!NT_SUCCESS(RC
)) {
475 if(UDFCleanUpFile__(Vcb
, AclInfo
)) {
476 if(AclInfo
) MyFreePool__(AclInfo
);
482 NumberBytesRead
= (ULONG
)UDFGetFileSize(AclInfo
);
483 (*SecurityDesc
) = DbgAllocatePool(NonPagedPool
, NumberBytesRead
);
485 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
486 RC
= UDFReadFile__(Vcb
, AclInfo
, 0, NumberBytesRead
,
487 FALSE
, (PCHAR
)(*SecurityDesc
), &NumberBytesRead
);
491 RC
= RtlValidSecurityDescriptor(*SecurityDesc
);
498 UDFCloseFile__(Vcb
, AclInfo
);
499 if(UDFCleanUpFile__(Vcb
, AclInfo
))
500 MyFreePool__(AclInfo
);
504 UDFCloseFile__(Vcb
, SDirInfo
);
505 if(UDFCleanUpFile__(Vcb
, SDirInfo
))
506 MyFreePool__(SDirInfo
);
509 if(!NT_SUCCESS(RC
) && (*SecurityDesc
)) {
510 DbgFreePool(*SecurityDesc
);
511 (*SecurityDesc
) = NULL
;
514 UDFReleaseResource(Res1
);
519 return STATUS_NO_SECURITY_ON_OBJECT
;
520 #endif //UDF_ENABLE_SECURITY
522 } // end UDFReadSecurity()
524 #ifdef UDF_ENABLE_SECURITY
526 UDFConvertToSelfRelative(
527 IN OUT PSECURITY_DESCRIPTOR
* SecurityDesc
531 SECURITY_INFORMATION SecurityInformation
;
532 PSECURITY_DESCRIPTOR NewSD
;
535 UDFPrint((" UDFConvertToSelfRelative\n"));
538 return STATUS_NO_SECURITY_ON_OBJECT
;
540 SecurityInformation
= FULL_SECURITY_INFORMATION
;
541 Len
= RtlLengthSecurityDescriptor(*SecurityDesc
);
543 NewSD
= (PSECURITY_DESCRIPTOR
)DbgAllocatePool(NonPagedPool
, Len
);
545 return STATUS_INSUFFICIENT_RESOURCES
;
547 RC
= SeQuerySecurityDescriptorInfo(&SecurityInformation
, NewSD
, &Len
, SecurityDesc
);
548 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
549 RC
= STATUS_INSUFFICIENT_RESOURCES
;
553 DbgFreePool(*SecurityDesc
);
554 *SecurityDesc
= NewSD
;
559 } // end UDFConvertToSelfRelative()
564 IN PSECURITY_DESCRIPTOR
* ParentSecurityDesc
,
565 IN OUT PSECURITY_DESCRIPTOR
* SecurityDesc
569 SECURITY_INFORMATION SecurityInformation
;
572 UDFPrint((" UDFInheritAcl\n"));
574 if(!(*ParentSecurityDesc
)) {
575 *SecurityDesc
= NULL
;
576 return STATUS_SUCCESS
;
579 SecurityInformation
= FULL_SECURITY_INFORMATION
;
580 Len
= RtlLengthSecurityDescriptor(*ParentSecurityDesc
);
581 *SecurityDesc
= (PSECURITY_DESCRIPTOR
)DbgAllocatePool(NonPagedPool
, Len
);
583 return STATUS_INSUFFICIENT_RESOURCES
;
585 RC
= SeQuerySecurityDescriptorInfo(&SecurityInformation
, *SecurityDesc
, &Len
, ParentSecurityDesc
);
586 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
587 RC
= STATUS_INSUFFICIENT_RESOURCES
;
590 if(!NT_SUCCESS(RC
)) {
591 DbgFreePool(*SecurityDesc
);
592 *SecurityDesc
= NULL
;
595 } // end UDFInheritAcl()
600 IN PSECURITY_DESCRIPTOR
* SecurityDesc
604 ULONG Len
= 2 * (sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
) + sizeof(ULONG
)*4 /*RtlLengthSid(SeExports->SeWorldSid)*/);
606 UDFPrint((" UDFBuildEmptyAcl\n"));
607 // Create Security Descriptor
608 (*SecurityDesc
) = (PSECURITY_DESCRIPTOR
)DbgAllocatePool(NonPagedPool
,
609 sizeof(SECURITY_DESCRIPTOR
) + Len
);
611 return STATUS_INSUFFICIENT_RESOURCES
;
613 RC
= RtlCreateSecurityDescriptor(*SecurityDesc
, SECURITY_DESCRIPTOR_REVISION
);
615 if(!NT_SUCCESS(RC
)) {
616 DbgFreePool(*SecurityDesc
);
617 *((PULONG
)SecurityDesc
) = NULL
;
620 } // end UDFBuildEmptyAcl()
623 UDFBuildFullControlAcl(
625 IN PSECURITY_DESCRIPTOR
* SecurityDesc
630 ULONG Len
= sizeof(ACL
) + 2*(sizeof(ACCESS_ALLOWED_ACE
) + sizeof(ULONG
)*4 /*- sizeof(ULONG)*/ /*+ RtlLengthSid(SeExports->SeWorldSid)*/);
632 UDFPrint((" UDFBuildFullControlAcl\n"));
633 // Create Security Descriptor
634 RC
= UDFBuildEmptyAcl(Vcb
, SecurityDesc
);
639 RC
= RtlSetOwnerSecurityDescriptor(*SecurityDesc
, SeExports
->SeWorldSid
, FALSE
);
640 if(!NT_SUCCESS(RC
)) {
641 DbgFreePool(*SecurityDesc
);
642 *((PULONG
)SecurityDesc
) = NULL
;
647 RC
= RtlSetGroupSecurityDescriptor(*SecurityDesc
, SeExports
->SeWorldSid
, FALSE
);
648 if(!NT_SUCCESS(RC
)) {
649 DbgFreePool(*SecurityDesc
);
650 *((PULONG
)SecurityDesc
) = NULL
;
655 Acl
= (PACL
)DbgAllocatePool(NonPagedPool
, Len
);
657 DbgFreePool(*SecurityDesc
);
658 *((PULONG
)SecurityDesc
) = NULL
;
661 RtlZeroMemory(Acl
, Len
);
663 RC
= RtlCreateAcl(Acl
, Len
, ACL_REVISION
);
664 if(!NT_SUCCESS(RC
)) {
666 DbgFreePool(*SecurityDesc
);
667 *((PULONG
)SecurityDesc
) = NULL
;
671 // Add (All)(All) access for Everyone
672 /* RC = RtlAddAccessAllowedAce(Acl, ACL_REVISION,
674 SeExports->SeWorldSid);*/
676 RC
= RtlAddAccessAllowedAce(Acl
, ACL_REVISION
,
678 SeExports
->SeWorldSid
);
680 if(!NT_SUCCESS(RC
)) {
682 DbgFreePool(*SecurityDesc
);
683 *((PULONG
)SecurityDesc
) = NULL
;
687 // Add Acl to Security Descriptor
688 RC
= RtlSetDaclSecurityDescriptor(*SecurityDesc
, TRUE
, Acl
, FALSE
);
689 if(!NT_SUCCESS(RC
)) {
691 DbgFreePool(*SecurityDesc
);
692 *((PULONG
)SecurityDesc
) = NULL
;
696 RC
= UDFConvertToSelfRelative(SecurityDesc
);
701 } // end UDFBuildFullControlAcl()
703 #endif // UDF_ENABLE_SECURITY
708 IN PFILE_OBJECT FileObject
, // OPTIONAL
710 IN PtrUDFNTRequiredFCB NtReqFcb
713 NTSTATUS RC
= STATUS_SUCCESS
;
714 #ifdef UDF_ENABLE_SECURITY
715 // SECURITY_INFORMATION SecurityInformation;
717 // UDFPrint((" UDFAssignAcl\n"));
718 if(!NtReqFcb
->SecurityDesc
) {
720 PSECURITY_DESCRIPTOR ExplicitSecurity
= NULL
;
722 if(UDFIsAStreamDir(Fcb
->FileInfo
) || UDFIsAStream(Fcb
->FileInfo
)) {
723 // Stream/SDir security
724 NtReqFcb
->SecurityDesc
= Fcb
->FileInfo
->ParentFile
->Dloc
->CommonFcb
->SecurityDesc
;
725 return STATUS_SUCCESS
;
729 if(Vcb
->RootDirFCB
&&
730 Vcb
->RootDirFCB
->FileInfo
&&
731 Vcb
->RootDirFCB
->FileInfo
->Dloc
&&
732 Vcb
->RootDirFCB
->FileInfo
->Dloc
->CommonFcb
) {
733 RC
= UDFInheritAcl(Vcb
, &(Vcb
->RootDirFCB
->FileInfo
->Dloc
->CommonFcb
->SecurityDesc
), &ExplicitSecurity
);
735 NtReqFcb
->SecurityDesc
= NULL
;
736 RC
= STATUS_NO_SECURITY_ON_OBJECT
;
741 RC
= UDFReadSecurity(Vcb
, Fcb
, &ExplicitSecurity
);
742 if(RC
== STATUS_NO_SECURITY_ON_OBJECT
) {
743 if(!Fcb
->FileInfo
->ParentFile
) {
744 RC
= UDFBuildFullControlAcl(Vcb
, &ExplicitSecurity
);
746 RC
= UDFInheritAcl(Vcb
, &(Fcb
->FileInfo
->ParentFile
->Dloc
->CommonFcb
->SecurityDesc
), &ExplicitSecurity
);
748 /* if(NT_SUCCESS(RC)) {
749 NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_SD_MODIFIED;
754 // SecurityInformation = FULL_SECURITY_INFORMATION;
755 NtReqFcb
->SecurityDesc
= ExplicitSecurity
;
757 /* RC = SeSetSecurityDescriptorInfo(FileObject,
758 &SecurityInformation,
760 &(NtReqFcb->SecurityDesc),
762 IoGetFileObjectGenericMapping() );*/
766 #endif //UDF_ENABLE_SECURITY
768 } // end UDFAssignAcl()
773 IN PtrUDFNTRequiredFCB NtReqFcb
,
774 IN BOOLEAN AutoInherited
777 #ifdef UDF_ENABLE_SECURITY
778 // NTSTATUS RC = STATUS_SUCCESS;
780 // UDFPrint((" UDFDeassignAcl\n"));
781 if(!NtReqFcb
->SecurityDesc
)
785 NtReqFcb
->SecurityDesc
= NULL
;
789 SeDeassignSecurity(&(NtReqFcb
->SecurityDesc
));
790 NtReqFcb
->SecurityDesc
= NULL
; // HA BCRK CLU4
791 #endif //UDF_ENABLE_SECURITY
793 } // end UDFDeassignAcl()
799 IN PSECURITY_DESCRIPTOR
* SecurityDesc
802 #ifdef UDF_ENABLE_SECURITY
803 PUDF_FILE_INFO FileInfo
= NULL
;
804 PUDF_FILE_INFO SDirInfo
= NULL
;
805 PUDF_FILE_INFO AclInfo
= NULL
;
806 PERESOURCE Res1
= NULL
;
808 ULONG NumberBytesRead
;
810 // UDFPrint(("UDFWriteSecurity\n"));
812 #if !defined(UDF_READ_ONLY_BUILD)
814 if(!Vcb
->WriteSecurity
||
815 (Vcb
->VCBFlags
& (UDF_VCB_FLAGS_VOLUME_READ_ONLY
|
816 UDF_VCB_FLAGS_MEDIA_READ_ONLY
)))
818 #endif //!defined(UDF_READ_ONLY_BUILD)
820 return STATUS_SUCCESS
;
822 #if !defined(UDF_READ_ONLY_BUILD)
826 FileInfo
= Fcb
->FileInfo
;
829 UDFPrint((" Volume Security\n"));
830 try_return(RC
= STATUS_SUCCESS
);
833 if(!(Fcb
->NTRequiredFCB
->NtReqFCBFlags
& UDF_NTREQ_FCB_SD_MODIFIED
))
834 try_return(RC
= STATUS_SUCCESS
);
836 // Open Stream Directory
837 RC
= UDFOpenStreamDir__(Vcb
, FileInfo
, &SDirInfo
);
839 if(RC
== STATUS_NOT_FOUND
) {
840 RC
= UDFCreateStreamDir__(Vcb
, FileInfo
, &SDirInfo
);
842 if(!NT_SUCCESS(RC
)) {
843 if(UDFCleanUpFile__(Vcb
, SDirInfo
)) {
844 if(SDirInfo
) MyFreePool__(SDirInfo
);
849 // Acquire SDir exclusively if Fcb present
852 UDF_CHECK_PAGING_IO_RESOURCE(SDirInfo
->Fcb
->NTRequiredFCB
);
853 UDFAcquireResourceExclusive(Res1
= &(SDirInfo
->Fcb
->NTRequiredFCB
->MainResource
),TRUE
);
857 RC
= UDFOpenFile__(Vcb
,
858 FALSE
,TRUE
,&(UDFGlobalData
.AclName
),
859 SDirInfo
,&AclInfo
,NULL
);
860 if(RC
== STATUS_OBJECT_NAME_NOT_FOUND
) {
861 RC
= UDFCreateFile__(Vcb
, FALSE
, &(UDFGlobalData
.AclName
),
862 0, 0, FALSE
, FALSE
, SDirInfo
, &AclInfo
);
864 if(!NT_SUCCESS(RC
)) {
865 if(UDFCleanUpFile__(Vcb
, AclInfo
)) {
866 if(AclInfo
) MyFreePool__(AclInfo
);
872 if(!(*SecurityDesc
)) {
873 UDFFlushFile__(Vcb
, AclInfo
);
874 RC
= UDFUnlinkFile__(Vcb
, AclInfo
, TRUE
);
877 NumberBytesRead
= RtlLengthSecurityDescriptor(*SecurityDesc
);
879 RC
= UDFWriteFile__(Vcb
, AclInfo
, 0, NumberBytesRead
,
880 FALSE
, (PCHAR
)(*SecurityDesc
), &NumberBytesRead
);
884 Fcb
->NTRequiredFCB
->NtReqFCBFlags
&= ~UDF_NTREQ_FCB_SD_MODIFIED
;
891 UDFCloseFile__(Vcb
, AclInfo
);
892 if(UDFCleanUpFile__(Vcb
, AclInfo
))
893 MyFreePool__(AclInfo
);
897 UDFCloseFile__(Vcb
, SDirInfo
);
898 if(UDFCleanUpFile__(Vcb
, SDirInfo
))
899 MyFreePool__(SDirInfo
);
902 UDFReleaseResource(Res1
);
907 #endif //!defined(UDF_READ_ONLY_BUILD)
908 #endif //UDF_ENABLE_SECURITY
910 return STATUS_SUCCESS
;
912 } // end UDFWriteSecurity()
917 PFILE_OBJECT FileObject
, // OPTIONAL
921 UDFAssignAcl(Vcb
, FileObject
, Fcb
, Fcb
->NTRequiredFCB
);
922 return (Fcb
->NTRequiredFCB
->SecurityDesc
);
923 } // end UDFLookUpAcl()
927 UDFCheckAccessRights(
928 PFILE_OBJECT FileObject
, // OPTIONAL
929 PACCESS_STATE AccessState
,
931 PtrUDFCCB Ccb
, // OPTIONAL
932 ACCESS_MASK DesiredAccess
,
937 BOOLEAN ROCheck
= FALSE
;
938 #ifdef UDF_ENABLE_SECURITY
939 BOOLEAN SecurityCheck
;
940 PSECURITY_DESCRIPTOR SecDesc
;
941 SECURITY_SUBJECT_CONTEXT SubjectContext
;
942 ACCESS_MASK LocalAccessMask
;
943 #endif //UDF_ENABLE_SECURITY
945 // Check attr compatibility
948 #ifdef UDF_READ_ONLY_BUILD
950 #endif //UDF_READ_ONLY_BUILD
952 if(Fcb
->FCBFlags
& UDF_FCB_READ_ONLY
) {
955 if((Fcb
->Vcb
->origIntegrityType
== INTEGRITY_TYPE_OPEN
) &&
956 Ccb
&& !(Ccb
->CCBFlags
& UDF_CCB_VOLUME_OPEN
) &&
957 (Fcb
->Vcb
->CompatFlags
& UDF_VCB_IC_DIRTY_RO
)) {
958 AdPrint(("force R/O on dirty\n"));
962 #ifdef UDF_READ_ONLY_BUILD
964 #endif //UDF_READ_ONLY_BUILD
965 ACCESS_MASK DesiredAccessMask
= 0;
967 if(Fcb
->Vcb
->CompatFlags
& UDF_VCB_IC_WRITE_IN_RO_DIR
) {
968 if(Fcb
->FCBFlags
& UDF_FCB_DIRECTORY
) {
969 DesiredAccessMask
= (FILE_WRITE_EA
|
972 DesiredAccessMask
= (FILE_WRITE_DATA
|
978 DesiredAccessMask
= (FILE_WRITE_DATA
|
982 FILE_ADD_SUBDIRECTORY
|
986 if(DesiredAccess
& DesiredAccessMask
)
987 return STATUS_ACCESS_DENIED
;
989 #ifdef UDF_ENABLE_SECURITY
991 // NOTE: we should not perform security check if an empty DesiredAccess
992 // was specified. AFAIU, SeAccessCheck() will return FALSE in this case.
993 SecDesc
= UDFLookUpAcl(Fcb
->Vcb
, FileObject
, Fcb
);
994 if(SecDesc
&& DesiredAccess
) {
995 SeCaptureSubjectContext(&SubjectContext
);
997 SeAccessCheck(SecDesc
,
1001 Ccb
? Ccb
->PreviouslyGrantedAccess
: 0,
1003 IoGetFileObjectGenericMapping(),
1005 Ccb
? &(Ccb
->PreviouslyGrantedAccess
) : &LocalAccessMask
,
1007 SeReleaseSubjectContext(&SubjectContext
);
1009 if(!SecurityCheck
) {
1012 #endif //UDF_ENABLE_SECURITY
1013 if(DesiredAccess
& ACCESS_SYSTEM_SECURITY
) {
1014 if (!SeSinglePrivilegeCheck(SeExports
->SeSecurityPrivilege
, UserMode
))
1015 return STATUS_ACCESS_DENIED
;
1016 Ccb
->PreviouslyGrantedAccess
|= ACCESS_SYSTEM_SECURITY
;
1018 #ifdef UDF_ENABLE_SECURITY
1020 #endif //UDF_ENABLE_SECURITY
1022 if (Fcb
->OpenHandleCount
) {
1023 // The FCB is currently in use by some thread.
1024 // We must check whether the requested access/share access
1025 // conflicts with the existing open operations.
1026 RC
= IoCheckShareAccess(DesiredAccess
, ShareAccess
, FileObject
,
1027 &(Fcb
->NTRequiredFCB
->FCBShareAccess
), TRUE
);
1028 #ifndef UDF_ENABLE_SECURITY
1030 Ccb
->PreviouslyGrantedAccess
|= DesiredAccess
;
1031 IoUpdateShareAccess(FileObject
, &(Fcb
->NTRequiredFCB
->FCBShareAccess
));
1032 #endif //UDF_ENABLE_SECURITY
1034 IoSetShareAccess(DesiredAccess
, ShareAccess
, FileObject
, &(Fcb
->NTRequiredFCB
->FCBShareAccess
));
1035 #ifndef UDF_ENABLE_SECURITY
1037 Ccb
->PreviouslyGrantedAccess
= DesiredAccess
;
1038 #endif //UDF_ENABLE_SECURITY
1039 RC
= STATUS_SUCCESS
;
1042 // we get here if given file was opened for internal purposes
1043 RC
= STATUS_SUCCESS
;
1046 } // end UDFCheckAccessRights()
1050 PFILE_OBJECT FileObject
,
1051 PACCESS_STATE AccessState
,
1054 ACCESS_MASK DesiredAccess
,
1058 #ifndef UDF_ENABLE_SECURITY
1060 ASSERT(Fcb
->FileInfo
);
1062 return UDFCheckAccessRights(FileObject
, AccessState
, Fcb
, Ccb
, DesiredAccess
, ShareAccess
);
1064 #else //UDF_ENABLE_SECURITY
1067 // Set Security on Object
1068 PSECURITY_DESCRIPTOR SecDesc
;
1069 SECURITY_SUBJECT_CONTEXT SubjectContext
;
1070 BOOLEAN AutoInherit
;
1073 ASSERT(Fcb
->FileInfo
);
1075 SecDesc
= UDFLookUpAcl(Fcb
->Vcb
, FileObject
, Fcb
);
1076 AutoInherit
= UDFIsAStreamDir(Fcb
->FileInfo
) || UDFIsAStream(Fcb
->FileInfo
);
1078 if(SecDesc
&& !AutoInherit
) {
1079 // Get caller's User/Primary Group info
1080 SeCaptureSubjectContext(&SubjectContext
);
1081 RC
= SeAssignSecurity(
1082 Fcb
->FileInfo
->ParentFile
->Dloc
->CommonFcb
->SecurityDesc
,
1084 AccessState
->SecurityDescriptor
,
1085 &(Fcb
->NTRequiredFCB
->SecurityDesc
),
1086 UDFIsADirectory(Fcb
->FileInfo
),
1088 IoGetFileObjectGenericMapping(),
1090 SeReleaseSubjectContext(&SubjectContext
);
1091 UDFConvertToSelfRelative(&(Fcb
->NTRequiredFCB
->SecurityDesc
));
1093 if(!NT_SUCCESS(RC
)) {
1095 UDFDeassignAcl(Fcb
->NTRequiredFCB
, AutoInherit
);
1100 RC
= UDFCheckAccessRights(FileObject
, AccessState
, Fcb
, Ccb
, DesiredAccess
, ShareAccess
);
1105 #endif //UDF_ENABLE_SECURITY
1107 } // end UDFSetAccessRights()