1 //////////////////////////////////////////////////////////////////// 2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3 // All rights reserved 4 // This file was released under the GPLv2 on June 2015. 5 //////////////////////////////////////////////////////////////////// 6 /************************************************************************* 7 * 8 * File: SecurSup.cpp 9 * 10 * Module: UDF File System Driver (Kernel mode execution only) 11 * 12 * Description: 13 * Contains code to handle the "Get/Set Security" dispatch entry points. 14 * 15 *************************************************************************/ 16 17 #include "udffs.h" 18 19 // define the file specific bug-check id 20 #define UDF_BUG_CHECK_ID UDF_FILE_SECURITY 21 22 #ifdef UDF_ENABLE_SECURITY 23 24 NTSTATUS UDFConvertToSelfRelative( 25 IN OUT PSECURITY_DESCRIPTOR* SecurityDesc); 26 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 41 };*/ 42 43 /************************************************************************* 44 * 45 * Function: UDFGetSecurity() 46 * 47 * Description: 48 * 49 * Expected Interrupt Level (for execution) : 50 * 51 * IRQL_PASSIVE_LEVEL 52 * 53 * Return Value: Irrelevant. 54 * 55 *************************************************************************/ 56 NTSTATUS 57 UDFGetSecurity( 58 IN PDEVICE_OBJECT DeviceObject, // the logical volume device object 59 IN PIRP Irp) // I/O Request Packet 60 { 61 NTSTATUS RC = STATUS_SUCCESS; 62 PtrUDFIrpContext PtrIrpContext = NULL; 63 BOOLEAN AreWeTopLevel = FALSE; 64 65 UDFPrint(("UDFGetSecurity\n")); 66 // BrutePoint(); 67 68 FsRtlEnterFileSystem(); 69 ASSERT(DeviceObject); 70 ASSERT(Irp); 71 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 76 // synchronous 77 _SEH2_TRY { 78 79 // get an IRP context structure and issue the request 80 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject); 81 if(PtrIrpContext) { 82 RC = UDFCommonGetSecurity(PtrIrpContext, Irp); 83 } else { 84 RC = STATUS_INSUFFICIENT_RESOURCES; 85 Irp->IoStatus.Status = RC; 86 Irp->IoStatus.Information = 0; 87 // complete the IRP 88 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 89 } 90 91 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 92 93 RC = UDFExceptionHandler(PtrIrpContext, Irp); 94 95 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); 96 } 97 98 if (AreWeTopLevel) { 99 IoSetTopLevelIrp(NULL); 100 } 101 102 FsRtlExitFileSystem(); 103 104 return(RC); 105 } // end UDFGetSecurity() 106 107 108 /************************************************************************* 109 * 110 * Function: UDFCommonGetSecurity() 111 * 112 * Description: 113 * This is the common routine for getting Security (ACL) called 114 * by both the fsd and fsp threads 115 * 116 * Expected Interrupt Level (for execution) : 117 * 118 * IRQL_PASSIVE_LEVEL 119 * 120 * Return Value: Irrelevant 121 * 122 *************************************************************************/ 123 NTSTATUS 124 UDFCommonGetSecurity( 125 IN PtrUDFIrpContext PtrIrpContext, 126 IN PIRP Irp) 127 { 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; 139 140 UDFPrint(("UDFCommonGetSecurity\n")); 141 142 _SEH2_TRY { 143 144 // First, get a pointer to the current I/O stack location. 145 IrpSp = IoGetCurrentIrpStackLocation(Irp); 146 ASSERT(IrpSp); 147 148 FileObject = IrpSp->FileObject; 149 ASSERT(FileObject); 150 151 // Get the FCB and CCB pointers. 152 Ccb = (PtrUDFCCB)(FileObject->FsContext2); 153 ASSERT(Ccb); 154 Fcb = Ccb->Fcb; 155 ASSERT(Fcb); 156 157 /* if(!Fcb->Vcb->ReadSecurity) 158 try_return(RC = STATUS_NOT_IMPLEMENTED);*/ 159 160 NtReqFcb = Fcb->NTRequiredFCB; 161 CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 162 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)) { 167 PostRequest = TRUE; 168 try_return(RC = STATUS_PENDING); 169 } 170 AcquiredFCB = TRUE; 171 172 PtrSystemBuffer = UDFGetCallersBuffer(PtrIrpContext, Irp); 173 if(!PtrSystemBuffer) 174 try_return(RC = STATUS_INVALID_USER_BUFFER); 175 BufferLength = IrpSp->Parameters.QuerySecurity.Length; 176 177 if(!NtReqFcb->SecurityDesc) { 178 RC = UDFAssignAcl(Fcb->Vcb, FileObject, Fcb, NtReqFcb); 179 if(!NT_SUCCESS(RC)) 180 try_return(RC); 181 } 182 183 _SEH2_TRY { 184 RC = SeQuerySecurityDescriptorInfo(&(IrpSp->Parameters.QuerySecurity.SecurityInformation), 185 (PSECURITY_DESCRIPTOR)PtrSystemBuffer, 186 &BufferLength, 187 &(NtReqFcb->SecurityDesc) ); 188 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 189 RC = STATUS_BUFFER_TOO_SMALL; 190 } 191 192 try_exit: NOTHING; 193 194 } _SEH2_FINALLY { 195 196 // Release the FCB resources if acquired. 197 if (AcquiredFCB) { 198 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); 199 UDFReleaseResource(&(NtReqFcb->MainResource)); 200 AcquiredFCB = FALSE; 201 } 202 203 if (PostRequest) { 204 // Perform appropriate post related processing here 205 RC = UDFPostRequest(PtrIrpContext, Irp); 206 } else 207 if(!AbnormalTermination()) { 208 Irp->IoStatus.Status = RC; 209 Irp->IoStatus.Information = BufferLength; 210 // Free up the Irp Context 211 UDFReleaseIrpContext(PtrIrpContext); 212 // complete the IRP 213 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 214 } 215 216 } // end of "__finally" processing 217 218 return(RC); 219 } 220 221 #ifndef UDF_READ_ONLY_BUILD 222 /************************************************************************* 223 * 224 * Function: UDFSetSecurity() 225 * 226 * Description: 227 * 228 * Expected Interrupt Level (for execution) : 229 * 230 * IRQL_PASSIVE_LEVEL 231 * 232 * Return Value: Irrelevant. 233 * 234 *************************************************************************/ 235 NTSTATUS 236 UDFSetSecurity( 237 IN PDEVICE_OBJECT DeviceObject, // the logical volume device object 238 IN PIRP Irp) // I/O Request Packet 239 { 240 NTSTATUS RC = STATUS_SUCCESS; 241 PtrUDFIrpContext PtrIrpContext = NULL; 242 BOOLEAN AreWeTopLevel = FALSE; 243 244 UDFPrint(("UDFSetSecurity\n")); 245 // BrutePoint(); 246 247 FsRtlEnterFileSystem(); 248 ASSERT(DeviceObject); 249 ASSERT(Irp); 250 251 // set the top level context 252 AreWeTopLevel = UDFIsIrpTopLevel(Irp); 253 // Call the common Lock Control routine, with blocking allowed if 254 // synchronous 255 _SEH2_TRY { 256 257 // get an IRP context structure and issue the request 258 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject); 259 if(PtrIrpContext) { 260 RC = UDFCommonSetSecurity(PtrIrpContext, Irp); 261 } else { 262 RC = STATUS_INSUFFICIENT_RESOURCES; 263 Irp->IoStatus.Status = RC; 264 Irp->IoStatus.Information = 0; 265 // complete the IRP 266 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 267 } 268 269 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 270 271 RC = UDFExceptionHandler(PtrIrpContext, Irp); 272 273 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); 274 } 275 276 if (AreWeTopLevel) { 277 IoSetTopLevelIrp(NULL); 278 } 279 280 FsRtlExitFileSystem(); 281 282 return(RC); 283 } // end UDFSetSecurity() 284 285 286 /************************************************************************* 287 * 288 * Function: UDFCommonSetSecurity() 289 * 290 * Description: 291 * This is the common routine for getting Security (ACL) called 292 * by both the fsd and fsp threads 293 * 294 * Expected Interrupt Level (for execution) : 295 * 296 * IRQL_PASSIVE_LEVEL 297 * 298 * Return Value: Irrelevant 299 * 300 *************************************************************************/ 301 NTSTATUS 302 UDFCommonSetSecurity( 303 IN PtrUDFIrpContext PtrIrpContext, 304 IN PIRP Irp) 305 { 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; 316 317 UDFPrint(("UDFCommonSetSecurity\n")); 318 319 _SEH2_TRY { 320 321 // First, get a pointer to the current I/O stack location. 322 IrpSp = IoGetCurrentIrpStackLocation(Irp); 323 ASSERT(IrpSp); 324 325 FileObject = IrpSp->FileObject; 326 ASSERT(FileObject); 327 328 // Get the FCB and CCB pointers. 329 Ccb = (PtrUDFCCB)(FileObject->FsContext2); 330 ASSERT(Ccb); 331 Fcb = Ccb->Fcb; 332 ASSERT(Fcb); 333 334 if(!Fcb->Vcb->WriteSecurity) 335 try_return(RC = STATUS_NOT_IMPLEMENTED); 336 337 NtReqFcb = Fcb->NTRequiredFCB; 338 CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 339 340 // Acquire the FCB resource exclusive 341 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); 342 if (!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) { 343 PostRequest = TRUE; 344 try_return(RC = STATUS_PENDING); 345 } 346 AcquiredFCB = TRUE; 347 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; 360 361 _SEH2_TRY { 362 UDFConvertToSelfRelative(&(NtReqFcb->SecurityDesc)); 363 364 KdDump(NtReqFcb->SecurityDesc, RtlLengthSecurityDescriptor(NtReqFcb->SecurityDesc)); 365 UDFPrint(("\n")); 366 367 RC = SeSetSecurityDescriptorInfo(/*FileObject*/ NULL, 368 &(IrpSp->Parameters.SetSecurity.SecurityInformation), 369 IrpSp->Parameters.SetSecurity.SecurityDescriptor, 370 &(NtReqFcb->SecurityDesc), 371 NonPagedPool, 372 IoGetFileObjectGenericMapping() ); 373 374 KdDump(NtReqFcb->SecurityDesc, RtlLengthSecurityDescriptor(NtReqFcb->SecurityDesc)); 375 376 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 377 RC = STATUS_INVALID_PARAMETER; 378 } 379 if(NT_SUCCESS(RC)) { 380 NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_SD_MODIFIED; 381 382 UDFNotifyFullReportChange( Fcb->Vcb, Fcb->FileInfo, 383 FILE_NOTIFY_CHANGE_SECURITY, 384 FILE_ACTION_MODIFIED); 385 } 386 387 try_exit: NOTHING; 388 389 } _SEH2_FINALLY { 390 391 // Release the FCB resources if acquired. 392 if (AcquiredFCB) { 393 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); 394 UDFReleaseResource(&(NtReqFcb->MainResource)); 395 AcquiredFCB = FALSE; 396 } 397 398 if (PostRequest) { 399 // Perform appropriate post related processing here 400 RC = UDFPostRequest(PtrIrpContext, Irp); 401 } else 402 if(!AbnormalTermination()) { 403 Irp->IoStatus.Status = RC; 404 Irp->IoStatus.Information = 0; 405 // Free up the Irp Context 406 UDFReleaseIrpContext(PtrIrpContext); 407 // complete the IRP 408 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 409 } 410 411 } // end of "__finally" processing 412 413 return(RC); 414 } // ens UDFCommonSetSecurity() 415 416 #endif //UDF_READ_ONLY_BUILD 417 #endif //UDF_ENABLE_SECURITY 418 419 NTSTATUS 420 UDFReadSecurity( 421 IN PVCB Vcb, 422 IN PtrUDFFCB Fcb, 423 IN PSECURITY_DESCRIPTOR* SecurityDesc 424 ) 425 { 426 #ifdef UDF_ENABLE_SECURITY 427 PUDF_FILE_INFO FileInfo = NULL; 428 PUDF_FILE_INFO SDirInfo = NULL; 429 PUDF_FILE_INFO AclInfo = NULL; 430 NTSTATUS RC; 431 ULONG NumberBytesRead; 432 PERESOURCE Res1 = NULL; 433 434 UDFPrint(("UDFReadSecurity\n")); 435 436 _SEH2_TRY { 437 438 FileInfo = Fcb->FileInfo; 439 ASSERT(FileInfo); 440 if(!FileInfo) { 441 UDFPrint((" Volume Security\n")); 442 try_return(RC = STATUS_NO_SECURITY_ON_OBJECT); 443 } 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); 447 } 448 449 // Open Stream Directory 450 RC = UDFOpenStreamDir__(Vcb, FileInfo, &SDirInfo); 451 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); 457 } 458 SDirInfo = NULL; 459 try_return(RC); 460 } 461 // Acquire SDir exclusively if Fcb present 462 if(SDirInfo->Fcb) { 463 BrutePoint(); 464 UDF_CHECK_PAGING_IO_RESOURCE(SDirInfo->Fcb->NTRequiredFCB); 465 UDFAcquireResourceExclusive(Res1 = &(SDirInfo->Fcb->NTRequiredFCB->MainResource),TRUE); 466 } 467 468 // Open Acl Stream 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); 477 } 478 AclInfo = NULL; 479 try_return(RC); 480 } 481 482 NumberBytesRead = (ULONG)UDFGetFileSize(AclInfo); 483 (*SecurityDesc) = DbgAllocatePool(NonPagedPool, NumberBytesRead); 484 if(!(*SecurityDesc)) 485 try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 486 RC = UDFReadFile__(Vcb, AclInfo, 0, NumberBytesRead, 487 FALSE, (PCHAR)(*SecurityDesc), &NumberBytesRead); 488 if(!NT_SUCCESS(RC)) 489 try_return(RC); 490 491 RC = RtlValidSecurityDescriptor(*SecurityDesc); 492 493 try_exit: NOTHING; 494 495 } _SEH2_FINALLY { 496 497 if(AclInfo) { 498 UDFCloseFile__(Vcb, AclInfo); 499 if(UDFCleanUpFile__(Vcb, AclInfo)) 500 MyFreePool__(AclInfo); 501 } 502 503 if(SDirInfo) { 504 UDFCloseFile__(Vcb, SDirInfo); 505 if(UDFCleanUpFile__(Vcb, SDirInfo)) 506 MyFreePool__(SDirInfo); 507 } 508 509 if(!NT_SUCCESS(RC) && (*SecurityDesc)) { 510 DbgFreePool(*SecurityDesc); 511 (*SecurityDesc) = NULL; 512 } 513 if(Res1) 514 UDFReleaseResource(Res1); 515 } 516 517 return RC; 518 #else 519 return STATUS_NO_SECURITY_ON_OBJECT; 520 #endif //UDF_ENABLE_SECURITY 521 522 } // end UDFReadSecurity() 523 524 #ifdef UDF_ENABLE_SECURITY 525 NTSTATUS 526 UDFConvertToSelfRelative( 527 IN OUT PSECURITY_DESCRIPTOR* SecurityDesc 528 ) 529 { 530 NTSTATUS RC; 531 SECURITY_INFORMATION SecurityInformation; 532 PSECURITY_DESCRIPTOR NewSD; 533 ULONG Len; 534 535 UDFPrint((" UDFConvertToSelfRelative\n")); 536 537 if(!(*SecurityDesc)) 538 return STATUS_NO_SECURITY_ON_OBJECT; 539 540 SecurityInformation = FULL_SECURITY_INFORMATION; 541 Len = RtlLengthSecurityDescriptor(*SecurityDesc); 542 ASSERT(Len <= 1024); 543 NewSD = (PSECURITY_DESCRIPTOR)DbgAllocatePool(NonPagedPool, Len); 544 if(!NewSD) 545 return STATUS_INSUFFICIENT_RESOURCES; 546 _SEH2_TRY { 547 RC = SeQuerySecurityDescriptorInfo(&SecurityInformation, NewSD, &Len, SecurityDesc); 548 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 549 RC = STATUS_INSUFFICIENT_RESOURCES; 550 } 551 552 if(NT_SUCCESS(RC)) { 553 DbgFreePool(*SecurityDesc); 554 *SecurityDesc = NewSD; 555 } else { 556 DbgFreePool(NewSD); 557 } 558 return RC; 559 } // end UDFConvertToSelfRelative() 560 561 NTSTATUS 562 UDFInheritAcl( 563 IN PVCB Vcb, 564 IN PSECURITY_DESCRIPTOR* ParentSecurityDesc, 565 IN OUT PSECURITY_DESCRIPTOR* SecurityDesc 566 ) 567 { 568 NTSTATUS RC; 569 SECURITY_INFORMATION SecurityInformation; 570 ULONG Len; 571 572 UDFPrint((" UDFInheritAcl\n")); 573 574 if(!(*ParentSecurityDesc)) { 575 *SecurityDesc = NULL; 576 return STATUS_SUCCESS; 577 } 578 579 SecurityInformation = FULL_SECURITY_INFORMATION; 580 Len = RtlLengthSecurityDescriptor(*ParentSecurityDesc); 581 *SecurityDesc = (PSECURITY_DESCRIPTOR)DbgAllocatePool(NonPagedPool, Len); 582 if(!(*SecurityDesc)) 583 return STATUS_INSUFFICIENT_RESOURCES; 584 _SEH2_TRY { 585 RC = SeQuerySecurityDescriptorInfo(&SecurityInformation, *SecurityDesc, &Len, ParentSecurityDesc); 586 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 587 RC = STATUS_INSUFFICIENT_RESOURCES; 588 } 589 590 if(!NT_SUCCESS(RC)) { 591 DbgFreePool(*SecurityDesc); 592 *SecurityDesc = NULL; 593 } 594 return RC; 595 } // end UDFInheritAcl() 596 597 NTSTATUS 598 UDFBuildEmptyAcl( 599 IN PVCB Vcb, 600 IN PSECURITY_DESCRIPTOR* SecurityDesc 601 ) 602 { 603 NTSTATUS RC; 604 ULONG Len = 2 * (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(ULONG)*4 /*RtlLengthSid(SeExports->SeWorldSid)*/); 605 606 UDFPrint((" UDFBuildEmptyAcl\n")); 607 // Create Security Descriptor 608 (*SecurityDesc) = (PSECURITY_DESCRIPTOR)DbgAllocatePool(NonPagedPool, 609 sizeof(SECURITY_DESCRIPTOR) + Len); 610 if(!(*SecurityDesc)) 611 return STATUS_INSUFFICIENT_RESOURCES; 612 613 RC = RtlCreateSecurityDescriptor(*SecurityDesc, SECURITY_DESCRIPTOR_REVISION); 614 615 if(!NT_SUCCESS(RC)) { 616 DbgFreePool(*SecurityDesc); 617 *((PULONG)SecurityDesc) = NULL; 618 } 619 return RC; 620 } // end UDFBuildEmptyAcl() 621 622 NTSTATUS 623 UDFBuildFullControlAcl( 624 IN PVCB Vcb, 625 IN PSECURITY_DESCRIPTOR* SecurityDesc 626 ) 627 { 628 NTSTATUS RC; 629 PACL Acl; 630 ULONG Len = sizeof(ACL) + 2*(sizeof(ACCESS_ALLOWED_ACE) + sizeof(ULONG)*4 /*- sizeof(ULONG)*/ /*+ RtlLengthSid(SeExports->SeWorldSid)*/); 631 632 UDFPrint((" UDFBuildFullControlAcl\n")); 633 // Create Security Descriptor 634 RC = UDFBuildEmptyAcl(Vcb, SecurityDesc); 635 if(!NT_SUCCESS(RC)) 636 return RC; 637 638 // Set Owner 639 RC = RtlSetOwnerSecurityDescriptor(*SecurityDesc, SeExports->SeWorldSid, FALSE); 640 if(!NT_SUCCESS(RC)) { 641 DbgFreePool(*SecurityDesc); 642 *((PULONG)SecurityDesc) = NULL; 643 return RC; 644 } 645 646 // Set Group 647 RC = RtlSetGroupSecurityDescriptor(*SecurityDesc, SeExports->SeWorldSid, FALSE); 648 if(!NT_SUCCESS(RC)) { 649 DbgFreePool(*SecurityDesc); 650 *((PULONG)SecurityDesc) = NULL; 651 return RC; 652 } 653 654 // Create empty Acl 655 Acl = (PACL)DbgAllocatePool(NonPagedPool, Len); 656 if(!Acl) { 657 DbgFreePool(*SecurityDesc); 658 *((PULONG)SecurityDesc) = NULL; 659 return RC; 660 } 661 RtlZeroMemory(Acl, Len); 662 663 RC = RtlCreateAcl(Acl, Len, ACL_REVISION); 664 if(!NT_SUCCESS(RC)) { 665 DbgFreePool(Acl); 666 DbgFreePool(*SecurityDesc); 667 *((PULONG)SecurityDesc) = NULL; 668 return RC; 669 } 670 671 // Add (All)(All) access for Everyone 672 /* RC = RtlAddAccessAllowedAce(Acl, ACL_REVISION, 673 GENERIC_ALL, 674 SeExports->SeWorldSid);*/ 675 676 RC = RtlAddAccessAllowedAce(Acl, ACL_REVISION, 677 FILE_ALL_ACCESS, 678 SeExports->SeWorldSid); 679 680 if(!NT_SUCCESS(RC)) { 681 DbgFreePool(Acl); 682 DbgFreePool(*SecurityDesc); 683 *((PULONG)SecurityDesc) = NULL; 684 return RC; 685 } 686 687 // Add Acl to Security Descriptor 688 RC = RtlSetDaclSecurityDescriptor(*SecurityDesc, TRUE, Acl, FALSE); 689 if(!NT_SUCCESS(RC)) { 690 DbgFreePool(Acl); 691 DbgFreePool(*SecurityDesc); 692 *((PULONG)SecurityDesc) = NULL; 693 return RC; 694 } 695 696 RC = UDFConvertToSelfRelative(SecurityDesc); 697 698 DbgFreePool(Acl); 699 700 return RC; 701 } // end UDFBuildFullControlAcl() 702 703 #endif // UDF_ENABLE_SECURITY 704 705 NTSTATUS 706 UDFAssignAcl( 707 IN PVCB Vcb, 708 IN PFILE_OBJECT FileObject, // OPTIONAL 709 IN PtrUDFFCB Fcb, 710 IN PtrUDFNTRequiredFCB NtReqFcb 711 ) 712 { 713 NTSTATUS RC = STATUS_SUCCESS; 714 #ifdef UDF_ENABLE_SECURITY 715 // SECURITY_INFORMATION SecurityInformation; 716 717 // UDFPrint((" UDFAssignAcl\n")); 718 if(!NtReqFcb->SecurityDesc) { 719 720 PSECURITY_DESCRIPTOR ExplicitSecurity = NULL; 721 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; 726 } else 727 if(!Fcb->FileInfo) { 728 // Volume security 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); 734 } else { 735 NtReqFcb->SecurityDesc = NULL; 736 RC = STATUS_NO_SECURITY_ON_OBJECT; 737 } 738 return RC; 739 } 740 741 RC = UDFReadSecurity(Vcb, Fcb, &ExplicitSecurity); 742 if(RC == STATUS_NO_SECURITY_ON_OBJECT) { 743 if(!Fcb->FileInfo->ParentFile) { 744 RC = UDFBuildFullControlAcl(Vcb, &ExplicitSecurity); 745 } else { 746 RC = UDFInheritAcl(Vcb, &(Fcb->FileInfo->ParentFile->Dloc->CommonFcb->SecurityDesc), &ExplicitSecurity); 747 } 748 /* if(NT_SUCCESS(RC)) { 749 NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_SD_MODIFIED; 750 }*/ 751 } 752 if(NT_SUCCESS(RC)) { 753 754 // SecurityInformation = FULL_SECURITY_INFORMATION; 755 NtReqFcb->SecurityDesc = ExplicitSecurity; 756 757 /* RC = SeSetSecurityDescriptorInfo(FileObject, 758 &SecurityInformation, 759 ExplicitSecurity, 760 &(NtReqFcb->SecurityDesc), 761 NonPagedPool, 762 IoGetFileObjectGenericMapping() );*/ 763 764 } 765 } 766 #endif //UDF_ENABLE_SECURITY 767 return RC; 768 } // end UDFAssignAcl() 769 770 771 VOID 772 UDFDeassignAcl( 773 IN PtrUDFNTRequiredFCB NtReqFcb, 774 IN BOOLEAN AutoInherited 775 ) 776 { 777 #ifdef UDF_ENABLE_SECURITY 778 // NTSTATUS RC = STATUS_SUCCESS; 779 780 // UDFPrint((" UDFDeassignAcl\n")); 781 if(!NtReqFcb->SecurityDesc) 782 return; 783 784 if(AutoInherited) { 785 NtReqFcb->SecurityDesc = NULL; 786 return; 787 } 788 789 SeDeassignSecurity(&(NtReqFcb->SecurityDesc)); 790 NtReqFcb->SecurityDesc = NULL; // HA BCRK CLU4 791 #endif //UDF_ENABLE_SECURITY 792 return; 793 } // end UDFDeassignAcl() 794 795 NTSTATUS 796 UDFWriteSecurity( 797 IN PVCB Vcb, 798 IN PtrUDFFCB Fcb, 799 IN PSECURITY_DESCRIPTOR* SecurityDesc 800 ) 801 { 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; 807 NTSTATUS RC; 808 ULONG NumberBytesRead; 809 810 // UDFPrint(("UDFWriteSecurity\n")); 811 812 #if !defined(UDF_READ_ONLY_BUILD) 813 814 if(!Vcb->WriteSecurity || 815 (Vcb->VCBFlags & (UDF_VCB_FLAGS_VOLUME_READ_ONLY | 816 UDF_VCB_FLAGS_MEDIA_READ_ONLY))) 817 818 #endif //!defined(UDF_READ_ONLY_BUILD) 819 820 return STATUS_SUCCESS; 821 822 #if !defined(UDF_READ_ONLY_BUILD) 823 824 _SEH2_TRY { 825 826 FileInfo = Fcb->FileInfo; 827 ASSERT(FileInfo); 828 if(!FileInfo) { 829 UDFPrint((" Volume Security\n")); 830 try_return(RC = STATUS_SUCCESS); 831 } 832 833 if(!(Fcb->NTRequiredFCB->NtReqFCBFlags & UDF_NTREQ_FCB_SD_MODIFIED)) 834 try_return(RC = STATUS_SUCCESS); 835 836 // Open Stream Directory 837 RC = UDFOpenStreamDir__(Vcb, FileInfo, &SDirInfo); 838 839 if(RC == STATUS_NOT_FOUND) { 840 RC = UDFCreateStreamDir__(Vcb, FileInfo, &SDirInfo); 841 } 842 if(!NT_SUCCESS(RC)) { 843 if(UDFCleanUpFile__(Vcb, SDirInfo)) { 844 if(SDirInfo) MyFreePool__(SDirInfo); 845 } 846 SDirInfo = NULL; 847 try_return(RC); 848 } 849 // Acquire SDir exclusively if Fcb present 850 if(SDirInfo->Fcb) { 851 BrutePoint(); 852 UDF_CHECK_PAGING_IO_RESOURCE(SDirInfo->Fcb->NTRequiredFCB); 853 UDFAcquireResourceExclusive(Res1 = &(SDirInfo->Fcb->NTRequiredFCB->MainResource),TRUE); 854 } 855 856 // Open Acl Stream 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); 863 } 864 if(!NT_SUCCESS(RC)) { 865 if(UDFCleanUpFile__(Vcb, AclInfo)) { 866 if(AclInfo) MyFreePool__(AclInfo); 867 } 868 AclInfo = NULL; 869 try_return(RC); 870 } 871 872 if(!(*SecurityDesc)) { 873 UDFFlushFile__(Vcb, AclInfo); 874 RC = UDFUnlinkFile__(Vcb, AclInfo, TRUE); 875 try_return(RC); 876 } 877 NumberBytesRead = RtlLengthSecurityDescriptor(*SecurityDesc); 878 879 RC = UDFWriteFile__(Vcb, AclInfo, 0, NumberBytesRead, 880 FALSE, (PCHAR)(*SecurityDesc), &NumberBytesRead); 881 if(!NT_SUCCESS(RC)) 882 try_return(RC); 883 884 Fcb->NTRequiredFCB->NtReqFCBFlags &= ~UDF_NTREQ_FCB_SD_MODIFIED; 885 886 try_exit: NOTHING; 887 888 } _SEH2_FINALLY { 889 890 if(AclInfo) { 891 UDFCloseFile__(Vcb, AclInfo); 892 if(UDFCleanUpFile__(Vcb, AclInfo)) 893 MyFreePool__(AclInfo); 894 } 895 896 if(SDirInfo) { 897 UDFCloseFile__(Vcb, SDirInfo); 898 if(UDFCleanUpFile__(Vcb, SDirInfo)) 899 MyFreePool__(SDirInfo); 900 } 901 if(Res1) 902 UDFReleaseResource(Res1); 903 } 904 905 return RC; 906 907 #endif //!defined(UDF_READ_ONLY_BUILD) 908 #endif //UDF_ENABLE_SECURITY 909 910 return STATUS_SUCCESS; 911 912 } // end UDFWriteSecurity() 913 914 PSECURITY_DESCRIPTOR 915 UDFLookUpAcl( 916 IN PVCB Vcb, 917 PFILE_OBJECT FileObject, // OPTIONAL 918 IN PtrUDFFCB Fcb 919 ) 920 { 921 UDFAssignAcl(Vcb, FileObject, Fcb, Fcb->NTRequiredFCB); 922 return (Fcb->NTRequiredFCB->SecurityDesc); 923 } // end UDFLookUpAcl() 924 925 926 NTSTATUS 927 UDFCheckAccessRights( 928 PFILE_OBJECT FileObject, // OPTIONAL 929 PACCESS_STATE AccessState, 930 PtrUDFFCB Fcb, 931 PtrUDFCCB Ccb, // OPTIONAL 932 ACCESS_MASK DesiredAccess, 933 USHORT ShareAccess 934 ) 935 { 936 NTSTATUS RC; 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 944 945 // Check attr compatibility 946 ASSERT(Fcb); 947 ASSERT(Fcb->Vcb); 948 #ifdef UDF_READ_ONLY_BUILD 949 goto treat_as_ro; 950 #endif //UDF_READ_ONLY_BUILD 951 952 if(Fcb->FCBFlags & UDF_FCB_READ_ONLY) { 953 ROCheck = TRUE; 954 } else 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")); 959 ROCheck = TRUE; 960 } 961 if(ROCheck) { 962 #ifdef UDF_READ_ONLY_BUILD 963 treat_as_ro: 964 #endif //UDF_READ_ONLY_BUILD 965 ACCESS_MASK DesiredAccessMask = 0; 966 967 if(Fcb->Vcb->CompatFlags & UDF_VCB_IC_WRITE_IN_RO_DIR) { 968 if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) { 969 DesiredAccessMask = (FILE_WRITE_EA | 970 DELETE); 971 } else { 972 DesiredAccessMask = (FILE_WRITE_DATA | 973 FILE_APPEND_DATA | 974 FILE_WRITE_EA | 975 DELETE); 976 } 977 } else { 978 DesiredAccessMask = (FILE_WRITE_DATA | 979 FILE_APPEND_DATA | 980 FILE_WRITE_EA | 981 FILE_DELETE_CHILD | 982 FILE_ADD_SUBDIRECTORY | 983 FILE_ADD_FILE | 984 DELETE); 985 } 986 if(DesiredAccess & DesiredAccessMask) 987 return STATUS_ACCESS_DENIED; 988 } 989 #ifdef UDF_ENABLE_SECURITY 990 // Check 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); 996 SecurityCheck = 997 SeAccessCheck(SecDesc, 998 &SubjectContext, 999 FALSE, 1000 DesiredAccess, 1001 Ccb ? Ccb->PreviouslyGrantedAccess : 0, 1002 NULL, 1003 IoGetFileObjectGenericMapping(), 1004 UserMode, 1005 Ccb ? &(Ccb->PreviouslyGrantedAccess) : &LocalAccessMask, 1006 &RC); 1007 SeReleaseSubjectContext(&SubjectContext); 1008 1009 if(!SecurityCheck) { 1010 return RC; 1011 } else 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; 1017 } 1018 #ifdef UDF_ENABLE_SECURITY 1019 } 1020 #endif //UDF_ENABLE_SECURITY 1021 if(FileObject) { 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 1029 if(Ccb) 1030 Ccb->PreviouslyGrantedAccess |= DesiredAccess; 1031 IoUpdateShareAccess(FileObject, &(Fcb->NTRequiredFCB->FCBShareAccess)); 1032 #endif //UDF_ENABLE_SECURITY 1033 } else { 1034 IoSetShareAccess(DesiredAccess, ShareAccess, FileObject, &(Fcb->NTRequiredFCB->FCBShareAccess)); 1035 #ifndef UDF_ENABLE_SECURITY 1036 if(Ccb) 1037 Ccb->PreviouslyGrantedAccess = DesiredAccess; 1038 #endif //UDF_ENABLE_SECURITY 1039 RC = STATUS_SUCCESS; 1040 } 1041 } else { 1042 // we get here if given file was opened for internal purposes 1043 RC = STATUS_SUCCESS; 1044 } 1045 return RC; 1046 } // end UDFCheckAccessRights() 1047 1048 NTSTATUS 1049 UDFSetAccessRights( 1050 PFILE_OBJECT FileObject, 1051 PACCESS_STATE AccessState, 1052 PtrUDFFCB Fcb, 1053 PtrUDFCCB Ccb, 1054 ACCESS_MASK DesiredAccess, 1055 USHORT ShareAccess 1056 ) 1057 { 1058 #ifndef UDF_ENABLE_SECURITY 1059 ASSERT(Ccb); 1060 ASSERT(Fcb->FileInfo); 1061 1062 return UDFCheckAccessRights(FileObject, AccessState, Fcb, Ccb, DesiredAccess, ShareAccess); 1063 1064 #else //UDF_ENABLE_SECURITY 1065 1066 NTSTATUS RC; 1067 // Set Security on Object 1068 PSECURITY_DESCRIPTOR SecDesc; 1069 SECURITY_SUBJECT_CONTEXT SubjectContext; 1070 BOOLEAN AutoInherit; 1071 1072 ASSERT(Ccb); 1073 ASSERT(Fcb->FileInfo); 1074 1075 SecDesc = UDFLookUpAcl(Fcb->Vcb, FileObject, Fcb); 1076 AutoInherit = UDFIsAStreamDir(Fcb->FileInfo) || UDFIsAStream(Fcb->FileInfo); 1077 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, 1083 // NULL, 1084 AccessState->SecurityDescriptor, 1085 &(Fcb->NTRequiredFCB->SecurityDesc), 1086 UDFIsADirectory(Fcb->FileInfo), 1087 &SubjectContext, 1088 IoGetFileObjectGenericMapping(), 1089 NonPagedPool); 1090 SeReleaseSubjectContext(&SubjectContext); 1091 UDFConvertToSelfRelative(&(Fcb->NTRequiredFCB->SecurityDesc)); 1092 1093 if(!NT_SUCCESS(RC)) { 1094 Clean_Up_SD: 1095 UDFDeassignAcl(Fcb->NTRequiredFCB, AutoInherit); 1096 return RC; 1097 } 1098 } 1099 1100 RC = UDFCheckAccessRights(FileObject, AccessState, Fcb, Ccb, DesiredAccess, ShareAccess); 1101 if(!NT_SUCCESS(RC)) 1102 goto Clean_Up_SD; 1103 return RC; 1104 1105 #endif //UDF_ENABLE_SECURITY 1106 1107 } // end UDFSetAccessRights() 1108 1109