advapi32: Implement GetExplicitEntriesFromAclW.

Signed-off-by: Vincent Povirk <vincent@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Michael Müller 2017-11-10 15:50:31 -06:00 committed by Alexandre Julliard
parent 9b0c222f39
commit 07b629e8e4
2 changed files with 222 additions and 4 deletions

View file

@ -4211,11 +4211,87 @@ DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntr
/******************************************************************************
* GetExplicitEntriesFromAclW [ADVAPI32.@]
*/
DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
PEXPLICIT_ACCESSW* pListOfExplicitEntries)
DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG count, PEXPLICIT_ACCESSW *list )
{
FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
return ERROR_CALL_NOT_IMPLEMENTED;
ACL_SIZE_INFORMATION sizeinfo;
EXPLICIT_ACCESSW *entries;
MAX_SID *sid_entries;
ACE_HEADER *ace;
NTSTATUS status;
int i;
TRACE("%p %p %p\n",pacl, count, list);
if (!count || !list)
return ERROR_INVALID_PARAMETER;
status = RtlQueryInformationAcl(pacl, &sizeinfo, sizeof(sizeinfo), AclSizeInformation);
if (status) return RtlNtStatusToDosError(status);
if (!sizeinfo.AceCount)
{
*count = 0;
*list = NULL;
return ERROR_SUCCESS;
}
entries = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, (sizeof(EXPLICIT_ACCESSW) + sizeof(MAX_SID)) * sizeinfo.AceCount);
if (!entries) return ERROR_OUTOFMEMORY;
sid_entries = (MAX_SID *)(entries + sizeinfo.AceCount);
for (i = 0; i < sizeinfo.AceCount; i++)
{
status = RtlGetAce(pacl, i, (void**)&ace);
if (status) goto error;
switch (ace->AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
{
ACCESS_ALLOWED_ACE *allow = (ACCESS_ALLOWED_ACE *)ace;
entries[i].grfAccessMode = GRANT_ACCESS;
entries[i].grfInheritance = ace->AceFlags;
entries[i].grfAccessPermissions = allow->Mask;
CopySid(sizeof(MAX_SID), (PSID)&sid_entries[i], (PSID)&allow->SidStart);
entries[i].Trustee.pMultipleTrustee = NULL;
entries[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
entries[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
entries[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
entries[i].Trustee.ptstrName = (WCHAR *)&sid_entries[i];
break;
}
case ACCESS_DENIED_ACE_TYPE:
{
ACCESS_DENIED_ACE *deny = (ACCESS_DENIED_ACE *)ace;
entries[i].grfAccessMode = DENY_ACCESS;
entries[i].grfInheritance = ace->AceFlags;
entries[i].grfAccessPermissions = deny->Mask;
CopySid(sizeof(MAX_SID), (PSID)&sid_entries[i], (PSID)&deny->SidStart);
entries[i].Trustee.pMultipleTrustee = NULL;
entries[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
entries[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
entries[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
entries[i].Trustee.ptstrName = (WCHAR *)&sid_entries[i];
break;
}
default:
FIXME("Unhandled ace type %d\n", ace->AceType);
entries[i].grfAccessMode = NOT_USED_ACCESS;
continue;
}
}
*count = sizeinfo.AceCount;
*list = entries;
return ERROR_SUCCESS;
error:
LocalFree(entries);
return RtlNtStatusToDosError(status);
}
/******************************************************************************

View file

@ -133,6 +133,7 @@ static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);
static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
static PSID_IDENTIFIER_AUTHORITY (WINAPI *pGetSidIdentifierAuthority)(PSID);
static DWORD (WINAPI *pGetExplicitEntriesFromAclW)(PACL,PULONG,PEXPLICIT_ACCESSW*);
static HMODULE hmod;
static int myARGC;
@ -227,6 +228,7 @@ static void init(void)
pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid");
pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority");
pDuplicateTokenEx = (void *)GetProcAddress(hmod, "DuplicateTokenEx");
pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW");
myARGC = winetest_get_mainargs( &myARGV );
}
@ -7098,6 +7100,145 @@ static void test_child_token_sd(void)
HeapFree(GetProcessHeap(), 0, sd);
}
static void test_GetExplicitEntriesFromAclW(void)
{
static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
PSID everyone_sid = NULL, users_sid = NULL;
EXPLICIT_ACCESSW access;
EXPLICIT_ACCESSW *access2;
PACL new_acl, old_acl = NULL;
ULONG count;
DWORD res;
if (!pGetExplicitEntriesFromAclW)
{
win_skip("GetExplicitEntriesFromAclW is not available\n");
return;
}
if (!pSetEntriesInAclW)
{
win_skip("SetEntriesInAclW is not available\n");
return;
}
old_acl = HeapAlloc(GetProcessHeap(), 0, 256);
res = InitializeAcl(old_acl, 256, ACL_REVISION);
if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
win_skip("ACLs not implemented - skipping tests\n");
HeapFree(GetProcessHeap(), 0, old_acl);
return;
}
ok(res, "InitializeAcl failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyone_sid);
ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &users_sid);
ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, users_sid);
ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
access2 = NULL;
res = pGetExplicitEntriesFromAclW(old_acl, &count, &access2);
ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
ok(count == 1, "Expected count == 1, got %d\n", count);
ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
ok(access2[0].grfAccessPermissions == KEY_READ, "Expected KEY_READ, got %d\n", access2[0].grfAccessPermissions);
ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n");
LocalFree(access2);
access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
access.Trustee.pMultipleTrustee = NULL;
access.grfAccessPermissions = KEY_WRITE;
access.grfAccessMode = GRANT_ACCESS;
access.grfInheritance = NO_INHERITANCE;
access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
access.Trustee.ptstrName = everyone_sid;
res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
ok(new_acl != NULL, "returned acl was NULL\n");
access2 = NULL;
res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
ok(count == 2, "Expected count == 2, got %d\n", count);
ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
"Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
LocalFree(access2);
LocalFree(new_acl);
access.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
ok(new_acl != NULL, "returned acl was NULL\n");
access2 = NULL;
res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
ok(count == 2, "Expected count == 2, got %d\n", count);
ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
"Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
LocalFree(access2);
LocalFree(new_acl);
access.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
access.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
ok(new_acl != NULL, "returned acl was NULL\n");
access2 = NULL;
res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
ok(count == 2, "Expected count == 2, got %d\n", count);
ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
"Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
LocalFree(access2);
LocalFree(new_acl);
access.grfAccessMode = REVOKE_ACCESS;
access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
access.Trustee.ptstrName = users_sid;
res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
ok(new_acl != NULL, "returned acl was NULL\n");
access2 = (void *)0xdeadbeef;
res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
ok(count == 0, "Expected count == 0, got %d\n", count);
ok(access2 == NULL, "access2 was not NULL\n");
LocalFree(new_acl);
FreeSid(users_sid);
FreeSid(everyone_sid);
HeapFree(GetProcessHeap(), 0, old_acl);
}
START_TEST(security)
{
init();
@ -7151,6 +7292,7 @@ START_TEST(security)
test_pseudo_tokens();
test_maximum_allowed();
test_token_label();
test_GetExplicitEntriesFromAclW();
/* Must be the last test, modifies process token */
test_token_security_descriptor();