1 /* 2 * ReactOS MARTA provider 3 * Copyright (C) 2005 - 2006 ReactOS Team 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /* 20 * PROJECT: ReactOS MARTA provider 21 * FILE: lib/ntmarta/ntmarta.c 22 * PURPOSE: ReactOS MARTA provider 23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com> 24 * 25 * UPDATE HISTORY: 26 * 07/26/2005 Created 27 */ 28 29 #include "ntmarta.h" 30 31 #define NDEBUG 32 #include <debug.h> 33 34 HINSTANCE hDllInstance; 35 36 /* FIXME: Vista+ API */ 37 VOID 38 WINAPI 39 SetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, 40 OUT LPDWORD DesiredAccess) 41 { 42 *DesiredAccess = 0; 43 44 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) 45 *DesiredAccess |= WRITE_OWNER; 46 47 if (SecurityInformation & DACL_SECURITY_INFORMATION) 48 *DesiredAccess |= WRITE_DAC; 49 50 if (SecurityInformation & SACL_SECURITY_INFORMATION) 51 *DesiredAccess |= ACCESS_SYSTEM_SECURITY; 52 } 53 54 /* FIXME: Vista+ API */ 55 VOID 56 WINAPI 57 QuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, 58 OUT LPDWORD DesiredAccess) 59 { 60 *DesiredAccess = 0; 61 62 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | 63 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION)) 64 { 65 *DesiredAccess |= READ_CONTROL; 66 } 67 68 if (SecurityInformation & SACL_SECURITY_INFORMATION) 69 *DesiredAccess |= ACCESS_SYSTEM_SECURITY; 70 } 71 72 static ACCESS_MODE 73 AccpGetAceAccessMode(IN PACE_HEADER AceHeader) 74 { 75 ACCESS_MODE Mode = NOT_USED_ACCESS; 76 77 switch (AceHeader->AceType) 78 { 79 case ACCESS_ALLOWED_ACE_TYPE: 80 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 81 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 82 case ACCESS_ALLOWED_OBJECT_ACE_TYPE: 83 Mode = GRANT_ACCESS; 84 break; 85 86 case ACCESS_DENIED_ACE_TYPE: 87 case ACCESS_DENIED_CALLBACK_ACE_TYPE: 88 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 89 case ACCESS_DENIED_OBJECT_ACE_TYPE: 90 Mode = DENY_ACCESS; 91 break; 92 93 case SYSTEM_AUDIT_ACE_TYPE: 94 case SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 95 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 96 case SYSTEM_AUDIT_OBJECT_ACE_TYPE: 97 if (AceHeader->AceFlags & FAILED_ACCESS_ACE_FLAG) 98 Mode = SET_AUDIT_FAILURE; 99 else if (AceHeader->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) 100 Mode = SET_AUDIT_SUCCESS; 101 break; 102 } 103 104 return Mode; 105 } 106 107 static UINT 108 AccpGetAceStructureSize(IN PACE_HEADER AceHeader) 109 { 110 UINT Size = 0; 111 112 switch (AceHeader->AceType) 113 { 114 case ACCESS_ALLOWED_ACE_TYPE: 115 case ACCESS_DENIED_ACE_TYPE: 116 Size = FIELD_OFFSET(ACCESS_ALLOWED_ACE, 117 SidStart); 118 break; 119 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 120 case ACCESS_DENIED_CALLBACK_ACE_TYPE: 121 Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_ACE, 122 SidStart); 123 break; 124 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 125 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 126 { 127 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader; 128 Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE, 129 ObjectType); 130 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 131 Size += sizeof(Ace->ObjectType); 132 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) 133 Size += sizeof(Ace->InheritedObjectType); 134 break; 135 } 136 case ACCESS_ALLOWED_OBJECT_ACE_TYPE: 137 case ACCESS_DENIED_OBJECT_ACE_TYPE: 138 { 139 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader; 140 Size = FIELD_OFFSET(ACCESS_ALLOWED_OBJECT_ACE, 141 ObjectType); 142 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 143 Size += sizeof(Ace->ObjectType); 144 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) 145 Size += sizeof(Ace->InheritedObjectType); 146 break; 147 } 148 149 case SYSTEM_AUDIT_ACE_TYPE: 150 Size = FIELD_OFFSET(SYSTEM_AUDIT_ACE, 151 SidStart); 152 break; 153 case SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 154 Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_ACE, 155 SidStart); 156 break; 157 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 158 { 159 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader; 160 Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE, 161 ObjectType); 162 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 163 Size += sizeof(Ace->ObjectType); 164 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) 165 Size += sizeof(Ace->InheritedObjectType); 166 break; 167 } 168 case SYSTEM_AUDIT_OBJECT_ACE_TYPE: 169 { 170 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader; 171 Size = FIELD_OFFSET(SYSTEM_AUDIT_OBJECT_ACE, 172 ObjectType); 173 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 174 Size += sizeof(Ace->ObjectType); 175 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) 176 Size += sizeof(Ace->InheritedObjectType); 177 break; 178 } 179 180 case SYSTEM_MANDATORY_LABEL_ACE_TYPE: 181 Size = FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, 182 SidStart); 183 break; 184 } 185 186 return Size; 187 } 188 189 static PSID 190 AccpGetAceSid(IN PACE_HEADER AceHeader) 191 { 192 return (PSID)((ULONG_PTR)AceHeader + AccpGetAceStructureSize(AceHeader)); 193 } 194 195 static ACCESS_MASK 196 AccpGetAceAccessMask(IN PACE_HEADER AceHeader) 197 { 198 return *((PACCESS_MASK)(AceHeader + 1)); 199 } 200 201 static BOOL 202 AccpIsObjectAce(IN PACE_HEADER AceHeader) 203 { 204 BOOL Ret; 205 206 switch (AceHeader->AceType) 207 { 208 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 209 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 210 case ACCESS_ALLOWED_OBJECT_ACE_TYPE: 211 case ACCESS_DENIED_OBJECT_ACE_TYPE: 212 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 213 case SYSTEM_AUDIT_OBJECT_ACE_TYPE: 214 Ret = TRUE; 215 break; 216 217 default: 218 Ret = FALSE; 219 break; 220 } 221 222 return Ret; 223 } 224 225 static DWORD 226 AccpGetTrusteeObjects(IN PTRUSTEE_W Trustee, 227 OUT GUID *pObjectTypeGuid OPTIONAL, 228 OUT GUID *pInheritedObjectTypeGuid OPTIONAL) 229 { 230 DWORD Ret; 231 232 switch (Trustee->TrusteeForm) 233 { 234 case TRUSTEE_IS_OBJECTS_AND_NAME: 235 { 236 POBJECTS_AND_NAME_W pOan = (POBJECTS_AND_NAME_W)Trustee->ptstrName; 237 238 /* pOan->ObjectsPresent should always be 0 here because a previous 239 call to AccpGetTrusteeSid should have rejected these trustees 240 already. */ 241 ASSERT(pOan->ObjectsPresent == 0); 242 243 Ret = pOan->ObjectsPresent; 244 break; 245 } 246 247 case TRUSTEE_IS_OBJECTS_AND_SID: 248 { 249 POBJECTS_AND_SID pOas = (POBJECTS_AND_SID)Trustee->ptstrName; 250 251 if (pObjectTypeGuid != NULL && pOas->ObjectsPresent & ACE_OBJECT_TYPE_PRESENT) 252 *pObjectTypeGuid = pOas->ObjectTypeGuid; 253 254 if (pInheritedObjectTypeGuid != NULL && pOas->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) 255 *pInheritedObjectTypeGuid = pOas->InheritedObjectTypeGuid; 256 257 Ret = pOas->ObjectsPresent; 258 break; 259 } 260 261 default: 262 /* Any other trustee forms have no objects attached... */ 263 Ret = 0; 264 break; 265 } 266 267 return Ret; 268 } 269 270 static DWORD 271 AccpCalcNeededAceSize(IN PSID Sid, 272 IN DWORD ObjectsPresent) 273 { 274 DWORD Ret; 275 276 Ret = sizeof(ACE) + GetLengthSid(Sid); 277 278 /* This routine calculates the generic size of the ACE needed. 279 If no objects are present it is assumed that only a standard 280 ACE is to be created. */ 281 282 if (ObjectsPresent & ACE_OBJECT_TYPE_PRESENT) 283 Ret += sizeof(GUID); 284 if (ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) 285 Ret += sizeof(GUID); 286 287 if (ObjectsPresent != 0) 288 Ret += sizeof(DWORD); /* Include the Flags member to make it an object ACE */ 289 290 return Ret; 291 } 292 293 static GUID* 294 AccpGetObjectAceObjectType(IN PACE_HEADER AceHeader) 295 { 296 GUID *ObjectType = NULL; 297 298 switch (AceHeader->AceType) 299 { 300 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 301 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 302 { 303 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader; 304 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 305 ObjectType = &Ace->ObjectType; 306 break; 307 } 308 case ACCESS_ALLOWED_OBJECT_ACE_TYPE: 309 case ACCESS_DENIED_OBJECT_ACE_TYPE: 310 { 311 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader; 312 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 313 ObjectType = &Ace->ObjectType; 314 break; 315 } 316 317 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 318 { 319 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader; 320 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 321 ObjectType = &Ace->ObjectType; 322 break; 323 } 324 case SYSTEM_AUDIT_OBJECT_ACE_TYPE: 325 { 326 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader; 327 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 328 ObjectType = &Ace->ObjectType; 329 break; 330 } 331 } 332 333 return ObjectType; 334 } 335 336 static GUID* 337 AccpGetObjectAceInheritedObjectType(IN PACE_HEADER AceHeader) 338 { 339 GUID *ObjectType = NULL; 340 341 switch (AceHeader->AceType) 342 { 343 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 344 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 345 { 346 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader; 347 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) 348 { 349 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 350 ObjectType = &Ace->InheritedObjectType; 351 else 352 ObjectType = &Ace->ObjectType; 353 } 354 break; 355 } 356 case ACCESS_ALLOWED_OBJECT_ACE_TYPE: 357 case ACCESS_DENIED_OBJECT_ACE_TYPE: 358 { 359 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader; 360 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) 361 { 362 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 363 ObjectType = &Ace->InheritedObjectType; 364 else 365 ObjectType = &Ace->ObjectType; 366 } 367 break; 368 } 369 370 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 371 { 372 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader; 373 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) 374 { 375 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 376 ObjectType = &Ace->InheritedObjectType; 377 else 378 ObjectType = &Ace->ObjectType; 379 } 380 break; 381 } 382 case SYSTEM_AUDIT_OBJECT_ACE_TYPE: 383 { 384 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader; 385 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) 386 { 387 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) 388 ObjectType = &Ace->InheritedObjectType; 389 else 390 ObjectType = &Ace->ObjectType; 391 } 392 break; 393 } 394 } 395 396 return ObjectType; 397 } 398 399 static DWORD 400 AccpOpenLSAPolicyHandle(IN LPWSTR SystemName, 401 IN ACCESS_MASK DesiredAccess, 402 OUT PLSA_HANDLE pPolicyHandle) 403 { 404 LSA_OBJECT_ATTRIBUTES LsaObjectAttributes = {0}; 405 LSA_UNICODE_STRING LsaSystemName, *psn; 406 NTSTATUS Status; 407 408 if (SystemName != NULL && SystemName[0] != L'\0') 409 { 410 LsaSystemName.Buffer = SystemName; 411 LsaSystemName.Length = wcslen(SystemName) * sizeof(WCHAR); 412 LsaSystemName.MaximumLength = LsaSystemName.Length + sizeof(WCHAR); 413 psn = &LsaSystemName; 414 } 415 else 416 { 417 psn = NULL; 418 } 419 420 Status = LsaOpenPolicy(psn, 421 &LsaObjectAttributes, 422 DesiredAccess, 423 pPolicyHandle); 424 if (!NT_SUCCESS(Status)) 425 return LsaNtStatusToWinError(Status); 426 427 return ERROR_SUCCESS; 428 } 429 430 static LPWSTR 431 AccpGetTrusteeName(IN PTRUSTEE_W Trustee) 432 { 433 switch (Trustee->TrusteeForm) 434 { 435 case TRUSTEE_IS_NAME: 436 return Trustee->ptstrName; 437 438 case TRUSTEE_IS_OBJECTS_AND_NAME: 439 return ((POBJECTS_AND_NAME_W)Trustee->ptstrName)->ptstrName; 440 441 default: 442 return NULL; 443 } 444 } 445 446 static DWORD 447 AccpLookupCurrentUser(OUT PSID *ppSid) 448 { 449 DWORD Ret; 450 CHAR Buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES]; 451 DWORD Length; 452 HANDLE Token; 453 PSID pSid; 454 455 *ppSid = NULL; 456 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &Token)) 457 { 458 Ret = GetLastError(); 459 if (Ret != ERROR_NO_TOKEN) 460 { 461 return Ret; 462 } 463 464 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &Token)) 465 { 466 return GetLastError(); 467 } 468 } 469 470 Length = sizeof(Buffer); 471 if (!GetTokenInformation(Token, TokenUser, Buffer, Length, &Length)) 472 { 473 Ret = GetLastError(); 474 CloseHandle(Token); 475 return Ret; 476 } 477 CloseHandle(Token); 478 479 pSid = ((PTOKEN_USER)Buffer)->User.Sid; 480 Length = GetLengthSid(pSid); 481 *ppSid = LocalAlloc(LMEM_FIXED, Length); 482 if (!*ppSid) 483 { 484 return ERROR_NOT_ENOUGH_MEMORY; 485 } 486 CopyMemory(*ppSid, pSid, Length); 487 488 return ERROR_SUCCESS; 489 } 490 491 static DWORD 492 AccpLookupSidByName(IN LSA_HANDLE PolicyHandle, 493 IN LPWSTR Name, 494 OUT PSID *pSid) 495 { 496 NTSTATUS Status; 497 LSA_UNICODE_STRING LsaNames[1]; 498 PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL; 499 PLSA_TRANSLATED_SID2 TranslatedSid = NULL; 500 DWORD SidLen; 501 DWORD Ret = ERROR_SUCCESS; 502 503 LsaNames[0].Buffer = Name; 504 LsaNames[0].Length = wcslen(Name) * sizeof(WCHAR); 505 LsaNames[0].MaximumLength = LsaNames[0].Length + sizeof(WCHAR); 506 507 Status = LsaLookupNames2(PolicyHandle, 508 0, 509 sizeof(LsaNames) / sizeof(LsaNames[0]), 510 LsaNames, 511 &ReferencedDomains, 512 &TranslatedSid); 513 514 if (!NT_SUCCESS(Status)) 515 return LsaNtStatusToWinError(Status); 516 517 if (TranslatedSid->Use == SidTypeUnknown || TranslatedSid->Use == SidTypeInvalid) 518 { 519 Ret = LsaNtStatusToWinError(STATUS_NONE_MAPPED); /* FIXME- what error code? */ 520 goto Cleanup; 521 } 522 523 SidLen = GetLengthSid(TranslatedSid->Sid); 524 ASSERT(SidLen != 0); 525 526 *pSid = LocalAlloc(LMEM_FIXED, (SIZE_T)SidLen); 527 if (*pSid != NULL) 528 { 529 if (!CopySid(SidLen, 530 *pSid, 531 TranslatedSid->Sid)) 532 { 533 Ret = GetLastError(); 534 535 LocalFree((HLOCAL)*pSid); 536 *pSid = NULL; 537 } 538 } 539 else 540 Ret = ERROR_NOT_ENOUGH_MEMORY; 541 542 Cleanup: 543 LsaFreeMemory(ReferencedDomains); 544 LsaFreeMemory(TranslatedSid); 545 546 return Ret; 547 } 548 549 550 static DWORD 551 AccpGetTrusteeSid(IN PTRUSTEE_W Trustee, 552 IN OUT PLSA_HANDLE pPolicyHandle, 553 OUT PSID *ppSid, 554 OUT BOOL *Allocated) 555 { 556 DWORD Ret = ERROR_SUCCESS; 557 LPWSTR TrusteeName; 558 559 *ppSid = NULL; 560 *Allocated = FALSE; 561 562 /* Windows ignores this */ 563 #if 0 564 if (Trustee->pMultipleTrustee || Trustee->MultipleTrusteeOperation != NO_MULTIPLE_TRUSTEE) 565 { 566 /* This is currently not supported */ 567 return ERROR_INVALID_PARAMETER; 568 } 569 #endif 570 571 switch (Trustee->TrusteeForm) 572 { 573 case TRUSTEE_IS_OBJECTS_AND_NAME: 574 if (((POBJECTS_AND_NAME_W)Trustee->ptstrName)->ObjectsPresent != 0) 575 { 576 /* This is not supported as there is no way to interpret the 577 strings provided, and we need GUIDs for the ACEs... */ 578 Ret = ERROR_INVALID_PARAMETER; 579 break; 580 } 581 /* fall through */ 582 583 case TRUSTEE_IS_NAME: 584 TrusteeName = AccpGetTrusteeName(Trustee); 585 if (!wcscmp(TrusteeName, L"CURRENT_USER")) 586 { 587 Ret = AccpLookupCurrentUser(ppSid); 588 if (Ret == ERROR_SUCCESS) 589 { 590 ASSERT(*ppSid != NULL); 591 *Allocated = TRUE; 592 } 593 break; 594 } 595 596 if (*pPolicyHandle == NULL) 597 { 598 Ret = AccpOpenLSAPolicyHandle(NULL, /* FIXME - always local? */ 599 POLICY_LOOKUP_NAMES, 600 pPolicyHandle); 601 if (Ret != ERROR_SUCCESS) 602 return Ret; 603 604 ASSERT(*pPolicyHandle != NULL); 605 } 606 607 Ret = AccpLookupSidByName(*pPolicyHandle, 608 TrusteeName, 609 ppSid); 610 if (Ret == ERROR_SUCCESS) 611 { 612 ASSERT(*ppSid != NULL); 613 *Allocated = TRUE; 614 } 615 break; 616 617 case TRUSTEE_IS_OBJECTS_AND_SID: 618 *ppSid = ((POBJECTS_AND_SID)Trustee->ptstrName)->pSid; 619 break; 620 621 case TRUSTEE_IS_SID: 622 *ppSid = (PSID)Trustee->ptstrName; 623 break; 624 625 default: 626 Ret = ERROR_INVALID_PARAMETER; 627 break; 628 } 629 630 return Ret; 631 } 632 633 634 /********************************************************************** 635 * AccRewriteGetHandleRights EXPORTED 636 * 637 * @unimplemented 638 */ 639 DWORD WINAPI 640 AccRewriteGetHandleRights(HANDLE handle, 641 SE_OBJECT_TYPE ObjectType, 642 SECURITY_INFORMATION SecurityInfo, 643 PSID* ppsidOwner, 644 PSID* ppsidGroup, 645 PACL* ppDacl, 646 PACL* ppSacl, 647 PSECURITY_DESCRIPTOR* ppSecurityDescriptor) 648 { 649 PSECURITY_DESCRIPTOR pSD = NULL; 650 ULONG SDSize = 0; 651 NTSTATUS Status; 652 DWORD LastErr; 653 DWORD Ret; 654 655 /* save the last error code */ 656 LastErr = GetLastError(); 657 658 do 659 { 660 Ret = ERROR_SUCCESS; 661 662 /* allocate a buffer large enough to hold the 663 security descriptor we need to return */ 664 SDSize += 0x100; 665 if (pSD == NULL) 666 { 667 pSD = LocalAlloc(LMEM_FIXED, 668 (SIZE_T)SDSize); 669 } 670 else 671 { 672 PSECURITY_DESCRIPTOR newSD; 673 674 newSD = LocalReAlloc((HLOCAL)pSD, 675 (SIZE_T)SDSize, 676 LMEM_MOVEABLE); 677 if (newSD != NULL) 678 pSD = newSD; 679 } 680 681 if (pSD == NULL) 682 { 683 Ret = GetLastError(); 684 break; 685 } 686 687 /* perform the actual query depending on the object type */ 688 switch (ObjectType) 689 { 690 case SE_REGISTRY_KEY: 691 { 692 Ret = (DWORD)RegGetKeySecurity((HKEY)handle, 693 SecurityInfo, 694 pSD, 695 &SDSize); 696 break; 697 } 698 699 case SE_FILE_OBJECT: 700 /* FIXME - handle console handles? */ 701 case SE_KERNEL_OBJECT: 702 { 703 Status = NtQuerySecurityObject(handle, 704 SecurityInfo, 705 pSD, 706 SDSize, 707 &SDSize); 708 if (!NT_SUCCESS(Status)) 709 { 710 Ret = RtlNtStatusToDosError(Status); 711 } 712 break; 713 } 714 715 case SE_SERVICE: 716 { 717 if (!QueryServiceObjectSecurity((SC_HANDLE)handle, 718 SecurityInfo, 719 pSD, 720 SDSize, 721 &SDSize)) 722 { 723 Ret = GetLastError(); 724 } 725 break; 726 } 727 728 case SE_WINDOW_OBJECT: 729 { 730 if (!GetUserObjectSecurity(handle, 731 &SecurityInfo, 732 pSD, 733 SDSize, 734 &SDSize)) 735 { 736 Ret = GetLastError(); 737 } 738 break; 739 } 740 741 default: 742 { 743 UNIMPLEMENTED; 744 Ret = ERROR_CALL_NOT_IMPLEMENTED; 745 break; 746 } 747 } 748 749 } while (Ret == ERROR_INSUFFICIENT_BUFFER); 750 751 if (Ret == ERROR_SUCCESS) 752 { 753 BOOL Present, Defaulted; 754 755 if (SecurityInfo & OWNER_SECURITY_INFORMATION && ppsidOwner != NULL) 756 { 757 *ppsidOwner = NULL; 758 if (!GetSecurityDescriptorOwner(pSD, 759 ppsidOwner, 760 &Defaulted)) 761 { 762 Ret = GetLastError(); 763 goto Cleanup; 764 } 765 } 766 767 if (SecurityInfo & GROUP_SECURITY_INFORMATION && ppsidGroup != NULL) 768 { 769 *ppsidGroup = NULL; 770 if (!GetSecurityDescriptorGroup(pSD, 771 ppsidGroup, 772 &Defaulted)) 773 { 774 Ret = GetLastError(); 775 goto Cleanup; 776 } 777 } 778 779 if (SecurityInfo & DACL_SECURITY_INFORMATION && ppDacl != NULL) 780 { 781 *ppDacl = NULL; 782 if (!GetSecurityDescriptorDacl(pSD, 783 &Present, 784 ppDacl, 785 &Defaulted)) 786 { 787 Ret = GetLastError(); 788 goto Cleanup; 789 } 790 } 791 792 if (SecurityInfo & SACL_SECURITY_INFORMATION && ppSacl != NULL) 793 { 794 *ppSacl = NULL; 795 if (!GetSecurityDescriptorSacl(pSD, 796 &Present, 797 ppSacl, 798 &Defaulted)) 799 { 800 Ret = GetLastError(); 801 goto Cleanup; 802 } 803 } 804 805 *ppSecurityDescriptor = pSD; 806 } 807 else 808 { 809 Cleanup: 810 if (pSD != NULL) 811 { 812 LocalFree((HLOCAL)pSD); 813 } 814 } 815 816 /* restore the last error code */ 817 SetLastError(LastErr); 818 819 return Ret; 820 } 821 822 823 /********************************************************************** 824 * AccRewriteSetHandleRights EXPORTED 825 * 826 * @unimplemented 827 */ 828 DWORD WINAPI 829 AccRewriteSetHandleRights(HANDLE handle, 830 SE_OBJECT_TYPE ObjectType, 831 SECURITY_INFORMATION SecurityInfo, 832 PSECURITY_DESCRIPTOR pSecurityDescriptor) 833 { 834 NTSTATUS Status; 835 DWORD LastErr; 836 DWORD Ret = ERROR_SUCCESS; 837 838 /* save the last error code */ 839 LastErr = GetLastError(); 840 841 /* set the security according to the object type */ 842 switch (ObjectType) 843 { 844 case SE_REGISTRY_KEY: 845 { 846 Ret = (DWORD)RegSetKeySecurity((HKEY)handle, 847 SecurityInfo, 848 pSecurityDescriptor); 849 break; 850 } 851 852 case SE_FILE_OBJECT: 853 /* FIXME - handle console handles? */ 854 case SE_KERNEL_OBJECT: 855 { 856 Status = NtSetSecurityObject(handle, 857 SecurityInfo, 858 pSecurityDescriptor); 859 if (!NT_SUCCESS(Status)) 860 { 861 Ret = RtlNtStatusToDosError(Status); 862 } 863 break; 864 } 865 866 case SE_SERVICE: 867 { 868 if (!SetServiceObjectSecurity((SC_HANDLE)handle, 869 SecurityInfo, 870 pSecurityDescriptor)) 871 { 872 Ret = GetLastError(); 873 } 874 break; 875 } 876 877 case SE_WINDOW_OBJECT: 878 { 879 if (!SetUserObjectSecurity(handle, 880 &SecurityInfo, 881 pSecurityDescriptor)) 882 { 883 Ret = GetLastError(); 884 } 885 break; 886 } 887 888 default: 889 { 890 UNIMPLEMENTED; 891 Ret = ERROR_CALL_NOT_IMPLEMENTED; 892 break; 893 } 894 } 895 896 897 /* restore the last error code */ 898 SetLastError(LastErr); 899 900 return Ret; 901 } 902 903 904 static DWORD 905 AccpOpenNamedObject(LPWSTR pObjectName, 906 SE_OBJECT_TYPE ObjectType, 907 SECURITY_INFORMATION SecurityInfo, 908 PHANDLE Handle, 909 PHANDLE Handle2, 910 BOOL Write) 911 { 912 LPWSTR lpPath; 913 NTSTATUS Status; 914 ACCESS_MASK DesiredAccess = (ACCESS_MASK)0; 915 DWORD Ret = ERROR_SUCCESS; 916 917 /* determine the required access rights */ 918 switch (ObjectType) 919 { 920 case SE_REGISTRY_KEY: 921 case SE_FILE_OBJECT: 922 case SE_KERNEL_OBJECT: 923 case SE_SERVICE: 924 case SE_WINDOW_OBJECT: 925 if (Write) 926 { 927 SetSecurityAccessMask(SecurityInfo, 928 (PDWORD)&DesiredAccess); 929 } 930 else 931 { 932 QuerySecurityAccessMask(SecurityInfo, 933 (PDWORD)&DesiredAccess); 934 } 935 break; 936 937 default: 938 break; 939 } 940 941 /* make a copy of the path if we're modifying the string */ 942 switch (ObjectType) 943 { 944 case SE_REGISTRY_KEY: 945 case SE_SERVICE: 946 lpPath = (LPWSTR)LocalAlloc(LMEM_FIXED, 947 (wcslen(pObjectName) + 1) * sizeof(WCHAR)); 948 if (lpPath == NULL) 949 { 950 Ret = GetLastError(); 951 goto Cleanup; 952 } 953 954 wcscpy(lpPath, 955 pObjectName); 956 break; 957 958 default: 959 lpPath = pObjectName; 960 break; 961 } 962 963 /* open a handle to the path depending on the object type */ 964 switch (ObjectType) 965 { 966 case SE_FILE_OBJECT: 967 { 968 IO_STATUS_BLOCK IoStatusBlock; 969 OBJECT_ATTRIBUTES ObjectAttributes; 970 UNICODE_STRING FileName; 971 972 if (!RtlDosPathNameToNtPathName_U(pObjectName, 973 &FileName, 974 NULL, 975 NULL)) 976 { 977 Ret = ERROR_INVALID_NAME; 978 goto Cleanup; 979 } 980 981 InitializeObjectAttributes(&ObjectAttributes, 982 &FileName, 983 OBJ_CASE_INSENSITIVE, 984 NULL, 985 NULL); 986 987 Status = NtOpenFile(Handle, 988 DesiredAccess | SYNCHRONIZE, 989 &ObjectAttributes, 990 &IoStatusBlock, 991 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 992 FILE_SYNCHRONOUS_IO_NONALERT); 993 994 RtlFreeHeap(RtlGetProcessHeap(), 995 0, 996 FileName.Buffer); 997 998 if (!NT_SUCCESS(Status)) 999 { 1000 Ret = RtlNtStatusToDosError(Status); 1001 } 1002 break; 1003 } 1004 1005 case SE_REGISTRY_KEY: 1006 { 1007 static const struct 1008 { 1009 HKEY hRootKey; 1010 LPCWSTR szRootKey; 1011 } AccRegRootKeys[] = 1012 { 1013 {HKEY_CLASSES_ROOT, L"CLASSES_ROOT"}, 1014 {HKEY_CURRENT_USER, L"CURRENT_USER"}, 1015 {HKEY_LOCAL_MACHINE, L"MACHINE"}, 1016 {HKEY_USERS, L"USERS"}, 1017 {HKEY_CURRENT_CONFIG, L"CONFIG"}, 1018 }; 1019 LPWSTR lpMachineName, lpRootKeyName, lpKeyName; 1020 HKEY hRootKey = NULL; 1021 UINT i; 1022 1023 /* parse the registry path */ 1024 if (lpPath[0] == L'\\' && lpPath[1] == L'\\') 1025 { 1026 lpMachineName = lpPath; 1027 1028 lpRootKeyName = wcschr(lpPath + 2, 1029 L'\\'); 1030 if (lpRootKeyName == NULL) 1031 goto ParseRegErr; 1032 else 1033 *(lpRootKeyName++) = L'\0'; 1034 } 1035 else 1036 { 1037 lpMachineName = NULL; 1038 lpRootKeyName = lpPath; 1039 } 1040 1041 lpKeyName = wcschr(lpRootKeyName, 1042 L'\\'); 1043 if (lpKeyName != NULL) 1044 { 1045 *(lpKeyName++) = L'\0'; 1046 } 1047 1048 for (i = 0; 1049 i != sizeof(AccRegRootKeys) / sizeof(AccRegRootKeys[0]); 1050 i++) 1051 { 1052 if (!wcsicmp(lpRootKeyName, 1053 AccRegRootKeys[i].szRootKey)) 1054 { 1055 hRootKey = AccRegRootKeys[i].hRootKey; 1056 break; 1057 } 1058 } 1059 1060 if (hRootKey == NULL) 1061 { 1062 ParseRegErr: 1063 /* FIXME - right error code? */ 1064 Ret = ERROR_INVALID_PARAMETER; 1065 goto Cleanup; 1066 } 1067 1068 /* open the registry key */ 1069 if (lpMachineName != NULL) 1070 { 1071 Ret = RegConnectRegistry(lpMachineName, 1072 hRootKey, 1073 (PHKEY)Handle2); 1074 1075 if (Ret != ERROR_SUCCESS) 1076 goto Cleanup; 1077 1078 hRootKey = (HKEY)(*Handle2); 1079 } 1080 1081 Ret = RegOpenKeyEx(hRootKey, 1082 lpKeyName, 1083 0, 1084 (REGSAM)DesiredAccess, 1085 (PHKEY)Handle); 1086 if (Ret != ERROR_SUCCESS) 1087 { 1088 if (*Handle2 != NULL) 1089 { 1090 RegCloseKey((HKEY)(*Handle2)); 1091 } 1092 1093 goto Cleanup; 1094 } 1095 break; 1096 } 1097 1098 case SE_SERVICE: 1099 { 1100 LPWSTR lpServiceName, lpMachineName; 1101 1102 /* parse the service path */ 1103 if (lpPath[0] == L'\\' && lpPath[1] == L'\\') 1104 { 1105 DesiredAccess |= SC_MANAGER_CONNECT; 1106 1107 lpMachineName = lpPath; 1108 1109 lpServiceName = wcschr(lpPath + 2, 1110 L'\\'); 1111 if (lpServiceName == NULL) 1112 { 1113 /* FIXME - right error code? */ 1114 Ret = ERROR_INVALID_PARAMETER; 1115 goto Cleanup; 1116 } 1117 else 1118 *(lpServiceName++) = L'\0'; 1119 } 1120 else 1121 { 1122 lpMachineName = NULL; 1123 lpServiceName = lpPath; 1124 } 1125 1126 /* open the service */ 1127 *Handle2 = (HANDLE)OpenSCManager(lpMachineName, 1128 NULL, 1129 (DWORD)DesiredAccess); 1130 if (*Handle2 == NULL) 1131 { 1132 Ret = GetLastError(); 1133 ASSERT(Ret != ERROR_SUCCESS); 1134 goto Cleanup; 1135 } 1136 1137 DesiredAccess &= ~SC_MANAGER_CONNECT; 1138 *Handle = (HANDLE)OpenService((SC_HANDLE)(*Handle2), 1139 lpServiceName, 1140 (DWORD)DesiredAccess); 1141 if (*Handle == NULL) 1142 { 1143 Ret = GetLastError(); 1144 ASSERT(Ret != ERROR_SUCCESS); 1145 ASSERT(*Handle2 != NULL); 1146 CloseServiceHandle((SC_HANDLE)(*Handle2)); 1147 1148 goto Cleanup; 1149 } 1150 break; 1151 } 1152 1153 default: 1154 { 1155 UNIMPLEMENTED; 1156 Ret = ERROR_CALL_NOT_IMPLEMENTED; 1157 break; 1158 } 1159 } 1160 1161 Cleanup: 1162 if (lpPath != NULL && lpPath != pObjectName) 1163 { 1164 LocalFree((HLOCAL)lpPath); 1165 } 1166 1167 return Ret; 1168 } 1169 1170 1171 static VOID 1172 AccpCloseObjectHandle(SE_OBJECT_TYPE ObjectType, 1173 HANDLE Handle, 1174 HANDLE Handle2) 1175 { 1176 ASSERT(Handle != NULL); 1177 1178 /* close allocated handles depending on the object type */ 1179 switch (ObjectType) 1180 { 1181 case SE_REGISTRY_KEY: 1182 RegCloseKey((HKEY)Handle); 1183 if (Handle2 != NULL) 1184 RegCloseKey((HKEY)Handle2); 1185 break; 1186 1187 case SE_FILE_OBJECT: 1188 NtClose(Handle); 1189 break; 1190 1191 case SE_KERNEL_OBJECT: 1192 case SE_WINDOW_OBJECT: 1193 CloseHandle(Handle); 1194 break; 1195 1196 case SE_SERVICE: 1197 CloseServiceHandle((SC_HANDLE)Handle); 1198 ASSERT(Handle2 != NULL); 1199 CloseServiceHandle((SC_HANDLE)Handle2); 1200 break; 1201 1202 default: 1203 break; 1204 } 1205 } 1206 1207 1208 /********************************************************************** 1209 * AccRewriteGetNamedRights EXPORTED 1210 * 1211 * @unimplemented 1212 */ 1213 DWORD WINAPI 1214 AccRewriteGetNamedRights(LPWSTR pObjectName, 1215 SE_OBJECT_TYPE ObjectType, 1216 SECURITY_INFORMATION SecurityInfo, 1217 PSID* ppsidOwner, 1218 PSID* ppsidGroup, 1219 PACL* ppDacl, 1220 PACL* ppSacl, 1221 PSECURITY_DESCRIPTOR* ppSecurityDescriptor) 1222 { 1223 HANDLE Handle = NULL; 1224 HANDLE Handle2 = NULL; 1225 DWORD LastErr; 1226 DWORD Ret; 1227 1228 /* save the last error code */ 1229 LastErr = GetLastError(); 1230 1231 /* create the handle */ 1232 Ret = AccpOpenNamedObject(pObjectName, 1233 ObjectType, 1234 SecurityInfo, 1235 &Handle, 1236 &Handle2, 1237 FALSE); 1238 1239 if (Ret == ERROR_SUCCESS) 1240 { 1241 ASSERT(Handle != NULL); 1242 1243 /* perform the operation */ 1244 Ret = AccRewriteGetHandleRights(Handle, 1245 ObjectType, 1246 SecurityInfo, 1247 ppsidOwner, 1248 ppsidGroup, 1249 ppDacl, 1250 ppSacl, 1251 ppSecurityDescriptor); 1252 1253 /* close opened handles */ 1254 AccpCloseObjectHandle(ObjectType, 1255 Handle, 1256 Handle2); 1257 } 1258 1259 /* restore the last error code */ 1260 SetLastError(LastErr); 1261 1262 return Ret; 1263 } 1264 1265 1266 /********************************************************************** 1267 * AccRewriteSetNamedRights EXPORTED 1268 * 1269 * @unimplemented 1270 */ 1271 DWORD WINAPI 1272 AccRewriteSetNamedRights(LPWSTR pObjectName, 1273 SE_OBJECT_TYPE ObjectType, 1274 SECURITY_INFORMATION SecurityInfo, 1275 PSECURITY_DESCRIPTOR pSecurityDescriptor) 1276 { 1277 HANDLE Handle = NULL; 1278 HANDLE Handle2 = NULL; 1279 DWORD LastErr; 1280 DWORD Ret; 1281 1282 /* save the last error code */ 1283 LastErr = GetLastError(); 1284 1285 /* create the handle */ 1286 Ret = AccpOpenNamedObject(pObjectName, 1287 ObjectType, 1288 SecurityInfo, 1289 &Handle, 1290 &Handle2, 1291 TRUE); 1292 1293 if (Ret == ERROR_SUCCESS) 1294 { 1295 ASSERT(Handle != NULL); 1296 1297 /* perform the operation */ 1298 Ret = AccRewriteSetHandleRights(Handle, 1299 ObjectType, 1300 SecurityInfo, 1301 pSecurityDescriptor); 1302 1303 /* close opened handles */ 1304 AccpCloseObjectHandle(ObjectType, 1305 Handle, 1306 Handle2); 1307 } 1308 1309 /* restore the last error code */ 1310 SetLastError(LastErr); 1311 1312 return Ret; 1313 } 1314 1315 1316 /********************************************************************** 1317 * AccRewriteSetEntriesInAcl EXPORTED 1318 * 1319 * @implemented 1320 */ 1321 DWORD WINAPI 1322 AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries, 1323 PEXPLICIT_ACCESS_W pListOfExplicitEntries, 1324 PACL OldAcl, 1325 PACL* NewAcl) 1326 { 1327 PACL pNew = NULL; 1328 ACL_SIZE_INFORMATION SizeInformation; 1329 PACE_HEADER pAce; 1330 BOOLEAN KeepAceBuf[8]; 1331 BOOLEAN *pKeepAce = NULL; 1332 GUID ObjectTypeGuid, InheritedObjectTypeGuid; 1333 DWORD ObjectsPresent; 1334 BOOL needToClean; 1335 PSID pSid1, pSid2; 1336 ULONG i, j; 1337 LSA_HANDLE PolicyHandle = NULL; 1338 BOOL bRet; 1339 DWORD LastErr; 1340 DWORD Ret = ERROR_SUCCESS; 1341 1342 /* save the last error code */ 1343 LastErr = GetLastError(); 1344 1345 *NewAcl = NULL; 1346 1347 /* Get information about previous ACL */ 1348 if (OldAcl) 1349 { 1350 if (!GetAclInformation(OldAcl, &SizeInformation, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) 1351 { 1352 Ret = GetLastError(); 1353 goto Cleanup; 1354 } 1355 1356 if (SizeInformation.AceCount > sizeof(KeepAceBuf) / sizeof(KeepAceBuf[0])) 1357 { 1358 pKeepAce = (BOOLEAN *)LocalAlloc(LMEM_FIXED, SizeInformation.AceCount * sizeof(*pKeepAce)); 1359 if (!pKeepAce) 1360 { 1361 Ret = ERROR_NOT_ENOUGH_MEMORY; 1362 goto Cleanup; 1363 } 1364 } 1365 else 1366 pKeepAce = KeepAceBuf; 1367 1368 memset(pKeepAce, TRUE, SizeInformation.AceCount * sizeof(*pKeepAce)); 1369 } 1370 else 1371 { 1372 ZeroMemory(&SizeInformation, sizeof(ACL_SIZE_INFORMATION)); 1373 SizeInformation.AclBytesInUse = sizeof(ACL); 1374 } 1375 1376 /* Get size required for new entries */ 1377 for (i = 0; i < cCountOfExplicitEntries; i++) 1378 { 1379 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee, 1380 &PolicyHandle, 1381 &pSid1, 1382 &needToClean); 1383 if (Ret != ERROR_SUCCESS) 1384 goto Cleanup; 1385 1386 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee, 1387 NULL, 1388 NULL); 1389 1390 switch (pListOfExplicitEntries[i].grfAccessMode) 1391 { 1392 case REVOKE_ACCESS: 1393 case SET_ACCESS: 1394 /* Discard all accesses for the trustee... */ 1395 for (j = 0; j < SizeInformation.AceCount; j++) 1396 { 1397 if (!pKeepAce[j]) 1398 continue; 1399 if (!GetAce(OldAcl, j, (PVOID*)&pAce)) 1400 { 1401 Ret = GetLastError(); 1402 goto Cleanup; 1403 } 1404 1405 pSid2 = AccpGetAceSid(pAce); 1406 if (RtlEqualSid(pSid1, pSid2)) 1407 { 1408 pKeepAce[j] = FALSE; 1409 SizeInformation.AclBytesInUse -= pAce->AceSize; 1410 } 1411 } 1412 if (pListOfExplicitEntries[i].grfAccessMode == REVOKE_ACCESS) 1413 break; 1414 /* ...and replace by the current access */ 1415 case GRANT_ACCESS: 1416 case DENY_ACCESS: 1417 /* Add to ACL */ 1418 SizeInformation.AclBytesInUse += AccpCalcNeededAceSize(pSid1, ObjectsPresent); 1419 break; 1420 case SET_AUDIT_SUCCESS: 1421 case SET_AUDIT_FAILURE: 1422 /* FIXME */ 1423 DPRINT1("Case not implemented!\n"); 1424 break; 1425 default: 1426 DPRINT1("Unknown access mode 0x%x. Ignoring it\n", pListOfExplicitEntries[i].grfAccessMode); 1427 break; 1428 } 1429 1430 if (needToClean) 1431 LocalFree((HLOCAL)pSid1); 1432 } 1433 1434 /* Succeed, if no ACL needs to be allocated */ 1435 if (SizeInformation.AclBytesInUse == 0) 1436 goto Cleanup; 1437 1438 /* OK, now create the new ACL */ 1439 DPRINT("Allocating %u bytes for the new ACL\n", SizeInformation.AclBytesInUse); 1440 pNew = (PACL)LocalAlloc(LMEM_FIXED, SizeInformation.AclBytesInUse); 1441 if (!pNew) 1442 { 1443 Ret = ERROR_NOT_ENOUGH_MEMORY; 1444 goto Cleanup; 1445 } 1446 if (!InitializeAcl(pNew, SizeInformation.AclBytesInUse, ACL_REVISION)) 1447 { 1448 Ret = GetLastError(); 1449 goto Cleanup; 1450 } 1451 1452 /* Fill it */ 1453 /* 1a) New audit entries (SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE) */ 1454 /* FIXME */ 1455 1456 /* 1b) Existing audit entries */ 1457 /* FIXME */ 1458 1459 /* 2a) New denied entries (DENY_ACCESS) */ 1460 for (i = 0; i < cCountOfExplicitEntries; i++) 1461 { 1462 if (pListOfExplicitEntries[i].grfAccessMode == DENY_ACCESS) 1463 { 1464 /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */ 1465 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee, 1466 &PolicyHandle, 1467 &pSid1, 1468 &needToClean); 1469 if (Ret != ERROR_SUCCESS) 1470 goto Cleanup; 1471 1472 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee, 1473 &ObjectTypeGuid, 1474 &InheritedObjectTypeGuid); 1475 1476 if (ObjectsPresent == 0) 1477 { 1478 /* FIXME: Call AddAccessDeniedAceEx instead! */ 1479 bRet = AddAccessDeniedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1); 1480 } 1481 else 1482 { 1483 /* FIXME: Call AddAccessDeniedObjectAce */ 1484 DPRINT1("Object ACEs not yet supported!\n"); 1485 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1486 bRet = FALSE; 1487 } 1488 1489 if (needToClean) LocalFree((HLOCAL)pSid1); 1490 if (!bRet) 1491 { 1492 Ret = GetLastError(); 1493 goto Cleanup; 1494 } 1495 } 1496 } 1497 1498 /* 2b) Existing denied entries */ 1499 /* FIXME */ 1500 1501 /* 3a) New allow entries (GRANT_ACCESS, SET_ACCESS) */ 1502 for (i = 0; i < cCountOfExplicitEntries; i++) 1503 { 1504 if (pListOfExplicitEntries[i].grfAccessMode == SET_ACCESS || 1505 pListOfExplicitEntries[i].grfAccessMode == GRANT_ACCESS) 1506 { 1507 /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */ 1508 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee, 1509 &PolicyHandle, 1510 &pSid1, 1511 &needToClean); 1512 if (Ret != ERROR_SUCCESS) 1513 goto Cleanup; 1514 1515 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee, 1516 &ObjectTypeGuid, 1517 &InheritedObjectTypeGuid); 1518 1519 if (ObjectsPresent == 0) 1520 { 1521 /* FIXME: Call AddAccessAllowedAceEx instead! */ 1522 bRet = AddAccessAllowedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1); 1523 } 1524 else 1525 { 1526 /* FIXME: Call AddAccessAllowedObjectAce */ 1527 DPRINT1("Object ACEs not yet supported!\n"); 1528 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1529 bRet = FALSE; 1530 } 1531 1532 if (needToClean) LocalFree((HLOCAL)pSid1); 1533 if (!bRet) 1534 { 1535 Ret = GetLastError(); 1536 goto Cleanup; 1537 } 1538 } 1539 } 1540 1541 /* 3b) Existing allow entries */ 1542 /* FIXME */ 1543 1544 *NewAcl = pNew; 1545 1546 Cleanup: 1547 if (pKeepAce && pKeepAce != KeepAceBuf) 1548 LocalFree((HLOCAL)pKeepAce); 1549 1550 if (pNew && Ret != ERROR_SUCCESS) 1551 LocalFree((HLOCAL)pNew); 1552 1553 if (PolicyHandle) 1554 LsaClose(PolicyHandle); 1555 1556 /* restore the last error code */ 1557 SetLastError(LastErr); 1558 1559 return Ret; 1560 } 1561 1562 1563 /********************************************************************** 1564 * AccGetInheritanceSource EXPORTED 1565 * 1566 * @unimplemented 1567 */ 1568 DWORD WINAPI 1569 AccGetInheritanceSource(LPWSTR pObjectName, 1570 SE_OBJECT_TYPE ObjectType, 1571 SECURITY_INFORMATION SecurityInfo, 1572 BOOL Container, 1573 GUID** pObjectClassGuids, 1574 DWORD GuidCount, 1575 PACL pAcl, 1576 PFN_OBJECT_MGR_FUNCTS pfnArray, 1577 PGENERIC_MAPPING pGenericMapping, 1578 PINHERITED_FROMW pInheritArray) 1579 { 1580 UNIMPLEMENTED; 1581 return ERROR_CALL_NOT_IMPLEMENTED; 1582 } 1583 1584 1585 /********************************************************************** 1586 * AccFreeIndexArray EXPORTED 1587 * 1588 * @implemented 1589 */ 1590 DWORD WINAPI 1591 AccFreeIndexArray(PINHERITED_FROMW pInheritArray, 1592 USHORT AceCnt, 1593 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL) 1594 { 1595 PINHERITED_FROMW pLast; 1596 1597 UNREFERENCED_PARAMETER(pfnArray); 1598 1599 pLast = pInheritArray + AceCnt; 1600 while (pInheritArray != pLast) 1601 { 1602 if (pInheritArray->AncestorName != NULL) 1603 { 1604 LocalFree((HLOCAL)pInheritArray->AncestorName); 1605 pInheritArray->AncestorName = NULL; 1606 } 1607 1608 pInheritArray++; 1609 } 1610 1611 return ERROR_SUCCESS; 1612 } 1613 1614 1615 /********************************************************************** 1616 * AccRewriteGetExplicitEntriesFromAcl EXPORTED 1617 * 1618 * @implemented 1619 */ 1620 DWORD WINAPI 1621 AccRewriteGetExplicitEntriesFromAcl(PACL pacl, 1622 PULONG pcCountOfExplicitEntries, 1623 PEXPLICIT_ACCESS_W* pListOfExplicitEntries) 1624 { 1625 PACE_HEADER AceHeader; 1626 PSID Sid, SidTarget; 1627 ULONG ObjectAceCount = 0; 1628 POBJECTS_AND_SID ObjSid; 1629 SIZE_T Size; 1630 PEXPLICIT_ACCESS_W peaw; 1631 DWORD LastErr, SidLen; 1632 DWORD AceIndex = 0; 1633 DWORD ErrorCode = ERROR_SUCCESS; 1634 1635 /* save the last error code */ 1636 LastErr = GetLastError(); 1637 1638 if (pacl != NULL) 1639 { 1640 if (pacl->AceCount != 0) 1641 { 1642 Size = (SIZE_T)pacl->AceCount * sizeof(EXPLICIT_ACCESS_W); 1643 1644 /* calculate the space needed */ 1645 while (GetAce(pacl, 1646 AceIndex, 1647 (LPVOID*)&AceHeader)) 1648 { 1649 Sid = AccpGetAceSid(AceHeader); 1650 Size += GetLengthSid(Sid); 1651 1652 if (AccpIsObjectAce(AceHeader)) 1653 ObjectAceCount++; 1654 1655 AceIndex++; 1656 } 1657 1658 Size += ObjectAceCount * sizeof(OBJECTS_AND_SID); 1659 1660 ASSERT(pacl->AceCount == AceIndex); 1661 1662 /* allocate the array */ 1663 peaw = (PEXPLICIT_ACCESS_W)LocalAlloc(LMEM_FIXED, 1664 Size); 1665 if (peaw != NULL) 1666 { 1667 AceIndex = 0; 1668 ObjSid = (POBJECTS_AND_SID)(peaw + pacl->AceCount); 1669 SidTarget = (PSID)(ObjSid + ObjectAceCount); 1670 1671 /* initialize the array */ 1672 while (GetAce(pacl, 1673 AceIndex, 1674 (LPVOID*)&AceHeader)) 1675 { 1676 Sid = AccpGetAceSid(AceHeader); 1677 SidLen = GetLengthSid(Sid); 1678 1679 peaw[AceIndex].grfAccessPermissions = AccpGetAceAccessMask(AceHeader); 1680 peaw[AceIndex].grfAccessMode = AccpGetAceAccessMode(AceHeader); 1681 peaw[AceIndex].grfInheritance = AceHeader->AceFlags & VALID_INHERIT_FLAGS; 1682 1683 if (CopySid(SidLen, 1684 SidTarget, 1685 Sid)) 1686 { 1687 if (AccpIsObjectAce(AceHeader)) 1688 { 1689 BuildTrusteeWithObjectsAndSid(&peaw[AceIndex].Trustee, 1690 ObjSid++, 1691 AccpGetObjectAceObjectType(AceHeader), 1692 AccpGetObjectAceInheritedObjectType(AceHeader), 1693 SidTarget); 1694 } 1695 else 1696 { 1697 BuildTrusteeWithSid(&peaw[AceIndex].Trustee, 1698 SidTarget); 1699 } 1700 1701 SidTarget = (PSID)((ULONG_PTR)SidTarget + SidLen); 1702 } 1703 else 1704 { 1705 /* copying the SID failed, treat it as an fatal error... */ 1706 ErrorCode = GetLastError(); 1707 1708 /* free allocated resources */ 1709 LocalFree(peaw); 1710 peaw = NULL; 1711 AceIndex = 0; 1712 break; 1713 } 1714 1715 AceIndex++; 1716 } 1717 1718 *pcCountOfExplicitEntries = AceIndex; 1719 *pListOfExplicitEntries = peaw; 1720 } 1721 else 1722 ErrorCode = ERROR_NOT_ENOUGH_MEMORY; 1723 } 1724 else 1725 { 1726 goto EmptyACL; 1727 } 1728 } 1729 else 1730 { 1731 EmptyACL: 1732 *pcCountOfExplicitEntries = 0; 1733 *pListOfExplicitEntries = NULL; 1734 } 1735 1736 /* restore the last error code */ 1737 SetLastError(LastErr); 1738 1739 return ErrorCode; 1740 } 1741 1742 1743 /********************************************************************** 1744 * AccTreeResetNamedSecurityInfo EXPORTED 1745 * 1746 * @unimplemented 1747 */ 1748 DWORD WINAPI 1749 AccTreeResetNamedSecurityInfo(LPWSTR pObjectName, 1750 SE_OBJECT_TYPE ObjectType, 1751 SECURITY_INFORMATION SecurityInfo, 1752 PSID pOwner, 1753 PSID pGroup, 1754 PACL pDacl, 1755 PACL pSacl, 1756 BOOL KeepExplicit, 1757 FN_PROGRESSW fnProgress, 1758 PROG_INVOKE_SETTING ProgressInvokeSetting, 1759 PVOID Args) 1760 { 1761 UNIMPLEMENTED; 1762 return ERROR_CALL_NOT_IMPLEMENTED; 1763 } 1764 1765 1766 BOOL WINAPI 1767 DllMain(IN HINSTANCE hinstDLL, 1768 IN DWORD dwReason, 1769 IN LPVOID lpvReserved) 1770 { 1771 switch (dwReason) 1772 { 1773 case DLL_PROCESS_ATTACH: 1774 hDllInstance = hinstDLL; 1775 DisableThreadLibraryCalls(hinstDLL); 1776 break; 1777 1778 case DLL_PROCESS_DETACH: 1779 break; 1780 } 1781 return TRUE; 1782 } 1783 1784