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