1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: lib/advapi32/sec/ac.c 5 * PURPOSE: ACL/ACE functions 6 */ 7 8 #include <advapi32.h> 9 WINE_DEFAULT_DEBUG_CHANNEL(advapi); 10 11 /* --- ACE --- */ 12 13 /* 14 * @implemented 15 */ 16 BOOL 17 WINAPI 18 AddAccessAllowedObjectAce(PACL pAcl, 19 DWORD dwAceRevision, 20 DWORD AceFlags, 21 DWORD AccessMask, 22 GUID *ObjectTypeGuid, 23 GUID *InheritedObjectTypeGuid, 24 PSID pSid) 25 { 26 NTSTATUS Status; 27 28 Status = RtlAddAccessAllowedObjectAce(pAcl, 29 dwAceRevision, 30 AceFlags, 31 AccessMask, 32 ObjectTypeGuid, 33 InheritedObjectTypeGuid, 34 pSid); 35 if (!NT_SUCCESS(Status)) 36 { 37 SetLastError(RtlNtStatusToDosError(Status)); 38 return FALSE; 39 } 40 41 return TRUE; 42 } 43 44 /* 45 * @implemented 46 */ 47 BOOL 48 WINAPI 49 AddAccessDeniedObjectAce(PACL pAcl, 50 DWORD dwAceRevision, 51 DWORD AceFlags, 52 DWORD AccessMask, 53 GUID* ObjectTypeGuid, 54 GUID* InheritedObjectTypeGuid, 55 PSID pSid) 56 { 57 NTSTATUS Status; 58 59 Status = RtlAddAccessDeniedObjectAce(pAcl, 60 dwAceRevision, 61 AceFlags, 62 AccessMask, 63 ObjectTypeGuid, 64 InheritedObjectTypeGuid, 65 pSid); 66 if (!NT_SUCCESS(Status)) 67 { 68 SetLastError(RtlNtStatusToDosError(Status)); 69 return FALSE; 70 } 71 72 return TRUE; 73 } 74 75 /* 76 * @implemented 77 */ 78 BOOL 79 WINAPI 80 AddAuditAccessObjectAce(PACL pAcl, 81 DWORD dwAceRevision, 82 DWORD AceFlags, 83 DWORD AccessMask, 84 GUID *ObjectTypeGuid, 85 GUID *InheritedObjectTypeGuid, 86 PSID pSid, 87 BOOL bAuditSuccess, 88 BOOL bAuditFailure) 89 { 90 NTSTATUS Status; 91 92 Status = RtlAddAuditAccessObjectAce(pAcl, 93 dwAceRevision, 94 AceFlags, 95 AccessMask, 96 ObjectTypeGuid, 97 InheritedObjectTypeGuid, 98 pSid, 99 bAuditSuccess, 100 bAuditFailure); 101 if (!NT_SUCCESS(Status)) 102 { 103 SetLastError(RtlNtStatusToDosError(Status)); 104 return FALSE; 105 } 106 107 return TRUE; 108 } 109 110 /* 111 * @implemented 112 */ 113 DWORD 114 WINAPI 115 GetInheritanceSourceW(LPWSTR pObjectName, 116 SE_OBJECT_TYPE ObjectType, 117 SECURITY_INFORMATION SecurityInfo, 118 BOOL Container, 119 GUID **pObjectClassGuids OPTIONAL, 120 DWORD GuidCount, 121 PACL pAcl, 122 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL, 123 PGENERIC_MAPPING pGenericMapping, 124 PINHERITED_FROMW pInheritArray) 125 { 126 DWORD ErrorCode; 127 128 ErrorCode = CheckNtMartaPresent(); 129 if (ErrorCode == ERROR_SUCCESS) 130 { 131 /* call the MARTA provider */ 132 ErrorCode = AccGetInheritanceSource(pObjectName, 133 ObjectType, 134 SecurityInfo, 135 Container, 136 pObjectClassGuids, 137 GuidCount, 138 pAcl, 139 pfnArray, 140 pGenericMapping, 141 pInheritArray); 142 } 143 144 return ErrorCode; 145 } 146 147 148 /* 149 * @unimplemented 150 */ 151 DWORD 152 WINAPI 153 GetInheritanceSourceA(LPSTR pObjectName, 154 SE_OBJECT_TYPE ObjectType, 155 SECURITY_INFORMATION SecurityInfo, 156 BOOL Container, 157 GUID **pObjectClassGuids OPTIONAL, 158 DWORD GuidCount, 159 PACL pAcl, 160 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL, 161 PGENERIC_MAPPING pGenericMapping, 162 PINHERITED_FROMA pInheritArray) 163 { 164 /* That's all this function does, at least up to w2k3... Even MS was too 165 lazy to implement it... */ 166 return ERROR_CALL_NOT_IMPLEMENTED; 167 } 168 169 170 /* 171 * @implemented 172 */ 173 DWORD 174 WINAPI 175 FreeInheritedFromArray(PINHERITED_FROMW pInheritArray, 176 USHORT AceCnt, 177 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL) 178 { 179 DWORD ErrorCode; 180 181 ErrorCode = CheckNtMartaPresent(); 182 if (ErrorCode == ERROR_SUCCESS) 183 { 184 /* call the MARTA provider */ 185 ErrorCode = AccFreeIndexArray(pInheritArray, 186 AceCnt, 187 pfnArray); 188 } 189 190 return ErrorCode; 191 } 192 193 194 /* 195 * @implemented 196 */ 197 DWORD 198 WINAPI 199 SetEntriesInAclW(ULONG cCountOfExplicitEntries, 200 PEXPLICIT_ACCESS_W pListOfExplicitEntries, 201 PACL OldAcl, 202 PACL *NewAcl) 203 { 204 DWORD ErrorCode; 205 206 if (!NewAcl) 207 { 208 return ERROR_INVALID_PARAMETER; 209 } 210 211 ErrorCode = CheckNtMartaPresent(); 212 if (ErrorCode == ERROR_SUCCESS) 213 { 214 /* call the MARTA provider */ 215 ErrorCode = AccRewriteSetEntriesInAcl(cCountOfExplicitEntries, 216 pListOfExplicitEntries, 217 OldAcl, 218 NewAcl); 219 } 220 221 return ErrorCode; 222 } 223 224 225 static DWORD 226 InternalTrusteeAToW(IN PTRUSTEE_A pTrusteeA, 227 OUT PTRUSTEE_W *pTrusteeW) 228 { 229 TRUSTEE_FORM TrusteeForm; 230 INT BufferSize = 0; 231 PSTR lpStr; 232 DWORD ErrorCode = ERROR_SUCCESS; 233 234 //ASSERT(sizeof(TRUSTEE_W) == sizeof(TRUSTEE_A)); 235 236 TrusteeForm = GetTrusteeFormA(pTrusteeA); 237 switch (TrusteeForm) 238 { 239 case TRUSTEE_IS_NAME: 240 { 241 /* directly copy the array, this works as the size of the EXPLICIT_ACCESS_A 242 structure matches the size of the EXPLICIT_ACCESS_W version */ 243 lpStr = GetTrusteeNameA(pTrusteeA); 244 if (lpStr != NULL) 245 BufferSize = strlen(lpStr) + 1; 246 247 *pTrusteeW = RtlAllocateHeap(RtlGetProcessHeap(), 248 0, 249 sizeof(TRUSTEE_W) + (BufferSize * sizeof(WCHAR))); 250 if (*pTrusteeW != NULL) 251 { 252 RtlCopyMemory(*pTrusteeW, 253 pTrusteeA, 254 FIELD_OFFSET(TRUSTEE_A, 255 ptstrName)); 256 257 if (lpStr != NULL) 258 { 259 (*pTrusteeW)->ptstrName = (PWSTR)((*pTrusteeW) + 1); 260 261 /* convert the trustee's name */ 262 if (MultiByteToWideChar(CP_ACP, 263 0, 264 lpStr, 265 -1, 266 (*pTrusteeW)->ptstrName, 267 BufferSize) == 0) 268 { 269 goto ConvertErr; 270 } 271 } 272 else 273 { 274 RtlFreeHeap(RtlGetProcessHeap(), 275 0, 276 *pTrusteeW); 277 goto NothingToConvert; 278 } 279 } 280 else 281 ErrorCode = ERROR_NOT_ENOUGH_MEMORY; 282 break; 283 } 284 285 case TRUSTEE_IS_OBJECTS_AND_NAME: 286 { 287 POBJECTS_AND_NAME_A oanA = (POBJECTS_AND_NAME_A)GetTrusteeNameA(pTrusteeA); 288 POBJECTS_AND_NAME_W oan; 289 PWSTR StrBuf; 290 291 /* calculate the size needed */ 292 if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) && 293 oanA->InheritedObjectTypeName != NULL) 294 { 295 BufferSize = strlen(oanA->InheritedObjectTypeName) + 1; 296 } 297 if (oanA->ptstrName != NULL) 298 { 299 BufferSize += strlen(oanA->ptstrName) + 1; 300 } 301 302 *pTrusteeW = RtlAllocateHeap(RtlGetProcessHeap(), 303 0, 304 sizeof(TRUSTEE_W) + sizeof(OBJECTS_AND_NAME_W) + 305 (BufferSize * sizeof(WCHAR))); 306 307 if (*pTrusteeW != NULL) 308 { 309 oan = (POBJECTS_AND_NAME_W)((*pTrusteeW) + 1); 310 StrBuf = (PWSTR)(oan + 1); 311 312 /* copy over the parts of the TRUSTEE structure that don't need 313 to be touched */ 314 RtlCopyMemory(*pTrusteeW, 315 pTrusteeA, 316 FIELD_OFFSET(TRUSTEE_A, 317 ptstrName)); 318 319 (*pTrusteeW)->ptstrName = (LPWSTR)oan; 320 321 /* convert the OBJECTS_AND_NAME_A structure */ 322 oan->ObjectsPresent = oanA->ObjectsPresent; 323 oan->ObjectType = oanA->ObjectType; 324 325 if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) && 326 oanA->InheritedObjectTypeName != NULL) 327 { 328 /* convert inherited object type name */ 329 BufferSize = strlen(oanA->InheritedObjectTypeName) + 1; 330 331 if (MultiByteToWideChar(CP_ACP, 332 0, 333 oanA->InheritedObjectTypeName, 334 -1, 335 StrBuf, 336 BufferSize) == 0) 337 { 338 goto ConvertErr; 339 } 340 oan->InheritedObjectTypeName = StrBuf; 341 342 StrBuf += BufferSize; 343 } 344 else 345 oan->InheritedObjectTypeName = NULL; 346 347 if (oanA->ptstrName != NULL) 348 { 349 /* convert the trustee name */ 350 BufferSize = strlen(oanA->ptstrName) + 1; 351 352 if (MultiByteToWideChar(CP_ACP, 353 0, 354 oanA->ptstrName, 355 -1, 356 StrBuf, 357 BufferSize) == 0) 358 { 359 goto ConvertErr; 360 } 361 oan->ptstrName = StrBuf; 362 } 363 else 364 oan->ptstrName = NULL; 365 } 366 else 367 ErrorCode = ERROR_NOT_ENOUGH_MEMORY; 368 break; 369 } 370 371 default: 372 { 373 NothingToConvert: 374 /* no need to convert anything to unicode */ 375 *pTrusteeW = (PTRUSTEE_W)pTrusteeA; 376 break; 377 } 378 } 379 380 return ErrorCode; 381 382 ConvertErr: 383 ErrorCode = GetLastError(); 384 385 /* cleanup */ 386 RtlFreeHeap(RtlGetProcessHeap(), 387 0, 388 *pTrusteeW); 389 390 return ErrorCode; 391 } 392 393 394 static __inline VOID 395 InternalFreeConvertedTrustee(IN PTRUSTEE_W pTrusteeW, 396 IN PTRUSTEE_A pTrusteeA) 397 { 398 if ((PVOID)pTrusteeW != (PVOID)pTrusteeA) 399 { 400 RtlFreeHeap(RtlGetProcessHeap(), 401 0, 402 pTrusteeW); 403 } 404 } 405 406 407 static DWORD 408 InternalExplicitAccessAToW(IN ULONG cCountOfExplicitEntries, 409 IN PEXPLICIT_ACCESS_A pListOfExplicitEntriesA, 410 OUT PEXPLICIT_ACCESS_W *pListOfExplicitEntriesW) 411 { 412 TRUSTEE_FORM TrusteeForm; 413 SIZE_T Size; 414 ULONG i; 415 ULONG ObjectsAndNameCount = 0; 416 PEXPLICIT_ACCESS_W peaw = NULL; 417 DWORD ErrorCode = ERROR_SUCCESS; 418 LPSTR lpStr; 419 420 /* NOTE: This code assumes that the size of the TRUSTEE_A and TRUSTEE_W structure matches! */ 421 //ASSERT(sizeof(TRUSTEE_A) == sizeof(TRUSTEE_W)); 422 423 if (cCountOfExplicitEntries != 0) 424 { 425 /* calculate the size needed */ 426 Size = cCountOfExplicitEntries * sizeof(EXPLICIT_ACCESS_W); 427 for (i = 0; i != cCountOfExplicitEntries; i++) 428 { 429 TrusteeForm = GetTrusteeFormA(&pListOfExplicitEntriesA[i].Trustee); 430 431 switch (TrusteeForm) 432 { 433 case TRUSTEE_IS_NAME: 434 { 435 lpStr = GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee); 436 if (lpStr != NULL) 437 Size += (strlen(lpStr) + 1) * sizeof(WCHAR); 438 break; 439 } 440 441 case TRUSTEE_IS_OBJECTS_AND_NAME: 442 { 443 POBJECTS_AND_NAME_A oan = (POBJECTS_AND_NAME_A)GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee); 444 445 if ((oan->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) && 446 oan->InheritedObjectTypeName != NULL) 447 { 448 Size += (strlen(oan->InheritedObjectTypeName) + 1) * sizeof(WCHAR); 449 } 450 451 if (oan->ptstrName != NULL) 452 Size += (strlen(oan->ptstrName) + 1) * sizeof(WCHAR); 453 454 ObjectsAndNameCount++; 455 break; 456 } 457 458 default: 459 break; 460 } 461 } 462 463 /* allocate the array */ 464 peaw = RtlAllocateHeap(RtlGetProcessHeap(), 465 0, 466 Size); 467 if (peaw != NULL) 468 { 469 INT BufferSize; 470 POBJECTS_AND_NAME_W oan = (POBJECTS_AND_NAME_W)(peaw + cCountOfExplicitEntries); 471 LPWSTR StrBuf = (LPWSTR)(oan + ObjectsAndNameCount); 472 473 /* convert the array to unicode */ 474 for (i = 0; i != cCountOfExplicitEntries; i++) 475 { 476 peaw[i].grfAccessPermissions = pListOfExplicitEntriesA[i].grfAccessPermissions; 477 peaw[i].grfAccessMode = pListOfExplicitEntriesA[i].grfAccessMode; 478 peaw[i].grfInheritance = pListOfExplicitEntriesA[i].grfInheritance; 479 480 /* convert or copy the TRUSTEE structure */ 481 TrusteeForm = GetTrusteeFormA(&pListOfExplicitEntriesA[i].Trustee); 482 switch (TrusteeForm) 483 { 484 case TRUSTEE_IS_NAME: 485 { 486 lpStr = GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee); 487 if (lpStr != NULL) 488 { 489 /* convert the trustee name */ 490 BufferSize = strlen(lpStr) + 1; 491 492 if (MultiByteToWideChar(CP_ACP, 493 0, 494 lpStr, 495 -1, 496 StrBuf, 497 BufferSize) == 0) 498 { 499 goto ConvertErr; 500 } 501 peaw[i].Trustee.ptstrName = StrBuf; 502 503 StrBuf += BufferSize; 504 } 505 else 506 goto RawTrusteeCopy; 507 508 break; 509 } 510 511 case TRUSTEE_IS_OBJECTS_AND_NAME: 512 { 513 POBJECTS_AND_NAME_A oanA = (POBJECTS_AND_NAME_A)GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee); 514 515 /* copy over the parts of the TRUSTEE structure that don't need 516 to be touched */ 517 RtlCopyMemory(&peaw[i].Trustee, 518 &pListOfExplicitEntriesA[i].Trustee, 519 FIELD_OFFSET(TRUSTEE_A, 520 ptstrName)); 521 522 peaw[i].Trustee.ptstrName = (LPWSTR)oan; 523 524 /* convert the OBJECTS_AND_NAME_A structure */ 525 oan->ObjectsPresent = oanA->ObjectsPresent; 526 oan->ObjectType = oanA->ObjectType; 527 528 if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) && 529 oanA->InheritedObjectTypeName != NULL) 530 { 531 /* convert inherited object type name */ 532 BufferSize = strlen(oanA->InheritedObjectTypeName) + 1; 533 534 if (MultiByteToWideChar(CP_ACP, 535 0, 536 oanA->InheritedObjectTypeName, 537 -1, 538 StrBuf, 539 BufferSize) == 0) 540 { 541 goto ConvertErr; 542 } 543 oan->InheritedObjectTypeName = StrBuf; 544 545 StrBuf += BufferSize; 546 } 547 else 548 oan->InheritedObjectTypeName = NULL; 549 550 if (oanA->ptstrName != NULL) 551 { 552 /* convert the trustee name */ 553 BufferSize = strlen(oanA->ptstrName) + 1; 554 555 if (MultiByteToWideChar(CP_ACP, 556 0, 557 oanA->ptstrName, 558 -1, 559 StrBuf, 560 BufferSize) == 0) 561 { 562 goto ConvertErr; 563 } 564 oan->ptstrName = StrBuf; 565 566 StrBuf += BufferSize; 567 } 568 else 569 oan->ptstrName = NULL; 570 571 /* move on to the next OBJECTS_AND_NAME_A structure */ 572 oan++; 573 break; 574 } 575 576 default: 577 { 578 RawTrusteeCopy: 579 /* just copy over the TRUSTEE structure, they don't contain any 580 ansi/unicode specific data */ 581 RtlCopyMemory(&peaw[i].Trustee, 582 &pListOfExplicitEntriesA[i].Trustee, 583 sizeof(TRUSTEE_A)); 584 break; 585 } 586 } 587 } 588 589 ASSERT(ErrorCode == ERROR_SUCCESS); 590 *pListOfExplicitEntriesW = peaw; 591 } 592 else 593 ErrorCode = ERROR_NOT_ENOUGH_MEMORY; 594 } 595 596 return ErrorCode; 597 598 ConvertErr: 599 ErrorCode = GetLastError(); 600 601 /* cleanup */ 602 RtlFreeHeap(RtlGetProcessHeap(), 603 0, 604 peaw); 605 606 return ErrorCode; 607 } 608 609 610 /* 611 * @implemented 612 */ 613 DWORD 614 WINAPI 615 SetEntriesInAclA(ULONG cCountOfExplicitEntries, 616 PEXPLICIT_ACCESS_A pListOfExplicitEntries, 617 PACL OldAcl, 618 PACL *NewAcl) 619 { 620 PEXPLICIT_ACCESS_W ListOfExplicitEntriesW = NULL; 621 DWORD ErrorCode; 622 623 ErrorCode = InternalExplicitAccessAToW(cCountOfExplicitEntries, 624 pListOfExplicitEntries, 625 &ListOfExplicitEntriesW); 626 if (ErrorCode == ERROR_SUCCESS) 627 { 628 ErrorCode = SetEntriesInAclW(cCountOfExplicitEntries, 629 ListOfExplicitEntriesW, 630 OldAcl, 631 NewAcl); 632 633 /* free the allocated array */ 634 RtlFreeHeap(RtlGetProcessHeap(), 635 0, 636 ListOfExplicitEntriesW); 637 } 638 639 return ErrorCode; 640 } 641 642 643 /* 644 * @implemented 645 */ 646 DWORD 647 WINAPI 648 GetExplicitEntriesFromAclW(PACL pacl, 649 PULONG pcCountOfExplicitEntries, 650 PEXPLICIT_ACCESS_W *pListOfExplicitEntries) 651 { 652 DWORD ErrorCode; 653 654 ErrorCode = CheckNtMartaPresent(); 655 if (ErrorCode == ERROR_SUCCESS) 656 { 657 /* call the MARTA provider */ 658 ErrorCode = AccRewriteGetExplicitEntriesFromAcl(pacl, 659 pcCountOfExplicitEntries, 660 pListOfExplicitEntries); 661 } 662 663 return ErrorCode; 664 } 665 666 667 /* 668 * @unimplemented 669 */ 670 DWORD 671 WINAPI 672 GetEffectiveRightsFromAclW(IN PACL pacl, 673 IN PTRUSTEE_W pTrustee, 674 OUT PACCESS_MASK pAccessRights) 675 { 676 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights); 677 678 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; 679 return ERROR_SUCCESS; 680 } 681 682 683 /* 684 * @implemented 685 */ 686 DWORD 687 WINAPI 688 GetEffectiveRightsFromAclA(IN PACL pacl, 689 IN PTRUSTEE_A pTrustee, 690 OUT PACCESS_MASK pAccessRights) 691 { 692 PTRUSTEE_W pTrusteeW = NULL; 693 DWORD ErrorCode; 694 695 ErrorCode = InternalTrusteeAToW(pTrustee, 696 &pTrusteeW); 697 if (ErrorCode == ERROR_SUCCESS) 698 { 699 ErrorCode = GetEffectiveRightsFromAclW(pacl, 700 pTrusteeW, 701 pAccessRights); 702 703 InternalFreeConvertedTrustee(pTrusteeW, 704 pTrustee); 705 } 706 else 707 ErrorCode = ERROR_NOT_ENOUGH_MEMORY; 708 709 return ErrorCode; 710 } 711 712 713 /* 714 * @unimplemented 715 */ 716 DWORD 717 WINAPI 718 GetAuditedPermissionsFromAclW(IN PACL pacl, 719 IN PTRUSTEE_W pTrustee, 720 OUT PACCESS_MASK pSuccessfulAuditedRights, 721 OUT PACCESS_MASK pFailedAuditRights) 722 { 723 FIXME("%s() not implemented!\n", __FUNCTION__); 724 return ERROR_CALL_NOT_IMPLEMENTED; 725 } 726 727 728 /* 729 * @implemented 730 */ 731 DWORD 732 WINAPI 733 GetAuditedPermissionsFromAclA(IN PACL pacl, 734 IN PTRUSTEE_A pTrustee, 735 OUT PACCESS_MASK pSuccessfulAuditedRights, 736 OUT PACCESS_MASK pFailedAuditRights) 737 { 738 PTRUSTEE_W pTrusteeW = NULL; 739 DWORD ErrorCode; 740 741 ErrorCode = InternalTrusteeAToW(pTrustee, 742 &pTrusteeW); 743 if (ErrorCode == ERROR_SUCCESS) 744 { 745 ErrorCode = GetAuditedPermissionsFromAclW(pacl, 746 pTrusteeW, 747 pSuccessfulAuditedRights, 748 pFailedAuditRights); 749 750 InternalFreeConvertedTrustee(pTrusteeW, 751 pTrustee); 752 } 753 else 754 ErrorCode = ERROR_NOT_ENOUGH_MEMORY; 755 756 return ErrorCode; 757 } 758 759 /* EOF */ 760