1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: lib/rtl/security.c 5 * PURPOSE: Security related functions and Security Objects 6 * PROGRAMMER: Eric Kohl 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <rtl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* PRIVATE FUNCTIONS **********************************************************/ 16 17 NTSTATUS 18 NTAPI 19 RtlpSetSecurityObject(IN PVOID Object OPTIONAL, 20 IN SECURITY_INFORMATION SecurityInformation, 21 IN PSECURITY_DESCRIPTOR ModificationDescriptor, 22 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 23 IN ULONG AutoInheritFlags, 24 IN ULONG PoolType, 25 IN PGENERIC_MAPPING GenericMapping, 26 IN HANDLE Token OPTIONAL) 27 { 28 PISECURITY_DESCRIPTOR_RELATIVE pNewSd = NULL; 29 PSID pOwnerSid = NULL; 30 PSID pGroupSid = NULL; 31 PACL pDacl = NULL; 32 PACL pSacl = NULL; 33 BOOLEAN Defaulted; 34 BOOLEAN Present; 35 ULONG ulOwnerSidSize = 0, ulGroupSidSize = 0; 36 ULONG ulDaclSize = 0, ulSaclSize = 0; 37 ULONG ulNewSdSize; 38 SECURITY_DESCRIPTOR_CONTROL Control = SE_SELF_RELATIVE; 39 PUCHAR pDest; 40 NTSTATUS Status = STATUS_SUCCESS; 41 42 DPRINT("RtlpSetSecurityObject()\n"); 43 44 /* Change the Owner SID */ 45 if (SecurityInformation & OWNER_SECURITY_INFORMATION) 46 { 47 Status = RtlGetOwnerSecurityDescriptor(ModificationDescriptor, &pOwnerSid, &Defaulted); 48 if (!NT_SUCCESS(Status)) 49 return Status; 50 } 51 else 52 { 53 Status = RtlGetOwnerSecurityDescriptor(*ObjectsSecurityDescriptor, &pOwnerSid, &Defaulted); 54 if (!NT_SUCCESS(Status)) 55 return Status; 56 } 57 58 if (pOwnerSid == NULL || !RtlValidSid(pOwnerSid)) 59 return STATUS_INVALID_OWNER; 60 61 ulOwnerSidSize = RtlLengthSid(pOwnerSid); 62 63 /* Change the Group SID */ 64 if (SecurityInformation & GROUP_SECURITY_INFORMATION) 65 { 66 Status = RtlGetGroupSecurityDescriptor(ModificationDescriptor, &pGroupSid, &Defaulted); 67 if (!NT_SUCCESS(Status)) 68 return Status; 69 } 70 else 71 { 72 Status = RtlGetGroupSecurityDescriptor(*ObjectsSecurityDescriptor, &pGroupSid, &Defaulted); 73 if (!NT_SUCCESS(Status)) 74 return Status; 75 } 76 77 if (pGroupSid == NULL || !RtlValidSid(pGroupSid)) 78 return STATUS_INVALID_PRIMARY_GROUP; 79 80 ulGroupSidSize = ROUND_UP(RtlLengthSid(pGroupSid), sizeof(ULONG)); 81 82 /* Change the DACL */ 83 if (SecurityInformation & DACL_SECURITY_INFORMATION) 84 { 85 Status = RtlGetDaclSecurityDescriptor(ModificationDescriptor, &Present, &pDacl, &Defaulted); 86 if (!NT_SUCCESS(Status)) 87 return Status; 88 89 Control |= SE_DACL_PRESENT; 90 } 91 else 92 { 93 Status = RtlGetDaclSecurityDescriptor(*ObjectsSecurityDescriptor, &Present, &pDacl, &Defaulted); 94 if (!NT_SUCCESS(Status)) 95 return Status; 96 97 if (Present) 98 Control |= SE_DACL_PRESENT; 99 100 if (Defaulted) 101 Control |= SE_DACL_DEFAULTED; 102 } 103 104 if (pDacl != NULL) 105 ulDaclSize = pDacl->AclSize; 106 107 /* Change the SACL */ 108 if (SecurityInformation & SACL_SECURITY_INFORMATION) 109 { 110 Status = RtlGetSaclSecurityDescriptor(ModificationDescriptor, &Present, &pSacl, &Defaulted); 111 if (!NT_SUCCESS(Status)) 112 return Status; 113 114 Control |= SE_SACL_PRESENT; 115 } 116 else 117 { 118 Status = RtlGetSaclSecurityDescriptor(*ObjectsSecurityDescriptor, &Present, &pSacl, &Defaulted); 119 if (!NT_SUCCESS(Status)) 120 return Status; 121 122 if (Present) 123 Control |= SE_SACL_PRESENT; 124 125 if (Defaulted) 126 Control |= SE_SACL_DEFAULTED; 127 } 128 129 if (pSacl != NULL) 130 ulSaclSize = pSacl->AclSize; 131 132 /* Calculate the size of the new security descriptor */ 133 ulNewSdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + 134 ROUND_UP(ulOwnerSidSize, sizeof(ULONG)) + 135 ROUND_UP(ulGroupSidSize, sizeof(ULONG)) + 136 ROUND_UP(ulDaclSize, sizeof(ULONG)) + 137 ROUND_UP(ulSaclSize, sizeof(ULONG)); 138 139 /* Allocate the new security descriptor */ 140 pNewSd = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulNewSdSize); 141 if (pNewSd == NULL) 142 { 143 Status = STATUS_NO_MEMORY; 144 DPRINT1("New security descriptor allocation failed (Status 0x%08lx)\n", Status); 145 goto done; 146 } 147 148 /* Initialize the new security descriptor */ 149 Status = RtlCreateSecurityDescriptorRelative(pNewSd, SECURITY_DESCRIPTOR_REVISION); 150 if (!NT_SUCCESS(Status)) 151 { 152 DPRINT1("New security descriptor creation failed (Status 0x%08lx)\n", Status); 153 goto done; 154 } 155 156 /* Set the security descriptor control flags */ 157 pNewSd->Control = Control; 158 159 pDest = (PUCHAR)((ULONG_PTR)pNewSd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); 160 161 /* Copy the SACL */ 162 if (pSacl != NULL) 163 { 164 RtlCopyMemory(pDest, pSacl, ulSaclSize); 165 pNewSd->Sacl = (ULONG_PTR)pDest - (ULONG_PTR)pNewSd; 166 pDest = pDest + ROUND_UP(ulSaclSize, sizeof(ULONG)); 167 } 168 169 /* Copy the DACL */ 170 if (pDacl != NULL) 171 { 172 RtlCopyMemory(pDest, pDacl, ulDaclSize); 173 pNewSd->Dacl = (ULONG_PTR)pDest - (ULONG_PTR)pNewSd; 174 pDest = pDest + ROUND_UP(ulDaclSize, sizeof(ULONG)); 175 } 176 177 /* Copy the Owner SID */ 178 RtlCopyMemory(pDest, pOwnerSid, ulOwnerSidSize); 179 pNewSd->Owner = (ULONG_PTR)pDest - (ULONG_PTR)pNewSd; 180 pDest = pDest + ROUND_UP(ulOwnerSidSize, sizeof(ULONG)); 181 182 /* Copy the Group SID */ 183 RtlCopyMemory(pDest, pGroupSid, ulGroupSidSize); 184 pNewSd->Group = (ULONG_PTR)pDest - (ULONG_PTR)pNewSd; 185 186 /* Free the old security descriptor */ 187 RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)*ObjectsSecurityDescriptor); 188 189 /* Return the new security descriptor */ 190 *ObjectsSecurityDescriptor = (PSECURITY_DESCRIPTOR)pNewSd; 191 192 done: 193 if (!NT_SUCCESS(Status)) 194 { 195 if (pNewSd != NULL) 196 RtlFreeHeap(RtlGetProcessHeap(), 0, pNewSd); 197 } 198 199 return Status; 200 } 201 202 NTSTATUS 203 NTAPI 204 RtlpNewSecurityObject(IN PSECURITY_DESCRIPTOR ParentDescriptor, 205 IN PSECURITY_DESCRIPTOR CreatorDescriptor, 206 OUT PSECURITY_DESCRIPTOR *NewDescriptor, 207 IN LPGUID *ObjectTypes, 208 IN ULONG GuidCount, 209 IN BOOLEAN IsDirectoryObject, 210 IN ULONG AutoInheritFlags, 211 IN HANDLE Token, 212 IN PGENERIC_MAPPING GenericMapping) 213 { 214 UNIMPLEMENTED; 215 return STATUS_NOT_IMPLEMENTED; 216 } 217 218 NTSTATUS 219 NTAPI 220 RtlpConvertToAutoInheritSecurityObject(IN PSECURITY_DESCRIPTOR ParentDescriptor, 221 IN PSECURITY_DESCRIPTOR CreatorDescriptor, 222 OUT PSECURITY_DESCRIPTOR *NewDescriptor, 223 IN LPGUID ObjectType, 224 IN BOOLEAN IsDirectoryObject, 225 IN PGENERIC_MAPPING GenericMapping) 226 { 227 UNIMPLEMENTED; 228 return STATUS_NOT_IMPLEMENTED; 229 } 230 231 /* PUBLIC FUNCTIONS ***********************************************************/ 232 233 /* 234 * @implemented 235 */ 236 NTSTATUS 237 NTAPI 238 RtlDefaultNpAcl(OUT PACL *pAcl) 239 { 240 NTSTATUS Status; 241 HANDLE TokenHandle; 242 PTOKEN_OWNER OwnerSid; 243 ULONG ReturnLength = 0; 244 ULONG AclSize; 245 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; 246 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; 247 248 /* 249 * Temporary buffer large enough to hold a maximum of two SIDs. 250 * An alternative is to call RtlAllocateAndInitializeSid many times... 251 */ 252 UCHAR SidBuffer[16]; 253 PSID Sid = (PSID)&SidBuffer; 254 255 ASSERT(RtlLengthRequiredSid(2) == 16); 256 257 /* Initialize the user ACL pointer */ 258 *pAcl = NULL; 259 260 /* 261 * Try to retrieve the SID of the current owner. For that, 262 * we first attempt to get the current thread level token. 263 */ 264 Status = NtOpenThreadToken(NtCurrentThread(), 265 TOKEN_QUERY, 266 TRUE, 267 &TokenHandle); 268 if (Status == STATUS_NO_TOKEN) 269 { 270 /* 271 * No thread level token, so use the process level token. 272 * This is the common case since the only time a thread 273 * has a token is when it is impersonating. 274 */ 275 Status = NtOpenProcessToken(NtCurrentProcess(), 276 TOKEN_QUERY, 277 &TokenHandle); 278 } 279 /* Fail if we didn't succeed in retrieving a handle to the token */ 280 if (!NT_SUCCESS(Status)) return Status; 281 282 /* 283 * Retrieve the owner SID from the token. 284 */ 285 286 /* Query the needed size... */ 287 Status = NtQueryInformationToken(TokenHandle, 288 TokenOwner, 289 NULL, 0, 290 &ReturnLength); 291 /* ... so that we must fail with STATUS_BUFFER_TOO_SMALL error */ 292 if (Status != STATUS_BUFFER_TOO_SMALL) goto Cleanup1; 293 294 /* Allocate space for the owner SID */ 295 OwnerSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ReturnLength); 296 if (OwnerSid == NULL) 297 { 298 Status = STATUS_NO_MEMORY; 299 goto Cleanup1; 300 } 301 302 /* Retrieve the owner SID; we must succeed */ 303 Status = NtQueryInformationToken(TokenHandle, 304 TokenOwner, 305 OwnerSid, 306 ReturnLength, 307 &ReturnLength); 308 if (!NT_SUCCESS(Status)) goto Cleanup2; 309 310 /* 311 * Allocate one ACL with 5 ACEs. 312 * 313 * NOTE: sizeof(ACE) == sizeof(ACCESS_ALLOWED_ACE) - sizeof(((ACCESS_ALLOWED_ACE*)NULL)->SidStart) 314 * (see kernel32/client/debugger.c line 54). 315 */ 316 AclSize = sizeof(ACL) + // Header 317 5 * sizeof(ACE /*ACCESS_ALLOWED_ACE*/) + // 5 ACEs: 318 RtlLengthRequiredSid(1) + // LocalSystem 319 RtlLengthRequiredSid(2) + // Administrators 320 RtlLengthRequiredSid(1) + // Anonymous 321 RtlLengthRequiredSid(1) + // World 322 RtlLengthSid(OwnerSid->Owner); // Owner 323 324 *pAcl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclSize); 325 if (*pAcl == NULL) 326 { 327 Status = STATUS_NO_MEMORY; 328 goto Cleanup2; 329 } 330 331 /* 332 * Build the ACL and add the five ACEs. 333 */ 334 Status = RtlCreateAcl(*pAcl, AclSize, ACL_REVISION2); 335 ASSERT(NT_SUCCESS(Status)); 336 337 /* Local System SID - Generic All */ 338 Status = RtlInitializeSid(Sid, &NtAuthority, 1); 339 ASSERT(NT_SUCCESS(Status)); 340 *RtlSubAuthoritySid(Sid, 0) = SECURITY_LOCAL_SYSTEM_RID; 341 Status = RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_ALL, Sid); 342 ASSERT(NT_SUCCESS(Status)); 343 344 /* Administrators SID - Generic All */ 345 Status = RtlInitializeSid(Sid, &NtAuthority, 2); 346 ASSERT(NT_SUCCESS(Status)); 347 *RtlSubAuthoritySid(Sid, 0) = SECURITY_BUILTIN_DOMAIN_RID; 348 *RtlSubAuthoritySid(Sid, 1) = DOMAIN_ALIAS_RID_ADMINS; 349 Status = RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_ALL, Sid); 350 ASSERT(NT_SUCCESS(Status)); 351 352 /* Owner SID - Generic All */ 353 RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_ALL, OwnerSid->Owner); 354 ASSERT(NT_SUCCESS(Status)); 355 356 /* Anonymous SID - Generic Read */ 357 Status = RtlInitializeSid(Sid, &NtAuthority, 1); 358 ASSERT(NT_SUCCESS(Status)); 359 *RtlSubAuthoritySid(Sid, 0) = SECURITY_ANONYMOUS_LOGON_RID; 360 Status = RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_READ, Sid); 361 ASSERT(NT_SUCCESS(Status)); 362 363 /* World SID - Generic Read */ 364 Status = RtlInitializeSid(Sid, &WorldAuthority, 1); 365 ASSERT(NT_SUCCESS(Status)); 366 *RtlSubAuthoritySid(Sid, 0) = SECURITY_WORLD_RID; 367 Status = RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_READ, Sid); 368 ASSERT(NT_SUCCESS(Status)); 369 370 /* If some problem happened, cleanup everything */ 371 if (!NT_SUCCESS(Status)) 372 { 373 RtlFreeHeap(RtlGetProcessHeap(), 0, *pAcl); 374 *pAcl = NULL; 375 } 376 377 Cleanup2: 378 /* Get rid of the owner SID */ 379 RtlFreeHeap(RtlGetProcessHeap(), 0, OwnerSid); 380 381 Cleanup1: 382 /* Close the token handle */ 383 NtClose(TokenHandle); 384 385 /* Done */ 386 return Status; 387 } 388 389 /* 390 * @unimplemented 391 */ 392 NTSTATUS 393 NTAPI 394 RtlCreateAndSetSD(IN PVOID AceData, 395 IN ULONG AceCount, 396 IN PSID OwnerSid OPTIONAL, 397 IN PSID GroupSid OPTIONAL, 398 OUT PSECURITY_DESCRIPTOR *NewDescriptor) 399 { 400 UNIMPLEMENTED; 401 return STATUS_NOT_IMPLEMENTED; 402 } 403 404 /* 405 * @implemented 406 */ 407 NTSTATUS 408 NTAPI 409 RtlDeleteSecurityObject(IN PSECURITY_DESCRIPTOR *ObjectDescriptor) 410 { 411 DPRINT1("RtlDeleteSecurityObject(%p)\n", ObjectDescriptor); 412 413 /* Free the object from the heap */ 414 RtlFreeHeap(RtlGetProcessHeap(), 0, *ObjectDescriptor); 415 return STATUS_SUCCESS; 416 } 417 418 /* 419 * @implemented 420 */ 421 NTSTATUS 422 NTAPI 423 RtlNewSecurityObject(IN PSECURITY_DESCRIPTOR ParentDescriptor, 424 IN PSECURITY_DESCRIPTOR CreatorDescriptor, 425 OUT PSECURITY_DESCRIPTOR *NewDescriptor, 426 IN BOOLEAN IsDirectoryObject, 427 IN HANDLE Token, 428 IN PGENERIC_MAPPING GenericMapping) 429 { 430 DPRINT1("RtlNewSecurityObject(%p)\n", ParentDescriptor); 431 432 /* Call the internal API */ 433 return RtlpNewSecurityObject(ParentDescriptor, 434 CreatorDescriptor, 435 NewDescriptor, 436 NULL, 437 0, 438 IsDirectoryObject, 439 0, 440 Token, 441 GenericMapping); 442 } 443 444 /* 445 * @implemented 446 */ 447 NTSTATUS 448 NTAPI 449 RtlNewSecurityObjectEx(IN PSECURITY_DESCRIPTOR ParentDescriptor, 450 IN PSECURITY_DESCRIPTOR CreatorDescriptor, 451 OUT PSECURITY_DESCRIPTOR *NewDescriptor, 452 IN LPGUID ObjectType, 453 IN BOOLEAN IsDirectoryObject, 454 IN ULONG AutoInheritFlags, 455 IN HANDLE Token, 456 IN PGENERIC_MAPPING GenericMapping) 457 { 458 DPRINT1("RtlNewSecurityObjectEx(%p)\n", ParentDescriptor); 459 460 /* Call the internal API */ 461 return RtlpNewSecurityObject(ParentDescriptor, 462 CreatorDescriptor, 463 NewDescriptor, 464 ObjectType ? &ObjectType : NULL, 465 ObjectType ? 1 : 0, 466 IsDirectoryObject, 467 AutoInheritFlags, 468 Token, 469 GenericMapping); 470 } 471 472 /* 473 * @implemented 474 */ 475 NTSTATUS 476 NTAPI 477 RtlNewSecurityObjectWithMultipleInheritance(IN PSECURITY_DESCRIPTOR ParentDescriptor, 478 IN PSECURITY_DESCRIPTOR CreatorDescriptor, 479 OUT PSECURITY_DESCRIPTOR *NewDescriptor, 480 IN LPGUID *ObjectTypes, 481 IN ULONG GuidCount, 482 IN BOOLEAN IsDirectoryObject, 483 IN ULONG AutoInheritFlags, 484 IN HANDLE Token, 485 IN PGENERIC_MAPPING GenericMapping) 486 { 487 DPRINT1("RtlNewSecurityObjectWithMultipleInheritance(%p)\n", ParentDescriptor); 488 489 /* Call the internal API */ 490 return RtlpNewSecurityObject(ParentDescriptor, 491 CreatorDescriptor, 492 NewDescriptor, 493 ObjectTypes, 494 GuidCount, 495 IsDirectoryObject, 496 AutoInheritFlags, 497 Token, 498 GenericMapping); 499 } 500 501 /* 502 * @implemented 503 */ 504 NTSTATUS 505 NTAPI 506 RtlNewInstanceSecurityObject(IN BOOLEAN ParentDescriptorChanged, 507 IN BOOLEAN CreatorDescriptorChanged, 508 IN PLUID OldClientTokenModifiedId, 509 OUT PLUID NewClientTokenModifiedId, 510 IN PSECURITY_DESCRIPTOR ParentDescriptor, 511 IN PSECURITY_DESCRIPTOR CreatorDescriptor, 512 OUT PSECURITY_DESCRIPTOR *NewDescriptor, 513 IN BOOLEAN IsDirectoryObject, 514 IN HANDLE Token, 515 IN PGENERIC_MAPPING GenericMapping) 516 { 517 TOKEN_STATISTICS TokenStats; 518 ULONG Size; 519 NTSTATUS Status; 520 DPRINT1("RtlNewInstanceSecurityObject(%p)\n", ParentDescriptor); 521 522 /* Query the token statistics */ 523 Status = NtQueryInformationToken(Token, 524 TokenStatistics, 525 &TokenStats, 526 sizeof(TokenStats), 527 &Size); 528 if (!NT_SUCCESS(Status)) return Status; 529 530 /* Return the LUID */ 531 *NewClientTokenModifiedId = TokenStats.ModifiedId; 532 533 /* Check if the LUID changed */ 534 if (RtlEqualLuid(NewClientTokenModifiedId, OldClientTokenModifiedId)) 535 { 536 /* Did nothing change? */ 537 if (!(ParentDescriptorChanged) && !(CreatorDescriptorChanged)) 538 { 539 /* There's no new descriptor, we're done */ 540 *NewDescriptor = NULL; 541 return STATUS_SUCCESS; 542 } 543 } 544 545 /* Call the standard API */ 546 return RtlNewSecurityObject(ParentDescriptor, 547 CreatorDescriptor, 548 NewDescriptor, 549 IsDirectoryObject, 550 Token, 551 GenericMapping); 552 } 553 554 /* 555 * @implemented 556 */ 557 NTSTATUS 558 NTAPI 559 RtlCreateUserSecurityObject(IN PVOID AceData, 560 IN ULONG AceCount, 561 IN PSID OwnerSid, 562 IN PSID GroupSid, 563 IN BOOLEAN IsDirectoryObject, 564 IN PGENERIC_MAPPING GenericMapping, 565 OUT PSECURITY_DESCRIPTOR *NewDescriptor) 566 { 567 NTSTATUS Status; 568 PSECURITY_DESCRIPTOR Sd; 569 HANDLE TokenHandle; 570 DPRINT1("RtlCreateUserSecurityObject(%p)\n", AceData); 571 572 /* Create the security descriptor based on the ACE Data */ 573 Status = RtlCreateAndSetSD(AceData, 574 AceCount, 575 OwnerSid, 576 GroupSid, 577 &Sd); 578 if (!NT_SUCCESS(Status)) return Status; 579 580 /* Open the process token */ 581 Status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &TokenHandle); 582 if (!NT_SUCCESS(Status)) goto Quickie; 583 584 /* Create the security object */ 585 Status = RtlNewSecurityObject(NULL, 586 Sd, 587 NewDescriptor, 588 IsDirectoryObject, 589 TokenHandle, 590 GenericMapping); 591 592 /* We're done, close the token handle */ 593 NtClose(TokenHandle); 594 595 Quickie: 596 /* Free the SD and return status */ 597 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); 598 return Status; 599 } 600 601 /* 602 * @implemented 603 */ 604 NTSTATUS 605 NTAPI 606 RtlNewSecurityGrantedAccess(IN ACCESS_MASK DesiredAccess, 607 OUT PPRIVILEGE_SET Privileges, 608 IN OUT PULONG Length, 609 IN HANDLE Token, 610 IN PGENERIC_MAPPING GenericMapping, 611 OUT PACCESS_MASK RemainingDesiredAccess) 612 { 613 NTSTATUS Status; 614 BOOLEAN Granted, CallerToken; 615 TOKEN_STATISTICS TokenStats; 616 ULONG Size; 617 DPRINT1("RtlNewSecurityGrantedAccess(%lx)\n", DesiredAccess); 618 619 /* Has the caller passed a token? */ 620 if (!Token) 621 { 622 /* Remember that we'll have to close the handle */ 623 CallerToken = FALSE; 624 625 /* Nope, open it */ 626 Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, TRUE, &Token); 627 if (!NT_SUCCESS(Status)) return Status; 628 } 629 else 630 { 631 /* Yep, use it */ 632 CallerToken = TRUE; 633 } 634 635 /* Get information on the token */ 636 Status = NtQueryInformationToken(Token, 637 TokenStatistics, 638 &TokenStats, 639 sizeof(TokenStats), 640 &Size); 641 ASSERT(NT_SUCCESS(Status)); 642 643 /* Windows doesn't do anything with the token statistics! */ 644 645 /* Map the access and return it back decoded */ 646 RtlMapGenericMask(&DesiredAccess, GenericMapping); 647 *RemainingDesiredAccess = DesiredAccess; 648 649 /* Check if one of the rights requested was the SACL right */ 650 if (DesiredAccess & ACCESS_SYSTEM_SECURITY) 651 { 652 /* Pretend that it's allowed FIXME: Do privilege check */ 653 DPRINT1("Missing privilege check for SE_SECURITY_PRIVILEGE"); 654 Granted = TRUE; 655 *RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY; 656 } 657 else 658 { 659 /* Nothing to grant */ 660 Granted = FALSE; 661 } 662 663 /* If the caller did not pass in a token, close the handle to ours */ 664 if (!CallerToken) NtClose(Token); 665 666 /* We need space to return only 1 privilege -- already part of the struct */ 667 Size = sizeof(PRIVILEGE_SET); 668 if (Size > *Length) 669 { 670 /* Tell the caller how much space we need and fail */ 671 *Length = Size; 672 return STATUS_BUFFER_TOO_SMALL; 673 } 674 675 /* Check if the SACL right was granted... */ 676 RtlZeroMemory(Privileges, Size); 677 if (Granted) 678 { 679 /* Yes, return it in the structure */ 680 Privileges->PrivilegeCount = 1; 681 Privileges->Privilege[0].Luid.LowPart = SE_SECURITY_PRIVILEGE; 682 Privileges->Privilege[0].Luid.HighPart = 0; 683 Privileges->Privilege[0].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS; 684 } 685 686 /* All done */ 687 return STATUS_SUCCESS; 688 } 689 690 /* 691 * @unimplemented 692 */ 693 NTSTATUS 694 NTAPI 695 RtlQuerySecurityObject(IN PSECURITY_DESCRIPTOR ObjectDescriptor, 696 IN SECURITY_INFORMATION SecurityInformation, 697 OUT PSECURITY_DESCRIPTOR ResultantDescriptor, 698 IN ULONG DescriptorLength, 699 OUT PULONG ReturnLength) 700 { 701 NTSTATUS Status; 702 SECURITY_DESCRIPTOR desc; 703 BOOLEAN defaulted, present; 704 PACL pacl; 705 PSID psid; 706 707 Status = RtlCreateSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION); 708 if (!NT_SUCCESS(Status)) return Status; 709 710 if (SecurityInformation & OWNER_SECURITY_INFORMATION) 711 { 712 Status = RtlGetOwnerSecurityDescriptor(ObjectDescriptor, &psid, &defaulted); 713 if (!NT_SUCCESS(Status)) return Status; 714 Status = RtlSetOwnerSecurityDescriptor(&desc, psid, defaulted); 715 if (!NT_SUCCESS(Status)) return Status; 716 } 717 718 if (SecurityInformation & GROUP_SECURITY_INFORMATION) 719 { 720 Status = RtlGetGroupSecurityDescriptor(ObjectDescriptor, &psid, &defaulted); 721 if (!NT_SUCCESS(Status)) return Status; 722 Status = RtlSetGroupSecurityDescriptor(&desc, psid, defaulted); 723 if (!NT_SUCCESS(Status)) return Status; 724 } 725 726 if (SecurityInformation & DACL_SECURITY_INFORMATION) 727 { 728 Status = RtlGetDaclSecurityDescriptor(ObjectDescriptor, &present, &pacl, &defaulted); 729 if (!NT_SUCCESS(Status)) return Status; 730 Status = RtlSetDaclSecurityDescriptor(&desc, present, pacl, defaulted); 731 if (!NT_SUCCESS(Status)) return Status; 732 } 733 734 if (SecurityInformation & SACL_SECURITY_INFORMATION) 735 { 736 Status = RtlGetSaclSecurityDescriptor(ObjectDescriptor, &present, &pacl, &defaulted); 737 if (!NT_SUCCESS(Status)) return Status; 738 Status = RtlSetSaclSecurityDescriptor(&desc, present, pacl, defaulted); 739 if (!NT_SUCCESS(Status)) return Status; 740 } 741 742 *ReturnLength = DescriptorLength; 743 return RtlAbsoluteToSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength); 744 } 745 746 747 /* 748 * @implemented 749 */ 750 NTSTATUS 751 NTAPI 752 RtlSetSecurityObject(IN SECURITY_INFORMATION SecurityInformation, 753 IN PSECURITY_DESCRIPTOR ModificationDescriptor, 754 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 755 IN PGENERIC_MAPPING GenericMapping, 756 IN HANDLE Token OPTIONAL) 757 { 758 /* Call the internal API */ 759 return RtlpSetSecurityObject(NULL, 760 SecurityInformation, 761 ModificationDescriptor, 762 ObjectsSecurityDescriptor, 763 0, 764 PagedPool, 765 GenericMapping, 766 Token); 767 } 768 769 /* 770 * @implemented 771 */ 772 NTSTATUS 773 NTAPI 774 RtlSetSecurityObjectEx(IN SECURITY_INFORMATION SecurityInformation, 775 IN PSECURITY_DESCRIPTOR ModificationDescriptor, 776 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 777 IN ULONG AutoInheritFlags, 778 IN PGENERIC_MAPPING GenericMapping, 779 IN HANDLE Token OPTIONAL) 780 { 781 /* Call the internal API */ 782 return RtlpSetSecurityObject(NULL, 783 SecurityInformation, 784 ModificationDescriptor, 785 ObjectsSecurityDescriptor, 786 AutoInheritFlags, 787 PagedPool, 788 GenericMapping, 789 Token); 790 791 } 792 793 /* 794 * @implemented 795 */ 796 NTSTATUS 797 NTAPI 798 RtlConvertToAutoInheritSecurityObject(IN PSECURITY_DESCRIPTOR ParentDescriptor, 799 IN PSECURITY_DESCRIPTOR CreatorDescriptor, 800 OUT PSECURITY_DESCRIPTOR *NewDescriptor, 801 IN LPGUID ObjectType, 802 IN BOOLEAN IsDirectoryObject, 803 IN PGENERIC_MAPPING GenericMapping) 804 { 805 /* Call the internal API */ 806 return RtlpConvertToAutoInheritSecurityObject(ParentDescriptor, 807 CreatorDescriptor, 808 NewDescriptor, 809 ObjectType, 810 IsDirectoryObject, 811 GenericMapping); 812 } 813 814 /* 815 * @unimplemented 816 */ 817 NTSTATUS 818 NTAPI 819 RtlRegisterSecureMemoryCacheCallback(IN PRTL_SECURE_MEMORY_CACHE_CALLBACK Callback) 820 { 821 UNIMPLEMENTED; 822 return STATUS_NOT_IMPLEMENTED; 823 } 824 825 /* 826 * @unimplemented 827 */ 828 BOOLEAN 829 NTAPI 830 RtlFlushSecureMemoryCache(IN PVOID MemoryCache, 831 IN OPTIONAL SIZE_T MemoryLength) 832 { 833 UNIMPLEMENTED; 834 return FALSE; 835 } 836