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