1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * PURPOSE: Security descriptor functions 5 * FILE: lib/rtl/sd.c 6 * PROGRAMER: David Welch <welch@cwcom.net> 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include <rtl.h> 12 #include "../../ntoskrnl/include/internal/se.h" 13 #define NDEBUG 14 #include <debug.h> 15 16 /* PRIVATE FUNCTIONS **********************************************************/ 17 18 BOOLEAN 19 NTAPI 20 RtlpValidateSDOffsetAndSize(IN ULONG Offset, 21 IN ULONG Length, 22 IN ULONG MinLength, 23 OUT PULONG MaxLength) 24 { 25 /* Assume failure */ 26 *MaxLength = 0; 27 28 /* Reject out of bounds lengths */ 29 if (Offset < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) return FALSE; 30 if (Offset >= Length) return FALSE; 31 32 /* Reject insufficient lengths */ 33 if ((Length - Offset) < MinLength) return FALSE; 34 35 /* Reject unaligned offsets */ 36 if (ALIGN_DOWN(Offset, ULONG) != Offset) return FALSE; 37 38 /* Return length that is safe to read */ 39 *MaxLength = Length - Offset; 40 return TRUE; 41 } 42 43 VOID 44 NTAPI 45 RtlpQuerySecurityDescriptor(IN PISECURITY_DESCRIPTOR SecurityDescriptor, 46 OUT PSID *Owner, 47 OUT PULONG OwnerSize, 48 OUT PSID *PrimaryGroup, 49 OUT PULONG PrimaryGroupSize, 50 OUT PACL *Dacl, 51 OUT PULONG DaclSize, 52 OUT PACL *Sacl, 53 OUT PULONG SaclSize) 54 { 55 PAGED_CODE_RTL(); 56 57 /* Get the owner */ 58 *Owner = SepGetOwnerFromDescriptor(SecurityDescriptor); 59 if (*Owner) 60 { 61 /* There's an owner, so align the size */ 62 *OwnerSize = ROUND_UP(RtlLengthSid(*Owner), sizeof(ULONG)); 63 } 64 else 65 { 66 /* No owner, no size */ 67 *OwnerSize = 0; 68 } 69 70 /* Get the group */ 71 *PrimaryGroup = SepGetGroupFromDescriptor(SecurityDescriptor); 72 if (*PrimaryGroup) 73 { 74 /* There's a group, so align the size */ 75 *PrimaryGroupSize = ROUND_UP(RtlLengthSid(*PrimaryGroup), sizeof(ULONG)); 76 } 77 else 78 { 79 /* No group, no size */ 80 *PrimaryGroupSize = 0; 81 } 82 83 /* Get the DACL */ 84 *Dacl = SepGetDaclFromDescriptor(SecurityDescriptor); 85 if (*Dacl) 86 { 87 /* There's a DACL, align the size */ 88 *DaclSize = ROUND_UP((*Dacl)->AclSize, sizeof(ULONG)); 89 } 90 else 91 { 92 /* No DACL, no size */ 93 *DaclSize = 0; 94 } 95 96 /* Get the SACL */ 97 *Sacl = SepGetSaclFromDescriptor(SecurityDescriptor); 98 if (*Sacl) 99 { 100 /* There's a SACL, align the size */ 101 *SaclSize = ROUND_UP((*Sacl)->AclSize, sizeof(ULONG)); 102 } 103 else 104 { 105 /* No SACL, no size */ 106 *SaclSize = 0; 107 } 108 } 109 110 /* PUBLIC FUNCTIONS ***********************************************************/ 111 112 /* 113 * @implemented 114 */ 115 NTSTATUS 116 NTAPI 117 RtlCreateSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 118 IN ULONG Revision) 119 { 120 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 121 PAGED_CODE_RTL(); 122 123 /* Fail on invalid revisions */ 124 if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 125 126 /* Setup an empty SD */ 127 RtlZeroMemory(Sd, sizeof(*Sd)); 128 Sd->Revision = SECURITY_DESCRIPTOR_REVISION; 129 130 /* All good */ 131 return STATUS_SUCCESS; 132 } 133 134 /* 135 * @implemented 136 */ 137 NTSTATUS 138 NTAPI 139 RtlCreateSecurityDescriptorRelative(IN PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, 140 IN ULONG Revision) 141 { 142 PAGED_CODE_RTL(); 143 144 /* Fail on invalid revisions */ 145 if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 146 147 /* Setup an empty SD */ 148 RtlZeroMemory(SecurityDescriptor, sizeof(*SecurityDescriptor)); 149 SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION; 150 SecurityDescriptor->Control = SE_SELF_RELATIVE; 151 152 /* All good */ 153 return STATUS_SUCCESS; 154 } 155 156 /* 157 * @implemented 158 */ 159 ULONG 160 NTAPI 161 RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) 162 { 163 PISECURITY_DESCRIPTOR Sd; 164 PSID Owner, Group; 165 PACL Sacl, Dacl; 166 ULONG Length; 167 PAGED_CODE_RTL(); 168 169 /* Start with the initial length of the SD itself */ 170 Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 171 if (Sd->Control & SE_SELF_RELATIVE) 172 { 173 Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 174 } 175 else 176 { 177 Length = sizeof(SECURITY_DESCRIPTOR); 178 } 179 180 /* Add the length of the individual subcomponents */ 181 Owner = SepGetOwnerFromDescriptor(Sd); 182 if (Owner) Length += ROUND_UP(RtlLengthSid(Owner), sizeof(ULONG)); 183 Group = SepGetGroupFromDescriptor(Sd); 184 if (Group) Length += ROUND_UP(RtlLengthSid(Group), sizeof(ULONG)); 185 Dacl = SepGetDaclFromDescriptor(Sd); 186 if (Dacl) Length += ROUND_UP(Dacl->AclSize, sizeof(ULONG)); 187 Sacl = SepGetSaclFromDescriptor(Sd); 188 if (Sacl) Length += ROUND_UP(Sacl->AclSize, sizeof(ULONG)); 189 190 /* Return the final length */ 191 return Length; 192 } 193 194 /* 195 * @implemented 196 */ 197 NTSTATUS 198 NTAPI 199 RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 200 OUT PBOOLEAN DaclPresent, 201 OUT PACL* Dacl, 202 OUT PBOOLEAN DaclDefaulted) 203 { 204 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 205 PAGED_CODE_RTL(); 206 207 /* Fail on invalid revisions */ 208 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 209 210 /* Is there a DACL? */ 211 *DaclPresent = (Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT; 212 if (*DaclPresent) 213 { 214 /* Yes, return it, and check if defaulted */ 215 *Dacl = SepGetDaclFromDescriptor(Sd); 216 *DaclDefaulted = (Sd->Control & SE_DACL_DEFAULTED) == SE_DACL_DEFAULTED; 217 } 218 219 /* All good */ 220 return STATUS_SUCCESS; 221 } 222 223 /* 224 * @implemented 225 */ 226 NTSTATUS 227 NTAPI 228 RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 229 OUT PBOOLEAN SaclPresent, 230 OUT PACL* Sacl, 231 OUT PBOOLEAN SaclDefaulted) 232 { 233 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 234 PAGED_CODE_RTL(); 235 236 /* Fail on invalid revisions */ 237 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 238 239 /* Is there a SACL? */ 240 *SaclPresent = (Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT; 241 if (*SaclPresent) 242 { 243 /* Yes, return it, and check if defaulted */ 244 *Sacl = SepGetSaclFromDescriptor(Sd); 245 *SaclDefaulted = (Sd->Control & SE_SACL_DEFAULTED) == SE_SACL_DEFAULTED; 246 } 247 248 /* All good */ 249 return STATUS_SUCCESS; 250 } 251 252 /* 253 * @implemented 254 */ 255 NTSTATUS 256 NTAPI 257 RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 258 OUT PSID* Owner, 259 OUT PBOOLEAN OwnerDefaulted) 260 { 261 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 262 PAGED_CODE_RTL(); 263 264 /* Fail on invalid revision */ 265 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 266 267 /* Get the owner and if defaulted */ 268 *Owner = SepGetOwnerFromDescriptor(Sd); 269 *OwnerDefaulted = (Sd->Control & SE_OWNER_DEFAULTED) == SE_OWNER_DEFAULTED; 270 271 /* All good */ 272 return STATUS_SUCCESS; 273 } 274 275 /* 276 * @implemented 277 */ 278 NTSTATUS 279 NTAPI 280 RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 281 OUT PSID* Group, 282 OUT PBOOLEAN GroupDefaulted) 283 { 284 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 285 PAGED_CODE_RTL(); 286 287 /* Fail on invalid revision */ 288 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 289 290 /* Get the group and if defaulted */ 291 *Group = SepGetGroupFromDescriptor(Sd); 292 *GroupDefaulted = (Sd->Control & SE_GROUP_DEFAULTED) == SE_GROUP_DEFAULTED; 293 294 /* All good */ 295 return STATUS_SUCCESS; 296 } 297 298 /* 299 * @implemented 300 */ 301 NTSTATUS 302 NTAPI 303 RtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 304 IN BOOLEAN DaclPresent, 305 IN PACL Dacl, 306 IN BOOLEAN DaclDefaulted) 307 { 308 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 309 PAGED_CODE_RTL(); 310 311 /* Fail on invalid revision */ 312 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 313 314 /* Fail on relative descriptors */ 315 if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR; 316 317 /* Is there a DACL? */ 318 if (!DaclPresent) 319 { 320 /* Caller is destroying the DACL, unset the flag and we're done */ 321 Sd->Control = Sd->Control & ~SE_DACL_PRESENT; 322 return STATUS_SUCCESS; 323 } 324 325 /* Caller is setting a new DACL, set the pointer and flag */ 326 Sd->Dacl = Dacl; 327 Sd->Control |= SE_DACL_PRESENT; 328 329 /* Set if defaulted */ 330 Sd->Control &= ~SE_DACL_DEFAULTED; 331 if (DaclDefaulted) Sd->Control |= SE_DACL_DEFAULTED; 332 333 /* All good */ 334 return STATUS_SUCCESS; 335 } 336 337 /* 338 * @implemented 339 */ 340 NTSTATUS 341 NTAPI 342 RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 343 IN BOOLEAN SaclPresent, 344 IN PACL Sacl, 345 IN BOOLEAN SaclDefaulted) 346 { 347 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 348 PAGED_CODE_RTL(); 349 350 /* Fail on invalid revision */ 351 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 352 353 /* Fail on relative descriptors */ 354 if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR; 355 356 /* Is there a SACL? */ 357 if (!SaclPresent) 358 { 359 /* Caller is clearing the SACL, unset the flag and we're done */ 360 Sd->Control = Sd->Control & ~SE_SACL_PRESENT; 361 return STATUS_SUCCESS; 362 } 363 364 /* Caller is setting a new SACL, set it and the flag */ 365 Sd->Sacl = Sacl; 366 Sd->Control |= SE_SACL_PRESENT; 367 368 /* Set if defaulted */ 369 Sd->Control &= ~SE_SACL_DEFAULTED; 370 if (SaclDefaulted) Sd->Control |= SE_SACL_DEFAULTED; 371 372 /* All good */ 373 return STATUS_SUCCESS; 374 } 375 376 /* 377 * @implemented 378 */ 379 NTSTATUS 380 NTAPI 381 RtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 382 IN PSID Owner, 383 IN BOOLEAN OwnerDefaulted) 384 { 385 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 386 PAGED_CODE_RTL(); 387 388 /* Fail on invalid revision */ 389 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 390 391 /* Fail on relative descriptors */ 392 if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR; 393 394 /* Owner being set or cleared */ 395 Sd->Owner = Owner; 396 397 /* Set if defaulted */ 398 Sd->Control &= ~SE_OWNER_DEFAULTED; 399 if (OwnerDefaulted) Sd->Control |= SE_OWNER_DEFAULTED; 400 401 /* All good */ 402 return STATUS_SUCCESS; 403 } 404 405 /* 406 * @implemented 407 */ 408 NTSTATUS 409 NTAPI 410 RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 411 IN PSID Group, 412 IN BOOLEAN GroupDefaulted) 413 { 414 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 415 PAGED_CODE_RTL(); 416 417 /* Fail on invalid revision */ 418 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 419 420 /* Fail on relative descriptors */ 421 if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR; 422 423 /* Group being set or cleared */ 424 Sd->Group = Group; 425 426 /* Set if defaulted */ 427 Sd->Control &= ~SE_GROUP_DEFAULTED; 428 if (GroupDefaulted) Sd->Control |= SE_GROUP_DEFAULTED; 429 430 /* All good */ 431 return STATUS_SUCCESS; 432 } 433 434 /* 435 * @implemented 436 */ 437 NTSTATUS 438 NTAPI 439 RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 440 OUT PSECURITY_DESCRIPTOR_CONTROL Control, 441 OUT PULONG Revision) 442 { 443 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 444 PAGED_CODE_RTL(); 445 446 /* Read current revision, even if invalid */ 447 *Revision = Sd->Revision; 448 449 /* Fail on invalid revision */ 450 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 451 452 /* Read current control */ 453 *Control = Sd->Control; 454 455 /* All good */ 456 return STATUS_SUCCESS; 457 } 458 459 /* 460 * @implemented 461 */ 462 NTSTATUS 463 NTAPI 464 RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 465 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, 466 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet) 467 { 468 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 469 470 /* Check for invalid bits */ 471 if ((ControlBitsOfInterest & ~(SE_DACL_UNTRUSTED | 472 SE_SERVER_SECURITY | 473 SE_DACL_AUTO_INHERIT_REQ | 474 SE_SACL_AUTO_INHERIT_REQ | 475 SE_DACL_AUTO_INHERITED | 476 SE_SACL_AUTO_INHERITED | 477 SE_DACL_PROTECTED | 478 SE_SACL_PROTECTED)) || 479 (ControlBitsToSet & ~ControlBitsOfInterest)) 480 { 481 /* Fail */ 482 return STATUS_INVALID_PARAMETER; 483 } 484 485 /* Zero the 'bits of interest' */ 486 Sd->Control &= ~ControlBitsOfInterest; 487 488 /* Set the 'bits to set' */ 489 Sd->Control |= (ControlBitsToSet & ControlBitsOfInterest); 490 491 /* All good */ 492 return STATUS_SUCCESS; 493 } 494 495 /* 496 * @implemented 497 */ 498 BOOLEAN 499 NTAPI 500 RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 501 OUT PUCHAR RMControl) 502 { 503 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 504 PAGED_CODE_RTL(); 505 506 /* Check if there's no valid RM control */ 507 if (!(Sd->Control & SE_RM_CONTROL_VALID)) 508 { 509 /* Fail and return nothing */ 510 *RMControl = 0; 511 return FALSE; 512 } 513 514 /* Return it, ironically the member is "should be zero" */ 515 *RMControl = Sd->Sbz1; 516 return TRUE; 517 } 518 519 /* 520 * @implemented 521 */ 522 VOID 523 NTAPI 524 RtlSetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 525 IN PUCHAR RMControl) 526 { 527 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 528 PAGED_CODE_RTL(); 529 530 /* RM Control is being cleared or set */ 531 if (!RMControl) 532 { 533 /* Clear it */ 534 Sd->Control &= ~SE_RM_CONTROL_VALID; 535 Sd->Sbz1 = 0; 536 } 537 else 538 { 539 /* Set it */ 540 Sd->Control |= SE_RM_CONTROL_VALID; 541 Sd->Sbz1 = *RMControl; 542 } 543 } 544 545 /* 546 * @implemented 547 */ 548 NTSTATUS 549 NTAPI 550 RtlSetAttributesSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 551 IN SECURITY_DESCRIPTOR_CONTROL Control, 552 OUT PULONG Revision) 553 { 554 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 555 PAGED_CODE_RTL(); 556 557 /* Always return revision, even if invalid */ 558 *Revision = Sd->Revision; 559 560 /* Fail on invalid revision */ 561 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; 562 563 /* Mask out flags which are not attributes */ 564 Control &= SE_DACL_UNTRUSTED | 565 SE_SERVER_SECURITY | 566 SE_DACL_AUTO_INHERIT_REQ | 567 SE_SACL_AUTO_INHERIT_REQ | 568 SE_DACL_AUTO_INHERITED | 569 SE_SACL_AUTO_INHERITED | 570 SE_DACL_PROTECTED | 571 SE_SACL_PROTECTED; 572 573 /* Call the newer API */ 574 return RtlSetControlSecurityDescriptor(SecurityDescriptor, Control, Control); 575 } 576 577 /* 578 * @implemented 579 */ 580 NTSTATUS 581 NTAPI 582 RtlCopySecurityDescriptor(IN PSECURITY_DESCRIPTOR pSourceSecurityDescriptor, 583 OUT PSECURITY_DESCRIPTOR *pDestinationSecurityDescriptor) 584 { 585 PSID Owner, Group; 586 PACL Dacl, Sacl; 587 DWORD OwnerLength, GroupLength, DaclLength, SaclLength, TotalLength; 588 PISECURITY_DESCRIPTOR Sd = pSourceSecurityDescriptor; 589 590 /* Get all the components */ 591 RtlpQuerySecurityDescriptor(Sd, 592 &Owner, 593 &OwnerLength, 594 &Group, 595 &GroupLength, 596 &Dacl, 597 &DaclLength, 598 &Sacl, 599 &SaclLength); 600 601 /* Add up their lengths */ 602 TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + 603 OwnerLength + 604 GroupLength + 605 DaclLength + 606 SaclLength; 607 608 /* Allocate a copy */ 609 *pDestinationSecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(), 610 0, 611 TotalLength); 612 if (*pDestinationSecurityDescriptor == NULL) return STATUS_NO_MEMORY; 613 614 /* Copy the old in the new */ 615 RtlCopyMemory(*pDestinationSecurityDescriptor, Sd, TotalLength); 616 617 /* All good */ 618 return STATUS_SUCCESS; 619 } 620 621 /* 622 * @implemented 623 */ 624 NTSTATUS 625 NTAPI 626 RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, 627 IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, 628 IN PULONG BufferLength) 629 { 630 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor; 631 PAGED_CODE_RTL(); 632 633 /* Can't already be relative */ 634 if (Sd->Control & SE_SELF_RELATIVE) return STATUS_BAD_DESCRIPTOR_FORMAT; 635 636 /* Call the other API */ 637 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor, 638 SelfRelativeSecurityDescriptor, 639 BufferLength); 640 } 641 642 /* 643 * @implemented 644 */ 645 NTSTATUS 646 NTAPI 647 RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSD, 648 OUT PSECURITY_DESCRIPTOR SelfRelativeSD, 649 IN OUT PULONG BufferLength) 650 { 651 PSID Owner, Group; 652 PACL Sacl, Dacl; 653 ULONG OwnerLength, GroupLength, SaclLength, DaclLength, TotalLength; 654 ULONG_PTR Current; 655 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSD; 656 PISECURITY_DESCRIPTOR_RELATIVE RelSd = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD; 657 PAGED_CODE_RTL(); 658 659 /* Query all components */ 660 RtlpQuerySecurityDescriptor(Sd, 661 &Owner, 662 &OwnerLength, 663 &Group, 664 &GroupLength, 665 &Dacl, 666 &DaclLength, 667 &Sacl, 668 &SaclLength); 669 670 /* Calculate final length */ 671 TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + 672 OwnerLength + 673 GroupLength + 674 SaclLength + 675 DaclLength; 676 677 /* Is there enough space? */ 678 if (*BufferLength < TotalLength) 679 { 680 /* Nope, return how much is needed */ 681 *BufferLength = TotalLength; 682 return STATUS_BUFFER_TOO_SMALL; 683 } 684 685 /* Start fresh */ 686 RtlZeroMemory(RelSd, TotalLength); 687 688 /* Copy the header fields */ 689 RtlCopyMemory(RelSd, 690 Sd, 691 FIELD_OFFSET(SECURITY_DESCRIPTOR_RELATIVE, Owner)); 692 693 /* Set the current copy pointer */ 694 Current = (ULONG_PTR)(RelSd + 1); 695 696 /* Is there a SACL? */ 697 if (SaclLength) 698 { 699 /* Copy it */ 700 RtlCopyMemory((PVOID)Current, Sacl, SaclLength); 701 RelSd->Sacl = (ULONG_PTR)Current - (ULONG_PTR)RelSd; 702 Current += SaclLength; 703 } 704 705 /* Is there a DACL? */ 706 if (DaclLength) 707 { 708 /* Copy it */ 709 RtlCopyMemory((PVOID)Current, Dacl, DaclLength); 710 RelSd->Dacl = (ULONG_PTR)Current - (ULONG_PTR)RelSd; 711 Current += DaclLength; 712 } 713 714 /* Is there an owner? */ 715 if (OwnerLength) 716 { 717 /* Copy it */ 718 RtlCopyMemory((PVOID)Current, Owner, OwnerLength); 719 RelSd->Owner = (ULONG_PTR)Current - (ULONG_PTR)RelSd; 720 Current += OwnerLength; 721 } 722 723 /* Is there a group? */ 724 if (GroupLength) 725 { 726 /* Copy it */ 727 RtlCopyMemory((PVOID)Current, Group, GroupLength); 728 RelSd->Group = (ULONG_PTR)Current - (ULONG_PTR)RelSd; 729 } 730 731 /* Mark it as relative */ 732 RelSd->Control |= SE_SELF_RELATIVE; 733 734 /* All good */ 735 return STATUS_SUCCESS; 736 } 737 738 /* 739 * @implemented 740 */ 741 NTSTATUS 742 NTAPI 743 RtlSelfRelativeToAbsoluteSD(IN PSECURITY_DESCRIPTOR SelfRelativeSD, 744 OUT PSECURITY_DESCRIPTOR AbsoluteSD, 745 IN PULONG AbsoluteSDSize, 746 IN PACL Dacl, 747 IN PULONG DaclSize, 748 IN PACL Sacl, 749 IN PULONG SaclSize, 750 IN PSID Owner, 751 IN PULONG OwnerSize, 752 IN PSID PrimaryGroup, 753 IN PULONG PrimaryGroupSize) 754 { 755 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSD; 756 PISECURITY_DESCRIPTOR RelSd = (PISECURITY_DESCRIPTOR)SelfRelativeSD; 757 ULONG OwnerLength, GroupLength, DaclLength, SaclLength; 758 PSID pOwner, pGroup; 759 PACL pDacl, pSacl; 760 PAGED_CODE_RTL(); 761 762 /* Must be relative, otherwiise fail */ 763 if (!(RelSd->Control & SE_SELF_RELATIVE)) return STATUS_BAD_DESCRIPTOR_FORMAT; 764 765 /* Get all the components */ 766 RtlpQuerySecurityDescriptor(RelSd, 767 &pOwner, 768 &OwnerLength, 769 &pGroup, 770 &GroupLength, 771 &pDacl, 772 &DaclLength, 773 &pSacl, 774 &SaclLength); 775 776 /* Fail if there's not enough space */ 777 if (!(Sd) || 778 (sizeof(SECURITY_DESCRIPTOR) > *AbsoluteSDSize) || 779 (OwnerLength > *OwnerSize) || 780 (GroupLength > *PrimaryGroupSize) || 781 (DaclLength > *DaclSize) || 782 (SaclLength > *SaclSize)) 783 { 784 /* Return how much space is needed for each components */ 785 *AbsoluteSDSize = sizeof(SECURITY_DESCRIPTOR); 786 *OwnerSize = OwnerLength; 787 *PrimaryGroupSize = GroupLength; 788 *DaclSize = DaclLength; 789 *SaclSize = SaclLength; 790 return STATUS_BUFFER_TOO_SMALL; 791 } 792 793 /* Copy the header fields */ 794 RtlMoveMemory(Sd, RelSd, sizeof(SECURITY_DESCRIPTOR_RELATIVE)); 795 796 /* Wipe out the pointers and the relative flag */ 797 Sd->Owner = NULL; 798 Sd->Group = NULL; 799 Sd->Sacl = NULL; 800 Sd->Dacl = NULL; 801 Sd->Control &= ~SE_SELF_RELATIVE; 802 803 /* Is there an owner? */ 804 if (pOwner) 805 { 806 /* Copy it */ 807 RtlMoveMemory(Owner, pOwner, RtlLengthSid(pOwner)); 808 Sd->Owner = Owner; 809 } 810 811 /* Is there a group? */ 812 if (pGroup) 813 { 814 /* Copy it */ 815 RtlMoveMemory(PrimaryGroup, pGroup, RtlLengthSid(pGroup)); 816 Sd->Group = PrimaryGroup; 817 } 818 819 /* Is there a DACL? */ 820 if (pDacl) 821 { 822 /* Copy it */ 823 RtlMoveMemory(Dacl, pDacl, pDacl->AclSize); 824 Sd->Dacl = Dacl; 825 } 826 827 /* Is there a SACL? */ 828 if (pSacl) 829 { 830 /* Copy it */ 831 RtlMoveMemory(Sacl, pSacl, pSacl->AclSize); 832 Sd->Sacl = Sacl; 833 } 834 835 /* All good */ 836 return STATUS_SUCCESS; 837 } 838 839 /* 840 * @implemented 841 */ 842 NTSTATUS 843 NTAPI 844 RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD, 845 OUT PULONG BufferSize) 846 { 847 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SelfRelativeSD; 848 PISECURITY_DESCRIPTOR_RELATIVE RelSd = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD; 849 PVOID DataStart, DataEnd; 850 LONG MoveDelta; 851 ULONG DataSize, OwnerLength, GroupLength, DaclLength, SaclLength; 852 PSID pOwner, pGroup; 853 PACL pDacl, pSacl; 854 PAGED_CODE_RTL(); 855 856 /* Need input */ 857 if (!RelSd) return STATUS_INVALID_PARAMETER_1; 858 859 /* Need to know how much space we have */ 860 if (!BufferSize) return STATUS_INVALID_PARAMETER_2; 861 862 /* Input must be relative */ 863 if (!(RelSd->Control & SE_SELF_RELATIVE)) return STATUS_BAD_DESCRIPTOR_FORMAT; 864 865 /* Query all the component sizes */ 866 RtlpQuerySecurityDescriptor(Sd, 867 &pOwner, 868 &OwnerLength, 869 &pGroup, 870 &GroupLength, 871 &pDacl, 872 &DaclLength, 873 &pSacl, 874 &SaclLength); 875 876 /* 877 * Check if there's a difference in structure layout between relatiev and 878 * absolute descriptors. On 32-bit, there won't be, since an offset is the 879 * same size as a pointer (32-bit), but on 64-bit, the offsets remain 32-bit 880 * as they are not SIZE_T, but ULONG, while the pointers now become 64-bit 881 * and thus the structure is different */ 882 MoveDelta = sizeof(SECURITY_DESCRIPTOR) - sizeof(SECURITY_DESCRIPTOR_RELATIVE); 883 if (!MoveDelta) 884 { 885 /* So on 32-bit, simply clear the flag... */ 886 Sd->Control &= ~SE_SELF_RELATIVE; 887 888 /* Ensure we're *really* on 32-bit */ 889 ASSERT(sizeof(Sd->Owner) == sizeof(RelSd->Owner)); 890 ASSERT(sizeof(Sd->Group) == sizeof(RelSd->Group)); 891 ASSERT(sizeof(Sd->Sacl) == sizeof(RelSd->Sacl)); 892 ASSERT(sizeof(Sd->Dacl) == sizeof(RelSd->Dacl)); 893 894 /* And simply set pointers where there used to be offsets */ 895 Sd->Owner = pOwner; 896 Sd->Group = pGroup; 897 Sd->Sacl = pSacl; 898 Sd->Dacl = pDacl; 899 return STATUS_SUCCESS; 900 } 901 902 /* 903 * Calculate the start and end of the data area, we simply just move the 904 * data by the difference between the size of the relative and absolute 905 * security descriptor structure 906 */ 907 DataStart = pOwner; 908 DataEnd = (PVOID)((ULONG_PTR)pOwner + OwnerLength); 909 910 /* Is there a group? */ 911 if (pGroup) 912 { 913 /* Is the group higher than where we started? */ 914 if (((ULONG_PTR)pGroup < (ULONG_PTR)DataStart) || !DataStart) 915 { 916 /* Update the start pointer */ 917 DataStart = pGroup; 918 } 919 920 /* Is the group beyond where we ended? */ 921 if (((ULONG_PTR)pGroup + GroupLength > (ULONG_PTR)DataEnd) || !DataEnd) 922 { 923 /* Update the end pointer */ 924 DataEnd = (PVOID)((ULONG_PTR)pGroup + GroupLength); 925 } 926 } 927 928 /* Is there a DACL? */ 929 if (pDacl) 930 { 931 /* Is the DACL higher than where we started? */ 932 if (((ULONG_PTR)pDacl < (ULONG_PTR)DataStart) || !DataStart) 933 { 934 /* Update the start pointer */ 935 DataStart = pDacl; 936 } 937 938 /* Is the DACL beyond where we ended? */ 939 if (((ULONG_PTR)pDacl + DaclLength > (ULONG_PTR)DataEnd) || !DataEnd) 940 { 941 /* Update the end pointer */ 942 DataEnd = (PVOID)((ULONG_PTR)pDacl + DaclLength); 943 } 944 } 945 946 /* Is there a SACL? */ 947 if (pSacl) 948 { 949 /* Is the SACL higher than where we started? */ 950 if (((ULONG_PTR)pSacl < (ULONG_PTR)DataStart) || !DataStart) 951 { 952 /* Update the start pointer */ 953 DataStart = pSacl; 954 } 955 956 /* Is the SACL beyond where we ended? */ 957 if (((ULONG_PTR)pSacl + SaclLength > (ULONG_PTR)DataEnd) || !DataEnd) 958 { 959 /* Update the end pointer */ 960 DataEnd = (PVOID)((ULONG_PTR)pSacl + SaclLength); 961 } 962 } 963 964 /* Sanity check */ 965 ASSERT((ULONG_PTR)DataEnd >= (ULONG_PTR)DataStart); 966 967 /* Now compute the difference between relative and absolute */ 968 DataSize = (ULONG)((ULONG_PTR)DataEnd - (ULONG_PTR)DataStart); 969 970 /* Is the new buffer large enough for this difference? */ 971 if (*BufferSize < sizeof(SECURITY_DESCRIPTOR) + DataSize) 972 { 973 /* Nope, bail out */ 974 *BufferSize = sizeof(SECURITY_DESCRIPTOR) + DataSize; 975 return STATUS_BUFFER_TOO_SMALL; 976 } 977 978 /* Is there anything actually to copy? */ 979 if (DataSize) 980 { 981 /* 982 * There must be at least one SID or ACL in the security descriptor! 983 * Also the data area must be located somewhere after the end of the 984 * SECURITY_DESCRIPTOR_RELATIVE structure 985 */ 986 ASSERT(DataStart != NULL); 987 ASSERT((ULONG_PTR)DataStart >= (ULONG_PTR)(RelSd + 1)); 988 989 /* It's time to move the data */ 990 RtlMoveMemory((PVOID)(Sd + 1), 991 DataStart, 992 DataSize); 993 } 994 995 /* Is there an owner? */ 996 if (pOwner) 997 { 998 /* Set the pointer to the relative position */ 999 Sd->Owner = (PSID)((LONG_PTR)pOwner + MoveDelta); 1000 } 1001 else 1002 { 1003 /* No owner, clear the pointer */ 1004 Sd->Owner = NULL; 1005 } 1006 1007 /* Is there a group */ 1008 if (pGroup) 1009 { 1010 /* Set the pointer to the relative position */ 1011 Sd->Group = (PSID)((LONG_PTR)pGroup + MoveDelta); 1012 } 1013 else 1014 { 1015 /* No group, clear the pointer */ 1016 Sd->Group = NULL; 1017 } 1018 1019 /* Is there a SACL? */ 1020 if (pSacl) 1021 { 1022 /* Set the pointer to the relative position */ 1023 Sd->Sacl = (PACL)((LONG_PTR)pSacl + MoveDelta); 1024 } 1025 else 1026 { 1027 /* No SACL, clear the pointer */ 1028 Sd->Sacl = NULL; 1029 } 1030 1031 /* Is there a DACL? */ 1032 if (pDacl) 1033 { 1034 /* Set the pointer to the relative position */ 1035 Sd->Dacl = (PACL)((LONG_PTR)pDacl + MoveDelta); 1036 } 1037 else 1038 { 1039 /* No DACL, clear the pointer */ 1040 Sd->Dacl = NULL; 1041 } 1042 1043 /* Clear the self-relative flag */ 1044 Sd->Control &= ~SE_SELF_RELATIVE; 1045 1046 /* All good */ 1047 return STATUS_SUCCESS; 1048 } 1049 1050 /* 1051 * @implemented 1052 */ 1053 BOOLEAN 1054 NTAPI 1055 RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) 1056 { 1057 PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 1058 PSID Owner, Group; 1059 PACL Sacl, Dacl; 1060 PAGED_CODE_RTL(); 1061 1062 _SEH2_TRY 1063 { 1064 /* Fail on bad revisions */ 1065 if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) _SEH2_YIELD(return FALSE); 1066 1067 /* Owner SID must be valid if present */ 1068 Owner = SepGetOwnerFromDescriptor(Sd); 1069 if ((Owner) && (!RtlValidSid(Owner))) _SEH2_YIELD(return FALSE); 1070 1071 /* Group SID must be valid if present */ 1072 Group = SepGetGroupFromDescriptor(Sd); 1073 if ((Group) && (!RtlValidSid(Group))) _SEH2_YIELD(return FALSE); 1074 1075 /* DACL must be valid if present */ 1076 Dacl = SepGetDaclFromDescriptor(Sd); 1077 if ((Dacl) && (!RtlValidAcl(Dacl))) _SEH2_YIELD(return FALSE); 1078 1079 /* SACL must be valid if present */ 1080 Sacl = SepGetSaclFromDescriptor(Sd); 1081 if ((Sacl) && (!RtlValidAcl(Sacl))) _SEH2_YIELD(return FALSE); 1082 } 1083 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1084 { 1085 /* Access fault, bail out */ 1086 _SEH2_YIELD(return FALSE); 1087 } 1088 _SEH2_END; 1089 1090 /* All good */ 1091 return TRUE; 1092 } 1093 1094 /* 1095 * @implemented 1096 */ 1097 BOOLEAN 1098 NTAPI 1099 RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput, 1100 IN ULONG SecurityDescriptorLength, 1101 IN SECURITY_INFORMATION RequiredInformation) 1102 { 1103 PISECURITY_DESCRIPTOR_RELATIVE Sd = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptorInput; 1104 PSID Owner, Group; 1105 PACL Dacl, Sacl; 1106 ULONG Length; 1107 PAGED_CODE_RTL(); 1108 1109 /* Note that Windows allows no DACL/SACL even if RequiredInfo wants it */ 1110 1111 /* Do we have enough space, is the revision vaild, and is this SD relative? */ 1112 if ((SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) || 1113 (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) || 1114 !(Sd->Control & SE_SELF_RELATIVE)) 1115 { 1116 /* Nope, bail out */ 1117 return FALSE; 1118 } 1119 1120 /* Is there an owner? */ 1121 if (Sd->Owner) 1122 { 1123 /* Try to access it */ 1124 if (!RtlpValidateSDOffsetAndSize(Sd->Owner, 1125 SecurityDescriptorLength, 1126 sizeof(SID), 1127 &Length)) 1128 { 1129 /* It's beyond the buffer, fail */ 1130 return FALSE; 1131 } 1132 1133 /* Read the owner, check if it's valid and if the buffer contains it */ 1134 Owner = (PSID)((ULONG_PTR)Sd->Owner + (ULONG_PTR)Sd); 1135 if (!RtlValidSid(Owner) || (Length < RtlLengthSid(Owner))) return FALSE; 1136 } 1137 else if (RequiredInformation & OWNER_SECURITY_INFORMATION) 1138 { 1139 /* No owner but the caller expects one, fail */ 1140 return FALSE; 1141 } 1142 1143 /* Is there a group? */ 1144 if (Sd->Group) 1145 { 1146 /* Try to access it */ 1147 if (!RtlpValidateSDOffsetAndSize(Sd->Group, 1148 SecurityDescriptorLength, 1149 sizeof(SID), 1150 &Length)) 1151 { 1152 /* It's beyond the buffer, fail */ 1153 return FALSE; 1154 } 1155 1156 /* Read the group, check if it's valid and if the buffer contains it */ 1157 Group = (PSID)((ULONG_PTR)Sd->Group + (ULONG_PTR)Sd); 1158 if (!RtlValidSid(Group) || (Length < RtlLengthSid(Group))) return FALSE; 1159 } 1160 else if (RequiredInformation & GROUP_SECURITY_INFORMATION) 1161 { 1162 /* No group, but the caller expects one, fail */ 1163 return FALSE; 1164 } 1165 1166 /* Is there a DACL? */ 1167 if ((Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT) 1168 { 1169 /* Try to access it */ 1170 if (!RtlpValidateSDOffsetAndSize(Sd->Dacl, 1171 SecurityDescriptorLength, 1172 sizeof(ACL), 1173 &Length)) 1174 { 1175 /* It's beyond the buffer, fail */ 1176 return FALSE; 1177 } 1178 1179 /* Read the DACL, check if it's valid and if the buffer contains it */ 1180 Dacl = (PSID)((ULONG_PTR)Sd->Dacl + (ULONG_PTR)Sd); 1181 if (!(RtlValidAcl(Dacl)) || (Length < Dacl->AclSize)) return FALSE; 1182 } 1183 1184 /* Is there a SACL? */ 1185 if ((Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT) 1186 { 1187 /* Try to access it */ 1188 if (!RtlpValidateSDOffsetAndSize(Sd->Sacl, 1189 SecurityDescriptorLength, 1190 sizeof(ACL), 1191 &Length)) 1192 { 1193 /* It's beyond the buffer, fail */ 1194 return FALSE; 1195 } 1196 1197 /* Read the SACL, check if it's valid and if the buffer contains it */ 1198 Sacl = (PSID)((ULONG_PTR)Sd->Sacl + (ULONG_PTR)Sd); 1199 if (!(RtlValidAcl(Sacl)) || (Length < Sacl->AclSize)) return FALSE; 1200 } 1201 1202 /* All good */ 1203 return TRUE; 1204 } 1205 1206 /* EOF */ 1207