1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/se/sd.c 5 * PURPOSE: Security manager 6 * 7 * PROGRAMMERS: David Welch <welch@cwcom.net> 8 */ 9 10 /* INCLUDES *******************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS ********************************************************************/ 17 18 PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL; 19 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL; 20 PSECURITY_DESCRIPTOR SePublicOpenSd = NULL; 21 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL; 22 PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL; 23 PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL; 24 25 /* PRIVATE FUNCTIONS **********************************************************/ 26 27 CODE_SEG("INIT") 28 BOOLEAN 29 NTAPI 30 SepInitSDs(VOID) 31 { 32 /* Create PublicDefaultSd */ 33 SePublicDefaultSd = ExAllocatePoolWithTag(PagedPool, 34 sizeof(SECURITY_DESCRIPTOR), TAG_SD); 35 if (SePublicDefaultSd == NULL) 36 return FALSE; 37 38 RtlCreateSecurityDescriptor(SePublicDefaultSd, 39 SECURITY_DESCRIPTOR_REVISION); 40 RtlSetDaclSecurityDescriptor(SePublicDefaultSd, 41 TRUE, 42 SePublicDefaultDacl, 43 FALSE); 44 45 /* Create PublicDefaultUnrestrictedSd */ 46 SePublicDefaultUnrestrictedSd = ExAllocatePoolWithTag(PagedPool, 47 sizeof(SECURITY_DESCRIPTOR), TAG_SD); 48 if (SePublicDefaultUnrestrictedSd == NULL) 49 return FALSE; 50 51 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd, 52 SECURITY_DESCRIPTOR_REVISION); 53 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd, 54 TRUE, 55 SePublicDefaultUnrestrictedDacl, 56 FALSE); 57 58 /* Create PublicOpenSd */ 59 SePublicOpenSd = ExAllocatePoolWithTag(PagedPool, 60 sizeof(SECURITY_DESCRIPTOR), TAG_SD); 61 if (SePublicOpenSd == NULL) 62 return FALSE; 63 64 RtlCreateSecurityDescriptor(SePublicOpenSd, 65 SECURITY_DESCRIPTOR_REVISION); 66 RtlSetDaclSecurityDescriptor(SePublicOpenSd, 67 TRUE, 68 SePublicOpenDacl, 69 FALSE); 70 71 /* Create PublicOpenUnrestrictedSd */ 72 SePublicOpenUnrestrictedSd = ExAllocatePoolWithTag(PagedPool, 73 sizeof(SECURITY_DESCRIPTOR), TAG_SD); 74 if (SePublicOpenUnrestrictedSd == NULL) 75 return FALSE; 76 77 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd, 78 SECURITY_DESCRIPTOR_REVISION); 79 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd, 80 TRUE, 81 SePublicOpenUnrestrictedDacl, 82 FALSE); 83 84 /* Create SystemDefaultSd */ 85 SeSystemDefaultSd = ExAllocatePoolWithTag(PagedPool, 86 sizeof(SECURITY_DESCRIPTOR), TAG_SD); 87 if (SeSystemDefaultSd == NULL) 88 return FALSE; 89 90 RtlCreateSecurityDescriptor(SeSystemDefaultSd, 91 SECURITY_DESCRIPTOR_REVISION); 92 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd, 93 TRUE, 94 SeSystemDefaultDacl, 95 FALSE); 96 97 /* Create UnrestrictedSd */ 98 SeUnrestrictedSd = ExAllocatePoolWithTag(PagedPool, 99 sizeof(SECURITY_DESCRIPTOR), TAG_SD); 100 if (SeUnrestrictedSd == NULL) 101 return FALSE; 102 103 RtlCreateSecurityDescriptor(SeUnrestrictedSd, 104 SECURITY_DESCRIPTOR_REVISION); 105 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd, 106 TRUE, 107 SeUnrestrictedDacl, 108 FALSE); 109 110 return TRUE; 111 } 112 113 NTSTATUS 114 NTAPI 115 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, 116 PISECURITY_DESCRIPTOR SecurityDescriptor, 117 PULONG BufferLength) 118 { 119 ULONG Current; 120 ULONG SidSize; 121 ULONG SdSize; 122 NTSTATUS Status; 123 PISECURITY_DESCRIPTOR_RELATIVE SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor; 124 125 DPRINT("SeSetWorldSecurityDescriptor() called\n"); 126 127 if (SecurityInformation == 0) 128 { 129 return STATUS_ACCESS_DENIED; 130 } 131 132 /* calculate the minimum size of the buffer */ 133 SidSize = RtlLengthSid(SeWorldSid); 134 SdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 135 if (SecurityInformation & OWNER_SECURITY_INFORMATION) 136 SdSize += SidSize; 137 if (SecurityInformation & GROUP_SECURITY_INFORMATION) 138 SdSize += SidSize; 139 if (SecurityInformation & DACL_SECURITY_INFORMATION) 140 { 141 SdSize += sizeof(ACL) + sizeof(ACE) + SidSize; 142 } 143 144 if (*BufferLength < SdSize) 145 { 146 *BufferLength = SdSize; 147 return STATUS_BUFFER_TOO_SMALL; 148 } 149 150 *BufferLength = SdSize; 151 152 Status = RtlCreateSecurityDescriptorRelative(SdRel, 153 SECURITY_DESCRIPTOR_REVISION); 154 if (!NT_SUCCESS(Status)) 155 { 156 return Status; 157 } 158 159 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 160 161 if (SecurityInformation & OWNER_SECURITY_INFORMATION) 162 { 163 RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize); 164 SdRel->Owner = Current; 165 Current += SidSize; 166 } 167 168 if (SecurityInformation & GROUP_SECURITY_INFORMATION) 169 { 170 RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize); 171 SdRel->Group = Current; 172 Current += SidSize; 173 } 174 175 if (SecurityInformation & DACL_SECURITY_INFORMATION) 176 { 177 PACL Dacl = (PACL)((PUCHAR)SdRel + Current); 178 SdRel->Control |= SE_DACL_PRESENT; 179 180 Status = RtlCreateAcl(Dacl, 181 sizeof(ACL) + sizeof(ACE) + SidSize, 182 ACL_REVISION); 183 if (!NT_SUCCESS(Status)) 184 return Status; 185 186 Status = RtlAddAccessAllowedAce(Dacl, 187 ACL_REVISION, 188 GENERIC_ALL, 189 SeWorldSid); 190 if (!NT_SUCCESS(Status)) 191 return Status; 192 193 SdRel->Dacl = Current; 194 } 195 196 if (SecurityInformation & SACL_SECURITY_INFORMATION) 197 { 198 /* FIXME - SdRel->Control |= SE_SACL_PRESENT; */ 199 } 200 201 return STATUS_SUCCESS; 202 } 203 204 205 NTSTATUS 206 NTAPI 207 SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 208 IN KPROCESSOR_MODE AccessMode, 209 IN POOL_TYPE PoolType, 210 IN BOOLEAN CaptureIfKernel, 211 OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, 212 OUT PBOOLEAN Present) 213 { 214 PSECURITY_QUALITY_OF_SERVICE CapturedQos; 215 NTSTATUS Status = STATUS_SUCCESS; 216 217 PAGED_CODE(); 218 219 ASSERT(CapturedSecurityQualityOfService); 220 ASSERT(Present); 221 222 if (ObjectAttributes != NULL) 223 { 224 if (AccessMode != KernelMode) 225 { 226 SECURITY_QUALITY_OF_SERVICE SafeQos; 227 228 _SEH2_TRY 229 { 230 ProbeForRead(ObjectAttributes, 231 sizeof(OBJECT_ATTRIBUTES), 232 sizeof(ULONG)); 233 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) 234 { 235 if (ObjectAttributes->SecurityQualityOfService != NULL) 236 { 237 ProbeForRead(ObjectAttributes->SecurityQualityOfService, 238 sizeof(SECURITY_QUALITY_OF_SERVICE), 239 sizeof(ULONG)); 240 241 if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length == 242 sizeof(SECURITY_QUALITY_OF_SERVICE)) 243 { 244 /* 245 * Don't allocate memory here because ExAllocate should bugcheck 246 * the system if it's buggy, SEH would catch that! So make a local 247 * copy of the qos structure. 248 */ 249 RtlCopyMemory(&SafeQos, 250 ObjectAttributes->SecurityQualityOfService, 251 sizeof(SECURITY_QUALITY_OF_SERVICE)); 252 *Present = TRUE; 253 } 254 else 255 { 256 Status = STATUS_INVALID_PARAMETER; 257 } 258 } 259 else 260 { 261 *CapturedSecurityQualityOfService = NULL; 262 *Present = FALSE; 263 } 264 } 265 else 266 { 267 Status = STATUS_INVALID_PARAMETER; 268 } 269 } 270 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 271 { 272 Status = _SEH2_GetExceptionCode(); 273 } 274 _SEH2_END; 275 276 if (NT_SUCCESS(Status)) 277 { 278 if (*Present) 279 { 280 CapturedQos = ExAllocatePoolWithTag(PoolType, 281 sizeof(SECURITY_QUALITY_OF_SERVICE), 282 TAG_QOS); 283 if (CapturedQos != NULL) 284 { 285 RtlCopyMemory(CapturedQos, 286 &SafeQos, 287 sizeof(SECURITY_QUALITY_OF_SERVICE)); 288 *CapturedSecurityQualityOfService = CapturedQos; 289 } 290 else 291 { 292 Status = STATUS_INSUFFICIENT_RESOURCES; 293 } 294 } 295 else 296 { 297 *CapturedSecurityQualityOfService = NULL; 298 } 299 } 300 } 301 else 302 { 303 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) 304 { 305 if (CaptureIfKernel) 306 { 307 if (ObjectAttributes->SecurityQualityOfService != NULL) 308 { 309 if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length == 310 sizeof(SECURITY_QUALITY_OF_SERVICE)) 311 { 312 CapturedQos = ExAllocatePoolWithTag(PoolType, 313 sizeof(SECURITY_QUALITY_OF_SERVICE), 314 TAG_QOS); 315 if (CapturedQos != NULL) 316 { 317 RtlCopyMemory(CapturedQos, 318 ObjectAttributes->SecurityQualityOfService, 319 sizeof(SECURITY_QUALITY_OF_SERVICE)); 320 *CapturedSecurityQualityOfService = CapturedQos; 321 *Present = TRUE; 322 } 323 else 324 { 325 Status = STATUS_INSUFFICIENT_RESOURCES; 326 } 327 } 328 else 329 { 330 Status = STATUS_INVALID_PARAMETER; 331 } 332 } 333 else 334 { 335 *CapturedSecurityQualityOfService = NULL; 336 *Present = FALSE; 337 } 338 } 339 else 340 { 341 *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService; 342 *Present = (ObjectAttributes->SecurityQualityOfService != NULL); 343 } 344 } 345 else 346 { 347 Status = STATUS_INVALID_PARAMETER; 348 } 349 } 350 } 351 else 352 { 353 *CapturedSecurityQualityOfService = NULL; 354 *Present = FALSE; 355 } 356 357 return Status; 358 } 359 360 361 VOID 362 NTAPI 363 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL, 364 IN KPROCESSOR_MODE AccessMode, 365 IN BOOLEAN CaptureIfKernel) 366 { 367 PAGED_CODE(); 368 369 if (CapturedSecurityQualityOfService != NULL && 370 (AccessMode != KernelMode || CaptureIfKernel)) 371 { 372 ExFreePoolWithTag(CapturedSecurityQualityOfService, TAG_QOS); 373 } 374 } 375 376 /* PUBLIC FUNCTIONS ***********************************************************/ 377 378 static 379 ULONG 380 DetermineSIDSize( 381 PISID Sid, 382 PULONG OutSAC, 383 KPROCESSOR_MODE ProcessorMode) 384 { 385 ULONG Size; 386 387 if (!Sid) 388 { 389 *OutSAC = 0; 390 return 0; 391 } 392 393 if (ProcessorMode != KernelMode) 394 { 395 /* Securely access the buffers! */ 396 *OutSAC = ProbeForReadUchar(&Sid->SubAuthorityCount); 397 Size = RtlLengthRequiredSid(*OutSAC); 398 ProbeForRead(Sid, Size, sizeof(ULONG)); 399 } 400 else 401 { 402 *OutSAC = Sid->SubAuthorityCount; 403 Size = RtlLengthRequiredSid(*OutSAC); 404 } 405 406 return Size; 407 } 408 409 static 410 ULONG 411 DetermineACLSize( 412 PACL Acl, 413 KPROCESSOR_MODE ProcessorMode) 414 { 415 ULONG Size; 416 417 if (!Acl) return 0; 418 419 if (ProcessorMode == KernelMode) return Acl->AclSize; 420 421 /* Probe the buffers! */ 422 Size = ProbeForReadUshort(&Acl->AclSize); 423 ProbeForRead(Acl, Size, sizeof(ULONG)); 424 425 return Size; 426 } 427 428 NTSTATUS 429 NTAPI 430 SeCaptureSecurityDescriptor( 431 IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor, 432 IN KPROCESSOR_MODE CurrentMode, 433 IN POOL_TYPE PoolType, 434 IN BOOLEAN CaptureIfKernel, 435 OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor) 436 { 437 PISECURITY_DESCRIPTOR OriginalDescriptor = _OriginalSecurityDescriptor; 438 SECURITY_DESCRIPTOR DescriptorCopy; 439 PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor; 440 ULONG OwnerSAC = 0, GroupSAC = 0; 441 ULONG OwnerSize = 0, GroupSize = 0; 442 ULONG SaclSize = 0, DaclSize = 0; 443 ULONG DescriptorSize = 0; 444 ULONG Offset; 445 446 if (!OriginalDescriptor) 447 { 448 /* Nothing to do... */ 449 *CapturedSecurityDescriptor = NULL; 450 return STATUS_SUCCESS; 451 } 452 453 /* Quick path */ 454 if (CurrentMode == KernelMode && !CaptureIfKernel) 455 { 456 /* Check descriptor version */ 457 if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) 458 { 459 return STATUS_UNKNOWN_REVISION; 460 } 461 462 *CapturedSecurityDescriptor = _OriginalSecurityDescriptor; 463 return STATUS_SUCCESS; 464 } 465 466 _SEH2_TRY 467 { 468 if (CurrentMode != KernelMode) 469 { 470 ProbeForRead(OriginalDescriptor, 471 sizeof(SECURITY_DESCRIPTOR_RELATIVE), 472 sizeof(ULONG)); 473 } 474 475 /* Check the descriptor version */ 476 if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) 477 { 478 _SEH2_YIELD(return STATUS_UNKNOWN_REVISION); 479 } 480 481 if (CurrentMode != KernelMode) 482 { 483 /* Get the size of the descriptor */ 484 DescriptorSize = (OriginalDescriptor->Control & SE_SELF_RELATIVE) ? 485 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR); 486 487 /* Probe the entire security descriptor structure. The SIDs 488 * and ACLs will be probed and copied later though */ 489 ProbeForRead(OriginalDescriptor, DescriptorSize, sizeof(ULONG)); 490 } 491 492 /* Now capture all fields and convert to an absolute descriptor */ 493 DescriptorCopy.Revision = OriginalDescriptor->Revision; 494 DescriptorCopy.Sbz1 = OriginalDescriptor->Sbz1; 495 DescriptorCopy.Control = OriginalDescriptor->Control & ~SE_SELF_RELATIVE; 496 DescriptorCopy.Owner = SepGetOwnerFromDescriptor(OriginalDescriptor); 497 DescriptorCopy.Group = SepGetGroupFromDescriptor(OriginalDescriptor); 498 DescriptorCopy.Sacl = SepGetSaclFromDescriptor(OriginalDescriptor); 499 DescriptorCopy.Dacl = SepGetDaclFromDescriptor(OriginalDescriptor); 500 DescriptorSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 501 502 /* Determine owner and group sizes */ 503 OwnerSize = DetermineSIDSize(DescriptorCopy.Owner, &OwnerSAC, CurrentMode); 504 DescriptorSize += ROUND_UP(OwnerSize, sizeof(ULONG)); 505 GroupSize = DetermineSIDSize(DescriptorCopy.Group, &GroupSAC, CurrentMode); 506 DescriptorSize += ROUND_UP(GroupSize, sizeof(ULONG)); 507 508 /* Determine the size of the ACLs */ 509 if (DescriptorCopy.Control & SE_SACL_PRESENT) 510 { 511 /* Get the size and probe if user mode */ 512 SaclSize = DetermineACLSize(DescriptorCopy.Sacl, CurrentMode); 513 DescriptorSize += ROUND_UP(SaclSize, sizeof(ULONG)); 514 } 515 516 if (DescriptorCopy.Control & SE_DACL_PRESENT) 517 { 518 /* Get the size and probe if user mode */ 519 DaclSize = DetermineACLSize(DescriptorCopy.Dacl, CurrentMode); 520 DescriptorSize += ROUND_UP(DaclSize, sizeof(ULONG)); 521 } 522 } 523 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 524 { 525 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 526 } 527 _SEH2_END; 528 529 /* 530 * Allocate enough memory to store a complete copy of a self-relative 531 * security descriptor 532 */ 533 NewDescriptor = ExAllocatePoolWithTag(PoolType, 534 DescriptorSize, 535 TAG_SD); 536 if (!NewDescriptor) return STATUS_INSUFFICIENT_RESOURCES; 537 538 RtlZeroMemory(NewDescriptor, DescriptorSize); 539 NewDescriptor->Revision = DescriptorCopy.Revision; 540 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1; 541 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE; 542 543 _SEH2_TRY 544 { 545 /* 546 * Setup the offsets and copy the SIDs and ACLs to the new 547 * self-relative security descriptor. Probing the pointers is not 548 * neccessary anymore as we did that when collecting the sizes! 549 * Make sure to validate the SIDs and ACLs *again* as they could have 550 * been modified in the meanwhile! 551 */ 552 Offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 553 554 if (DescriptorCopy.Owner) 555 { 556 if (!RtlValidSid(DescriptorCopy.Owner)) RtlRaiseStatus(STATUS_INVALID_SID); 557 NewDescriptor->Owner = Offset; 558 RtlCopyMemory((PUCHAR)NewDescriptor + Offset, 559 DescriptorCopy.Owner, 560 OwnerSize); 561 Offset += ROUND_UP(OwnerSize, sizeof(ULONG)); 562 } 563 564 if (DescriptorCopy.Group) 565 { 566 if (!RtlValidSid(DescriptorCopy.Group)) RtlRaiseStatus(STATUS_INVALID_SID); 567 NewDescriptor->Group = Offset; 568 RtlCopyMemory((PUCHAR)NewDescriptor + Offset, 569 DescriptorCopy.Group, 570 GroupSize); 571 Offset += ROUND_UP(GroupSize, sizeof(ULONG)); 572 } 573 574 if (DescriptorCopy.Sacl) 575 { 576 if (!RtlValidAcl(DescriptorCopy.Sacl)) RtlRaiseStatus(STATUS_INVALID_ACL); 577 NewDescriptor->Sacl = Offset; 578 RtlCopyMemory((PUCHAR)NewDescriptor + Offset, 579 DescriptorCopy.Sacl, 580 SaclSize); 581 Offset += ROUND_UP(SaclSize, sizeof(ULONG)); 582 } 583 584 if (DescriptorCopy.Dacl) 585 { 586 if (!RtlValidAcl(DescriptorCopy.Dacl)) RtlRaiseStatus(STATUS_INVALID_ACL); 587 NewDescriptor->Dacl = Offset; 588 RtlCopyMemory((PUCHAR)NewDescriptor + Offset, 589 DescriptorCopy.Dacl, 590 DaclSize); 591 Offset += ROUND_UP(DaclSize, sizeof(ULONG)); 592 } 593 594 /* Make sure the size was correct */ 595 ASSERT(Offset == DescriptorSize); 596 } 597 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 598 { 599 /* We failed to copy the data to the new descriptor */ 600 ExFreePoolWithTag(NewDescriptor, TAG_SD); 601 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 602 } 603 _SEH2_END; 604 605 /* 606 * We're finally done! 607 * Copy the pointer to the captured descriptor to to the caller. 608 */ 609 *CapturedSecurityDescriptor = NewDescriptor; 610 return STATUS_SUCCESS; 611 } 612 613 /* 614 * @implemented 615 */ 616 _IRQL_requires_max_(PASSIVE_LEVEL) 617 NTSTATUS 618 NTAPI 619 SeQuerySecurityDescriptorInfo( 620 _In_ PSECURITY_INFORMATION SecurityInformation, 621 _Out_writes_bytes_(*Length) PSECURITY_DESCRIPTOR SecurityDescriptor, 622 _Inout_ PULONG Length, 623 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor) 624 { 625 PISECURITY_DESCRIPTOR ObjectSd; 626 PISECURITY_DESCRIPTOR_RELATIVE RelSD; 627 PSID Owner = NULL; 628 PSID Group = NULL; 629 PACL Dacl = NULL; 630 PACL Sacl = NULL; 631 ULONG OwnerLength = 0; 632 ULONG GroupLength = 0; 633 ULONG DaclLength = 0; 634 ULONG SaclLength = 0; 635 SECURITY_DESCRIPTOR_CONTROL Control = 0; 636 ULONG_PTR Current; 637 ULONG SdLength; 638 639 PAGED_CODE(); 640 641 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor; 642 643 if (*ObjectsSecurityDescriptor == NULL) 644 { 645 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) 646 { 647 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 648 return STATUS_BUFFER_TOO_SMALL; 649 } 650 651 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 652 RtlCreateSecurityDescriptorRelative(RelSD, 653 SECURITY_DESCRIPTOR_REVISION); 654 return STATUS_SUCCESS; 655 } 656 657 ObjectSd = *ObjectsSecurityDescriptor; 658 659 /* Calculate the required security descriptor length */ 660 Control = SE_SELF_RELATIVE; 661 if (*SecurityInformation & OWNER_SECURITY_INFORMATION) 662 { 663 Owner = SepGetOwnerFromDescriptor(ObjectSd); 664 if (Owner != NULL) 665 { 666 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4); 667 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED); 668 } 669 } 670 671 if (*SecurityInformation & GROUP_SECURITY_INFORMATION) 672 { 673 Group = SepGetGroupFromDescriptor(ObjectSd); 674 if (Group != NULL) 675 { 676 GroupLength = ROUND_UP(RtlLengthSid(Group), 4); 677 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED); 678 } 679 } 680 681 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) && 682 (ObjectSd->Control & SE_DACL_PRESENT)) 683 { 684 Dacl = SepGetDaclFromDescriptor(ObjectSd); 685 if (Dacl != NULL) 686 { 687 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4); 688 } 689 690 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT)); 691 } 692 693 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) && 694 (ObjectSd->Control & SE_SACL_PRESENT)) 695 { 696 Sacl = SepGetSaclFromDescriptor(ObjectSd); 697 if (Sacl != NULL) 698 { 699 SaclLength = ROUND_UP(Sacl->AclSize, 4); 700 } 701 702 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT)); 703 } 704 705 SdLength = OwnerLength + GroupLength + DaclLength + 706 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE); 707 if (*Length < SdLength) 708 { 709 *Length = SdLength; 710 return STATUS_BUFFER_TOO_SMALL; 711 } 712 713 /* Build the new security descrtiptor */ 714 RtlCreateSecurityDescriptorRelative(RelSD, 715 SECURITY_DESCRIPTOR_REVISION); 716 RelSD->Control = Control; 717 718 Current = (ULONG_PTR)(RelSD + 1); 719 720 if (OwnerLength != 0) 721 { 722 RtlCopyMemory((PVOID)Current, 723 Owner, 724 OwnerLength); 725 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); 726 Current += OwnerLength; 727 } 728 729 if (GroupLength != 0) 730 { 731 RtlCopyMemory((PVOID)Current, 732 Group, 733 GroupLength); 734 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); 735 Current += GroupLength; 736 } 737 738 if (DaclLength != 0) 739 { 740 RtlCopyMemory((PVOID)Current, 741 Dacl, 742 DaclLength); 743 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); 744 Current += DaclLength; 745 } 746 747 if (SaclLength != 0) 748 { 749 RtlCopyMemory((PVOID)Current, 750 Sacl, 751 SaclLength); 752 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); 753 Current += SaclLength; 754 } 755 756 *Length = SdLength; 757 758 return STATUS_SUCCESS; 759 } 760 761 /* 762 * @implemented 763 */ 764 NTSTATUS 765 NTAPI 766 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor, 767 IN KPROCESSOR_MODE CurrentMode, 768 IN BOOLEAN CaptureIfKernelMode) 769 { 770 PAGED_CODE(); 771 772 /* 773 * WARNING! You need to call this function with the same value for CurrentMode 774 * and CaptureIfKernelMode that you previously passed to 775 * SeCaptureSecurityDescriptor() in order to avoid memory leaks! 776 */ 777 if (CapturedSecurityDescriptor != NULL && 778 (CurrentMode != KernelMode || 779 (CurrentMode == KernelMode && CaptureIfKernelMode))) 780 { 781 /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */ 782 ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD); 783 } 784 785 return STATUS_SUCCESS; 786 } 787 788 /* 789 * @implemented 790 */ 791 _IRQL_requires_max_(PASSIVE_LEVEL) 792 NTSTATUS 793 NTAPI 794 SeSetSecurityDescriptorInfo( 795 _In_opt_ PVOID Object, 796 _In_ PSECURITY_INFORMATION SecurityInformation, 797 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 798 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 799 _In_ POOL_TYPE PoolType, 800 _In_ PGENERIC_MAPPING GenericMapping) 801 { 802 PAGED_CODE(); 803 804 return SeSetSecurityDescriptorInfoEx(Object, 805 SecurityInformation, 806 SecurityDescriptor, 807 ObjectsSecurityDescriptor, 808 0, 809 PoolType, 810 GenericMapping); 811 } 812 813 /* 814 * @implemented 815 */ 816 _IRQL_requires_max_(PASSIVE_LEVEL) 817 NTSTATUS 818 NTAPI 819 SeSetSecurityDescriptorInfoEx( 820 _In_opt_ PVOID Object, 821 _In_ PSECURITY_INFORMATION _SecurityInformation, 822 _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor, 823 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 824 _In_ ULONG AutoInheritFlags, 825 _In_ POOL_TYPE PoolType, 826 _In_ PGENERIC_MAPPING GenericMapping) 827 { 828 PISECURITY_DESCRIPTOR_RELATIVE ObjectSd; 829 PISECURITY_DESCRIPTOR_RELATIVE NewSd; 830 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor; 831 PSID Owner; 832 PSID Group; 833 PACL Dacl; 834 PACL Sacl; 835 ULONG OwnerLength; 836 ULONG GroupLength; 837 ULONG DaclLength; 838 ULONG SaclLength; 839 SECURITY_DESCRIPTOR_CONTROL Control = 0; 840 ULONG Current; 841 SECURITY_INFORMATION SecurityInformation; 842 843 PAGED_CODE(); 844 845 ObjectSd = *ObjectsSecurityDescriptor; 846 847 /* The object does not have a security descriptor. */ 848 if (!ObjectSd) 849 return STATUS_NO_SECURITY_ON_OBJECT; 850 851 ASSERT(ObjectSd->Control & SE_SELF_RELATIVE); 852 853 SecurityInformation = *_SecurityInformation; 854 855 /* Get owner and owner size */ 856 if (SecurityInformation & OWNER_SECURITY_INFORMATION) 857 { 858 Owner = SepGetOwnerFromDescriptor(SecurityDescriptor); 859 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED); 860 } 861 else 862 { 863 Owner = SepGetOwnerFromDescriptor(ObjectSd); 864 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED); 865 } 866 OwnerLength = Owner ? RtlLengthSid(Owner) : 0; 867 ASSERT(OwnerLength % sizeof(ULONG) == 0); 868 869 /* Get group and group size */ 870 if (SecurityInformation & GROUP_SECURITY_INFORMATION) 871 { 872 Group = SepGetGroupFromDescriptor(SecurityDescriptor); 873 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED); 874 } 875 else 876 { 877 Group = SepGetGroupFromDescriptor(ObjectSd); 878 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED); 879 } 880 GroupLength = Group ? RtlLengthSid(Group) : 0; 881 ASSERT(GroupLength % sizeof(ULONG) == 0); 882 883 /* Get DACL and DACL size */ 884 if (SecurityInformation & DACL_SECURITY_INFORMATION) 885 { 886 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor); 887 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT)); 888 } 889 else 890 { 891 Dacl = SepGetDaclFromDescriptor(ObjectSd); 892 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT)); 893 } 894 DaclLength = Dacl ? ROUND_UP((ULONG)Dacl->AclSize, 4) : 0; 895 896 /* Get SACL and SACL size */ 897 if (SecurityInformation & SACL_SECURITY_INFORMATION) 898 { 899 Sacl = SepGetSaclFromDescriptor(SecurityDescriptor); 900 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT)); 901 } 902 else 903 { 904 Sacl = SepGetSaclFromDescriptor(ObjectSd); 905 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT)); 906 } 907 SaclLength = Sacl ? ROUND_UP((ULONG)Sacl->AclSize, 4) : 0; 908 909 NewSd = ExAllocatePoolWithTag(NonPagedPool, 910 sizeof(SECURITY_DESCRIPTOR_RELATIVE) + 911 OwnerLength + GroupLength + 912 DaclLength + SaclLength, 913 TAG_SD); 914 if (NewSd == NULL) 915 { 916 return STATUS_INSUFFICIENT_RESOURCES; 917 } 918 919 RtlCreateSecurityDescriptorRelative(NewSd, SECURITY_DESCRIPTOR_REVISION1); 920 921 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 922 923 if (OwnerLength != 0) 924 { 925 RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength); 926 NewSd->Owner = Current; 927 Current += OwnerLength; 928 } 929 930 if (GroupLength != 0) 931 { 932 RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength); 933 NewSd->Group = Current; 934 Current += GroupLength; 935 } 936 937 if (DaclLength != 0) 938 { 939 RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength); 940 NewSd->Dacl = Current; 941 Current += DaclLength; 942 } 943 944 if (SaclLength != 0) 945 { 946 RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength); 947 NewSd->Sacl = Current; 948 Current += SaclLength; 949 } 950 951 *ObjectsSecurityDescriptor = NewSd; 952 return STATUS_SUCCESS; 953 } 954 955 956 /* 957 * @implemented 958 */ 959 BOOLEAN NTAPI 960 SeValidSecurityDescriptor(IN ULONG Length, 961 IN PSECURITY_DESCRIPTOR _SecurityDescriptor) 962 { 963 ULONG SdLength; 964 PISID Sid; 965 PACL Acl; 966 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor; 967 968 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH) 969 { 970 DPRINT1("Invalid Security Descriptor revision\n"); 971 return FALSE; 972 } 973 974 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) 975 { 976 DPRINT1("Invalid Security Descriptor revision\n"); 977 return FALSE; 978 } 979 980 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE)) 981 { 982 DPRINT1("No self-relative Security Descriptor\n"); 983 return FALSE; 984 } 985 986 SdLength = sizeof(SECURITY_DESCRIPTOR); 987 988 /* Check Owner SID */ 989 if (!SecurityDescriptor->Owner) 990 { 991 DPRINT1("No Owner SID\n"); 992 return FALSE; 993 } 994 995 if (SecurityDescriptor->Owner % sizeof(ULONG)) 996 { 997 DPRINT1("Invalid Owner SID alignment\n"); 998 return FALSE; 999 } 1000 1001 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner); 1002 if (Sid->Revision != SID_REVISION) 1003 { 1004 DPRINT1("Invalid Owner SID revision\n"); 1005 return FALSE; 1006 } 1007 1008 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG)); 1009 if (Length < SdLength) 1010 { 1011 DPRINT1("Invalid Owner SID size\n"); 1012 return FALSE; 1013 } 1014 1015 /* Check Group SID */ 1016 if (SecurityDescriptor->Group) 1017 { 1018 if (SecurityDescriptor->Group % sizeof(ULONG)) 1019 { 1020 DPRINT1("Invalid Group SID alignment\n"); 1021 return FALSE; 1022 } 1023 1024 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group); 1025 if (Sid->Revision != SID_REVISION) 1026 { 1027 DPRINT1("Invalid Group SID revision\n"); 1028 return FALSE; 1029 } 1030 1031 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG)); 1032 if (Length < SdLength) 1033 { 1034 DPRINT1("Invalid Group SID size\n"); 1035 return FALSE; 1036 } 1037 } 1038 1039 /* Check DACL */ 1040 if (SecurityDescriptor->Dacl) 1041 { 1042 if (SecurityDescriptor->Dacl % sizeof(ULONG)) 1043 { 1044 DPRINT1("Invalid DACL alignment\n"); 1045 return FALSE; 1046 } 1047 1048 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl); 1049 if ((Acl->AclRevision < MIN_ACL_REVISION) || 1050 (Acl->AclRevision > MAX_ACL_REVISION)) 1051 { 1052 DPRINT1("Invalid DACL revision\n"); 1053 return FALSE; 1054 } 1055 1056 SdLength += Acl->AclSize; 1057 if (Length < SdLength) 1058 { 1059 DPRINT1("Invalid DACL size\n"); 1060 return FALSE; 1061 } 1062 } 1063 1064 /* Check SACL */ 1065 if (SecurityDescriptor->Sacl) 1066 { 1067 if (SecurityDescriptor->Sacl % sizeof(ULONG)) 1068 { 1069 DPRINT1("Invalid SACL alignment\n"); 1070 return FALSE; 1071 } 1072 1073 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl); 1074 if ((Acl->AclRevision < MIN_ACL_REVISION) || 1075 (Acl->AclRevision > MAX_ACL_REVISION)) 1076 { 1077 DPRINT1("Invalid SACL revision\n"); 1078 return FALSE; 1079 } 1080 1081 SdLength += Acl->AclSize; 1082 if (Length < SdLength) 1083 { 1084 DPRINT1("Invalid SACL size\n"); 1085 return FALSE; 1086 } 1087 } 1088 1089 return TRUE; 1090 } 1091 1092 /* 1093 * @implemented 1094 */ 1095 _IRQL_requires_max_(PASSIVE_LEVEL) 1096 NTSTATUS 1097 NTAPI 1098 SeDeassignSecurity( 1099 _Inout_ PSECURITY_DESCRIPTOR *SecurityDescriptor) 1100 { 1101 PAGED_CODE(); 1102 1103 if (*SecurityDescriptor != NULL) 1104 { 1105 ExFreePoolWithTag(*SecurityDescriptor, TAG_SD); 1106 *SecurityDescriptor = NULL; 1107 } 1108 1109 return STATUS_SUCCESS; 1110 } 1111 1112 /* 1113 * @implemented 1114 */ 1115 _IRQL_requires_max_(PASSIVE_LEVEL) 1116 NTSTATUS 1117 NTAPI 1118 SeAssignSecurityEx( 1119 _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor, 1120 _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor, 1121 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, 1122 _In_opt_ GUID *ObjectType, 1123 _In_ BOOLEAN IsDirectoryObject, 1124 _In_ ULONG AutoInheritFlags, 1125 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 1126 _In_ PGENERIC_MAPPING GenericMapping, 1127 _In_ POOL_TYPE PoolType) 1128 { 1129 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor; 1130 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor; 1131 PISECURITY_DESCRIPTOR_RELATIVE Descriptor; 1132 PTOKEN Token; 1133 ULONG OwnerLength; 1134 ULONG GroupLength; 1135 ULONG DaclLength; 1136 ULONG SaclLength; 1137 ULONG Length; 1138 SECURITY_DESCRIPTOR_CONTROL Control = 0; 1139 ULONG Current; 1140 PSID Owner = NULL; 1141 PSID Group = NULL; 1142 PACL ExplicitAcl; 1143 BOOLEAN ExplicitPresent; 1144 BOOLEAN ExplicitDefaulted; 1145 PACL ParentAcl; 1146 PACL Dacl = NULL; 1147 PACL Sacl = NULL; 1148 BOOLEAN DaclIsInherited; 1149 BOOLEAN SaclIsInherited; 1150 BOOLEAN DaclPresent; 1151 BOOLEAN SaclPresent; 1152 NTSTATUS Status; 1153 1154 DBG_UNREFERENCED_PARAMETER(ObjectType); 1155 DBG_UNREFERENCED_PARAMETER(AutoInheritFlags); 1156 UNREFERENCED_PARAMETER(PoolType); 1157 1158 PAGED_CODE(); 1159 1160 *NewDescriptor = NULL; 1161 1162 if (!ARGUMENT_PRESENT(SubjectContext)) 1163 { 1164 return STATUS_NO_TOKEN; 1165 } 1166 1167 /* Lock subject context */ 1168 SeLockSubjectContext(SubjectContext); 1169 1170 if (SubjectContext->ClientToken != NULL) 1171 { 1172 Token = SubjectContext->ClientToken; 1173 } 1174 else 1175 { 1176 Token = SubjectContext->PrimaryToken; 1177 } 1178 1179 /* Inherit the Owner SID */ 1180 if (ExplicitDescriptor != NULL) 1181 { 1182 DPRINT("Use explicit owner sid!\n"); 1183 Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor); 1184 } 1185 if (!Owner) 1186 { 1187 if (AutoInheritFlags & 0x20 /* FIXME: SEF_DEFAULT_OWNER_FROM_PARENT */) 1188 { 1189 DPRINT("Use parent owner sid!\n"); 1190 if (!ARGUMENT_PRESENT(ParentDescriptor)) 1191 { 1192 SeUnlockSubjectContext(SubjectContext); 1193 return STATUS_INVALID_OWNER; 1194 } 1195 1196 Owner = SepGetOwnerFromDescriptor(ParentDescriptor); 1197 if (!Owner) 1198 { 1199 SeUnlockSubjectContext(SubjectContext); 1200 return STATUS_INVALID_OWNER; 1201 } 1202 } 1203 else 1204 { 1205 DPRINT("Use token owner sid!\n"); 1206 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid; 1207 } 1208 } 1209 OwnerLength = RtlLengthSid(Owner); 1210 ASSERT(OwnerLength % sizeof(ULONG) == 0); 1211 1212 /* Inherit the Group SID */ 1213 if (ExplicitDescriptor != NULL) 1214 { 1215 Group = SepGetGroupFromDescriptor(ExplicitDescriptor); 1216 } 1217 if (!Group) 1218 { 1219 if (AutoInheritFlags & 0x40 /* FIXME: SEF_DEFAULT_GROUP_FROM_PARENT */) 1220 { 1221 DPRINT("Use parent group sid!\n"); 1222 if (!ARGUMENT_PRESENT(ParentDescriptor)) 1223 { 1224 SeUnlockSubjectContext(SubjectContext); 1225 return STATUS_INVALID_PRIMARY_GROUP; 1226 } 1227 1228 Group = SepGetGroupFromDescriptor(ParentDescriptor); 1229 if (!Group) 1230 { 1231 SeUnlockSubjectContext(SubjectContext); 1232 return STATUS_INVALID_PRIMARY_GROUP; 1233 } 1234 } 1235 else 1236 { 1237 DPRINT("Use token group sid!\n"); 1238 Group = Token->PrimaryGroup; 1239 } 1240 } 1241 if (!Group) 1242 { 1243 SeUnlockSubjectContext(SubjectContext); 1244 return STATUS_INVALID_PRIMARY_GROUP; 1245 } 1246 GroupLength = RtlLengthSid(Group); 1247 ASSERT(GroupLength % sizeof(ULONG) == 0); 1248 1249 /* Inherit the DACL */ 1250 DaclLength = 0; 1251 ExplicitAcl = NULL; 1252 ExplicitPresent = FALSE; 1253 ExplicitDefaulted = FALSE; 1254 if (ExplicitDescriptor != NULL && 1255 (ExplicitDescriptor->Control & SE_DACL_PRESENT)) 1256 { 1257 ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor); 1258 ExplicitPresent = TRUE; 1259 if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED) 1260 ExplicitDefaulted = TRUE; 1261 } 1262 ParentAcl = NULL; 1263 if (ParentDescriptor != NULL && 1264 (ParentDescriptor->Control & SE_DACL_PRESENT)) 1265 { 1266 ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor); 1267 } 1268 Dacl = SepSelectAcl(ExplicitAcl, 1269 ExplicitPresent, 1270 ExplicitDefaulted, 1271 ParentAcl, 1272 Token->DefaultDacl, 1273 &DaclLength, 1274 Owner, 1275 Group, 1276 &DaclPresent, 1277 &DaclIsInherited, 1278 IsDirectoryObject, 1279 GenericMapping); 1280 if (DaclPresent) 1281 Control |= SE_DACL_PRESENT; 1282 ASSERT(DaclLength % sizeof(ULONG) == 0); 1283 1284 /* Inherit the SACL */ 1285 SaclLength = 0; 1286 ExplicitAcl = NULL; 1287 ExplicitPresent = FALSE; 1288 ExplicitDefaulted = FALSE; 1289 if (ExplicitDescriptor != NULL && 1290 (ExplicitDescriptor->Control & SE_SACL_PRESENT)) 1291 { 1292 ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor); 1293 ExplicitPresent = TRUE; 1294 if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED) 1295 ExplicitDefaulted = TRUE; 1296 } 1297 ParentAcl = NULL; 1298 if (ParentDescriptor != NULL && 1299 (ParentDescriptor->Control & SE_SACL_PRESENT)) 1300 { 1301 ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor); 1302 } 1303 Sacl = SepSelectAcl(ExplicitAcl, 1304 ExplicitPresent, 1305 ExplicitDefaulted, 1306 ParentAcl, 1307 NULL, 1308 &SaclLength, 1309 Owner, 1310 Group, 1311 &SaclPresent, 1312 &SaclIsInherited, 1313 IsDirectoryObject, 1314 GenericMapping); 1315 if (SaclPresent) 1316 Control |= SE_SACL_PRESENT; 1317 ASSERT(SaclLength % sizeof(ULONG) == 0); 1318 1319 /* Allocate and initialize the new security descriptor */ 1320 Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + 1321 OwnerLength + GroupLength + DaclLength + SaclLength; 1322 1323 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n", 1324 sizeof(SECURITY_DESCRIPTOR), 1325 OwnerLength, 1326 GroupLength, 1327 DaclLength, 1328 SaclLength); 1329 1330 Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD); 1331 if (Descriptor == NULL) 1332 { 1333 DPRINT1("ExAlloctePool() failed\n"); 1334 SeUnlockSubjectContext(SubjectContext); 1335 return STATUS_INSUFFICIENT_RESOURCES; 1336 } 1337 1338 RtlZeroMemory(Descriptor, Length); 1339 RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION); 1340 1341 Descriptor->Control = Control | SE_SELF_RELATIVE; 1342 1343 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 1344 1345 if (SaclLength != 0) 1346 { 1347 Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current), 1348 &SaclLength, 1349 Sacl, 1350 Owner, 1351 Group, 1352 SaclIsInherited, 1353 IsDirectoryObject, 1354 GenericMapping); 1355 ASSERT(Status == STATUS_SUCCESS); 1356 Descriptor->Sacl = Current; 1357 Current += SaclLength; 1358 } 1359 1360 if (DaclLength != 0) 1361 { 1362 Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current), 1363 &DaclLength, 1364 Dacl, 1365 Owner, 1366 Group, 1367 DaclIsInherited, 1368 IsDirectoryObject, 1369 GenericMapping); 1370 ASSERT(Status == STATUS_SUCCESS); 1371 Descriptor->Dacl = Current; 1372 Current += DaclLength; 1373 } 1374 1375 if (OwnerLength != 0) 1376 { 1377 RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength); 1378 Descriptor->Owner = Current; 1379 Current += OwnerLength; 1380 DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner); 1381 } 1382 else 1383 { 1384 DPRINT("Owner of %p is zero length\n", Descriptor); 1385 } 1386 1387 if (GroupLength != 0) 1388 { 1389 RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength); 1390 Descriptor->Group = Current; 1391 } 1392 1393 /* Unlock subject context */ 1394 SeUnlockSubjectContext(SubjectContext); 1395 1396 *NewDescriptor = Descriptor; 1397 1398 DPRINT("Descriptor %p\n", Descriptor); 1399 ASSERT(RtlLengthSecurityDescriptor(Descriptor)); 1400 1401 return STATUS_SUCCESS; 1402 } 1403 1404 /* 1405 * @implemented 1406 */ 1407 _IRQL_requires_max_(PASSIVE_LEVEL) 1408 NTSTATUS 1409 NTAPI 1410 SeAssignSecurity( 1411 _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor, 1412 _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor, 1413 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, 1414 _In_ BOOLEAN IsDirectoryObject, 1415 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 1416 _In_ PGENERIC_MAPPING GenericMapping, 1417 _In_ POOL_TYPE PoolType) 1418 { 1419 PAGED_CODE(); 1420 1421 return SeAssignSecurityEx(ParentDescriptor, 1422 ExplicitDescriptor, 1423 NewDescriptor, 1424 NULL, 1425 IsDirectoryObject, 1426 0, 1427 SubjectContext, 1428 GenericMapping, 1429 PoolType); 1430 } 1431 1432 /* 1433 * @implemented 1434 */ 1435 _IRQL_requires_max_(PASSIVE_LEVEL) 1436 NTSTATUS 1437 NTAPI 1438 SeComputeQuotaInformationSize( 1439 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 1440 _Out_ PULONG QuotaInfoSize) 1441 { 1442 PSID Group; 1443 PACL Dacl; 1444 1445 PAGED_CODE(); 1446 1447 *QuotaInfoSize = 0; 1448 1449 /* Validate security descriptor revision */ 1450 if (((PISECURITY_DESCRIPTOR)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION1) 1451 { 1452 return STATUS_UNKNOWN_REVISION; 1453 } 1454 1455 /* Get group and DACL, if any */ 1456 Group = SepGetGroupFromDescriptor(SecurityDescriptor); 1457 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor); 1458 1459 /* Return SID length if any */ 1460 if (Group != NULL) 1461 { 1462 *QuotaInfoSize = ALIGN_UP_BY(RtlLengthSid(Group), sizeof(ULONG)); 1463 } 1464 1465 /* Return DACL if any */ 1466 if (Dacl != NULL) 1467 { 1468 *QuotaInfoSize += ALIGN_UP_BY(Dacl->AclSize, sizeof(ULONG)); 1469 } 1470 1471 return STATUS_SUCCESS; 1472 } 1473 1474 /* EOF */ 1475