2017-06-15 20:16:10 -07:00
|
|
|
From cd5f99efd824965d92bd8491afd0c6e6d7bdc118 Mon Sep 17 00:00:00 2001
|
2016-08-28 17:51:46 -07:00
|
|
|
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
|
|
|
Date: Sun, 28 Aug 2016 21:56:41 +0200
|
|
|
|
Subject: advapi32: Implement GetExplicitEntriesFromAclW.
|
|
|
|
|
|
|
|
---
|
|
|
|
dlls/advapi32/security.c | 81 ++++++++++++++++++++++-
|
|
|
|
dlls/advapi32/tests/security.c | 142 +++++++++++++++++++++++++++++++++++++++++
|
|
|
|
2 files changed, 221 insertions(+), 2 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c
|
2017-06-15 20:16:10 -07:00
|
|
|
index e36792cff4..b305947347 100644
|
2016-08-28 17:51:46 -07:00
|
|
|
--- a/dlls/advapi32/security.c
|
|
|
|
+++ b/dlls/advapi32/security.c
|
2017-06-15 20:16:10 -07:00
|
|
|
@@ -4205,8 +4205,85 @@ DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntr
|
2016-08-28 17:51:46 -07:00
|
|
|
DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
|
|
|
|
PEXPLICIT_ACCESSW* pListOfExplicitEntries)
|
|
|
|
{
|
|
|
|
- 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;
|
|
|
|
+
|
|
|
|
+ FIXME("%p %p %p: semi-stub\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
|
|
|
|
+
|
|
|
|
+ if (!pcCountOfExplicitEntries || !pListOfExplicitEntries)
|
|
|
|
+ return ERROR_INVALID_PARAMETER;
|
|
|
|
+
|
|
|
|
+ status = RtlQueryInformationAcl(pacl, &sizeinfo, sizeof(sizeinfo), AclSizeInformation);
|
|
|
|
+ if (status) return RtlNtStatusToDosError(status);
|
|
|
|
+
|
|
|
|
+ if (!sizeinfo.AceCount)
|
|
|
|
+ {
|
|
|
|
+ *pcCountOfExplicitEntries = 0;
|
|
|
|
+ *pListOfExplicitEntries = 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*)((char*)entries + sizeof(EXPLICIT_ACCESSW) * 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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *pcCountOfExplicitEntries = sizeinfo.AceCount;
|
|
|
|
+ *pListOfExplicitEntries = entries;
|
|
|
|
+ return ERROR_SUCCESS;
|
|
|
|
+
|
|
|
|
+error:
|
|
|
|
+ LocalFree(entries);
|
|
|
|
+ return RtlNtStatusToDosError(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
2017-06-15 20:16:10 -07:00
|
|
|
index 09c6a721cc..286d236e4b 100644
|
2016-08-28 17:51:46 -07:00
|
|
|
--- a/dlls/advapi32/tests/security.c
|
|
|
|
+++ b/dlls/advapi32/tests/security.c
|
2017-06-15 20:16:10 -07:00
|
|
|
@@ -134,6 +134,7 @@ static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);
|
2016-08-28 17:51:46 -07:00
|
|
|
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;
|
2017-06-15 20:16:10 -07:00
|
|
|
@@ -230,6 +231,7 @@ static void init(void)
|
2016-08-28 17:51:46 -07:00
|
|
|
pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid");
|
|
|
|
pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority");
|
2017-06-15 20:16:10 -07:00
|
|
|
pDuplicateTokenEx = (void *)GetProcAddress(hmod, "DuplicateTokenEx");
|
2016-08-28 17:51:46 -07:00
|
|
|
+ pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW");
|
|
|
|
|
|
|
|
myARGC = winetest_get_mainargs( &myARGV );
|
|
|
|
}
|
2017-06-15 20:16:10 -07:00
|
|
|
@@ -6795,6 +6797,145 @@ static void test_token_security_descriptor(void)
|
|
|
|
CloseHandle(token);
|
2016-08-28 17:51:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
+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();
|
2017-06-15 20:16:10 -07:00
|
|
|
@@ -6845,4 +6986,5 @@ START_TEST(security)
|
2016-08-28 17:51:46 -07:00
|
|
|
test_pseudo_tokens();
|
2017-02-14 08:01:29 -08:00
|
|
|
test_maximum_allowed();
|
2017-06-15 20:16:10 -07:00
|
|
|
test_token_security_descriptor();
|
2016-08-28 17:51:46 -07:00
|
|
|
+ test_GetExplicitEntriesFromAclW();
|
|
|
|
}
|
|
|
|
--
|
2017-06-15 20:16:10 -07:00
|
|
|
2.13.1
|
2016-08-28 17:51:46 -07:00
|
|
|
|