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