shlwapi: Implement GetShellSecurityDescriptor and test for it.
This commit is contained in:
parent
def7df305e
commit
5151c81a23
|
@ -4453,3 +4453,151 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
|
||||||
}
|
}
|
||||||
fn(wEventId, uFlags, dwItem1, dwItem2);
|
fn(wEventId, uFlags, dwItem1, dwItem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
|
||||||
|
SID_IDENTIFIER_AUTHORITY sidAuthority;
|
||||||
|
DWORD dwUserGroupID;
|
||||||
|
DWORD dwUserID;
|
||||||
|
} SHELL_USER_SID, *PSHELL_USER_SID;
|
||||||
|
|
||||||
|
typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
|
||||||
|
SHELL_USER_SID susID;
|
||||||
|
DWORD dwAccessType;
|
||||||
|
BOOL fInherit;
|
||||||
|
DWORD dwAccessMask;
|
||||||
|
DWORD dwInheritMask;
|
||||||
|
DWORD dwInheritAccessMask;
|
||||||
|
} SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetShellSecurityDescriptor [SHLWAPI.475]
|
||||||
|
*
|
||||||
|
* prepares SECURITY_DESCRIPTOR from a set of ACEs
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
|
||||||
|
* each of which describes permissions to apply
|
||||||
|
* cUserPerm [I] number of entries in apUserPerm array
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* success: pointer to SECURITY_DESCRIPTOR
|
||||||
|
* failure: NULL
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* Call should free returned descriptor with LocalFree
|
||||||
|
*/
|
||||||
|
SECURITY_DESCRIPTOR * WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
|
||||||
|
{
|
||||||
|
PSID *sidlist;
|
||||||
|
PSID cur_user = NULL;
|
||||||
|
BYTE tuUser[2000];
|
||||||
|
DWORD acl_size;
|
||||||
|
int sid_count, i;
|
||||||
|
PSECURITY_DESCRIPTOR psd = NULL;
|
||||||
|
|
||||||
|
TRACE("%p %d\n", apUserPerm, cUserPerm);
|
||||||
|
|
||||||
|
if (apUserPerm == NULL || cUserPerm <= 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
|
||||||
|
if (!sidlist)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
acl_size = sizeof(ACL);
|
||||||
|
|
||||||
|
for(sid_count = 0; sid_count < cUserPerm; sid_count++)
|
||||||
|
{
|
||||||
|
static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
|
||||||
|
PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
|
||||||
|
PSHELL_USER_SID sid = &perm->susID;
|
||||||
|
PSID pSid;
|
||||||
|
BOOL ret = TRUE;
|
||||||
|
|
||||||
|
if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
|
||||||
|
{ /* current user's SID */
|
||||||
|
if (!cur_user)
|
||||||
|
{
|
||||||
|
HANDLE Token;
|
||||||
|
DWORD bufsize = sizeof(tuUser);
|
||||||
|
|
||||||
|
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
|
||||||
|
if (ret)
|
||||||
|
cur_user = ((PTOKEN_USER)&tuUser)->User.Sid;
|
||||||
|
CloseHandle(Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pSid = cur_user;
|
||||||
|
} else if (sid->dwUserID==0) /* one sub-authority */
|
||||||
|
ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, &pSid);
|
||||||
|
else
|
||||||
|
ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
|
||||||
|
0, 0, 0, 0, 0, 0, &pSid);
|
||||||
|
if (!ret)
|
||||||
|
goto free_sids;
|
||||||
|
|
||||||
|
sidlist[sid_count] = pSid;
|
||||||
|
/* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
|
||||||
|
acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
|
||||||
|
|
||||||
|
if (psd != NULL)
|
||||||
|
{
|
||||||
|
PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
|
||||||
|
|
||||||
|
if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(i = 0; i < sid_count; i++)
|
||||||
|
{
|
||||||
|
PSHELL_USER_PERMISSION sup = apUserPerm[i];
|
||||||
|
PSID sid = sidlist[i];
|
||||||
|
|
||||||
|
switch(sup->dwAccessType)
|
||||||
|
{
|
||||||
|
case ACCESS_ALLOWED_ACE_TYPE:
|
||||||
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
|
||||||
|
goto error;
|
||||||
|
if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
|
||||||
|
(BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
case ACCESS_DENIED_ACE_TYPE:
|
||||||
|
if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
|
||||||
|
goto error;
|
||||||
|
if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
|
||||||
|
(BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
goto free_sids;
|
||||||
|
|
||||||
|
error:
|
||||||
|
LocalFree(psd);
|
||||||
|
psd = NULL;
|
||||||
|
free_sids:
|
||||||
|
for(i = 0; i < sid_count; i++)
|
||||||
|
{
|
||||||
|
if (!cur_user || sidlist[i] != cur_user)
|
||||||
|
FreeSid(sidlist[i]);
|
||||||
|
}
|
||||||
|
HeapFree(GetProcessHeap(), 0, sidlist);
|
||||||
|
|
||||||
|
return psd;
|
||||||
|
}
|
||||||
|
|
|
@ -472,7 +472,7 @@
|
||||||
472 stub -noname SHCreatePropertyBagOnProfileSelections
|
472 stub -noname SHCreatePropertyBagOnProfileSelections
|
||||||
473 stub -noname SHGetIniStringUTF7W
|
473 stub -noname SHGetIniStringUTF7W
|
||||||
474 stub -noname SHSetIniStringUTF7W
|
474 stub -noname SHSetIniStringUTF7W
|
||||||
475 stub -noname GetShellSecurityDescriptor
|
475 stdcall -noname GetShellSecurityDescriptor(ptr long)
|
||||||
476 stub -noname SHGetObjectCompatFlags
|
476 stub -noname SHGetObjectCompatFlags
|
||||||
477 stub -noname SHCreatePropertyBagOnMemory
|
477 stub -noname SHCreatePropertyBagOnMemory
|
||||||
478 stdcall -noname IUnknown_TranslateAcceleratorIO(ptr ptr)
|
478 stdcall -noname IUnknown_TranslateAcceleratorIO(ptr ptr)
|
||||||
|
|
|
@ -327,6 +327,110 @@ static void test_fdsa(void)
|
||||||
HeapFree(GetProcessHeap(), 0, mem);
|
HeapFree(GetProcessHeap(), 0, mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct SHELL_USER_SID {
|
||||||
|
SID_IDENTIFIER_AUTHORITY sidAuthority;
|
||||||
|
DWORD dwUserGroupID;
|
||||||
|
DWORD dwUserID;
|
||||||
|
} SHELL_USER_SID, *PSHELL_USER_SID;
|
||||||
|
typedef struct SHELL_USER_PERMISSION {
|
||||||
|
SHELL_USER_SID susID;
|
||||||
|
DWORD dwAccessType;
|
||||||
|
BOOL fInherit;
|
||||||
|
DWORD dwAccessMask;
|
||||||
|
DWORD dwInheritMask;
|
||||||
|
DWORD dwInheritAccessMask;
|
||||||
|
} SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
|
||||||
|
static void test_GetShellSecurityDescriptor(void)
|
||||||
|
{
|
||||||
|
SHELL_USER_PERMISSION supCurrentUserFull = {
|
||||||
|
{ {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
|
||||||
|
ACCESS_ALLOWED_ACE_TYPE, FALSE,
|
||||||
|
GENERIC_ALL, 0, 0 };
|
||||||
|
#define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
|
||||||
|
SHELL_USER_PERMISSION supEveryoneDenied = {
|
||||||
|
{ {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
|
||||||
|
ACCESS_DENIED_ACE_TYPE, TRUE,
|
||||||
|
GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
|
||||||
|
PSHELL_USER_PERMISSION rgsup[2] = {
|
||||||
|
&supCurrentUserFull, &supEveryoneDenied,
|
||||||
|
};
|
||||||
|
SECURITY_DESCRIPTOR* psd;
|
||||||
|
SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
|
||||||
|
|
||||||
|
pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
|
||||||
|
|
||||||
|
psd = pGetShellSecurityDescriptor(NULL, 2);
|
||||||
|
ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
|
||||||
|
psd = pGetShellSecurityDescriptor(rgsup, 0);
|
||||||
|
ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
|
||||||
|
|
||||||
|
psd = pGetShellSecurityDescriptor(rgsup, 2);
|
||||||
|
ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
|
||||||
|
if (psd!=NULL)
|
||||||
|
{
|
||||||
|
BOOL bHasDacl = FALSE, bDefaulted;
|
||||||
|
PACL pAcl;
|
||||||
|
DWORD dwRev;
|
||||||
|
SECURITY_DESCRIPTOR_CONTROL control;
|
||||||
|
|
||||||
|
ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
|
||||||
|
|
||||||
|
ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
|
||||||
|
"GetSecurityDescriptorControl failed with error %d\n", GetLastError());
|
||||||
|
ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
|
||||||
|
|
||||||
|
ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
|
||||||
|
"GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
|
||||||
|
|
||||||
|
ok(bHasDacl, "SD has no DACL\n");
|
||||||
|
if (bHasDacl)
|
||||||
|
{
|
||||||
|
ok(!bDefaulted, "DACL should not be defaulted\n");
|
||||||
|
|
||||||
|
ok(pAcl != NULL, "NULL DACL!\n");
|
||||||
|
if (pAcl != NULL)
|
||||||
|
{
|
||||||
|
ACL_SIZE_INFORMATION asiSize;
|
||||||
|
|
||||||
|
ok(IsValidAcl(pAcl), "DACL is not valid\n");
|
||||||
|
|
||||||
|
ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
|
||||||
|
"GetAclInformation failed with error %d\n", GetLastError());
|
||||||
|
|
||||||
|
ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
|
||||||
|
if (asiSize.AceCount == 3)
|
||||||
|
{
|
||||||
|
ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
|
||||||
|
|
||||||
|
ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %d\n", GetLastError());
|
||||||
|
ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
|
||||||
|
"Invalid ACE type %d\n", paaa->Header.AceType);
|
||||||
|
ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
|
||||||
|
ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
|
||||||
|
|
||||||
|
ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %d\n", GetLastError());
|
||||||
|
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
|
||||||
|
"Invalid ACE type %d\n", paaa->Header.AceType);
|
||||||
|
/* first one of two ACEs generated from inheritable entry - without inheritance */
|
||||||
|
ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
|
||||||
|
ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
|
||||||
|
|
||||||
|
ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %d\n", GetLastError());
|
||||||
|
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
|
||||||
|
"Invalid ACE type %d\n", paaa->Header.AceType);
|
||||||
|
/* second ACE - with inheritance */
|
||||||
|
ok(paaa->Header.AceFlags == MY_INHERITANCE,
|
||||||
|
"Invalid ACE flags %x\n", paaa->Header.AceFlags);
|
||||||
|
ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFree(psd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(ordinal)
|
START_TEST(ordinal)
|
||||||
{
|
{
|
||||||
hShlwapi = LoadLibraryA("shlwapi.dll");
|
hShlwapi = LoadLibraryA("shlwapi.dll");
|
||||||
|
@ -345,6 +449,7 @@ START_TEST(ordinal)
|
||||||
test_SHSearchMapInt();
|
test_SHSearchMapInt();
|
||||||
test_alloc_shared();
|
test_alloc_shared();
|
||||||
test_fdsa();
|
test_fdsa();
|
||||||
|
test_GetShellSecurityDescriptor();
|
||||||
|
|
||||||
FreeLibrary(hShlwapi);
|
FreeLibrary(hShlwapi);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue