Commit 5151c81a authored by Andrey Turkin's avatar Andrey Turkin Committed by Alexandre Julliard

shlwapi: Implement GetShellSecurityDescriptor and test for it.

parent def7df30
......@@ -4453,3 +4453,151 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
}
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
473 stub -noname SHGetIniStringUTF7W
474 stub -noname SHSetIniStringUTF7W
475 stub -noname GetShellSecurityDescriptor
475 stdcall -noname GetShellSecurityDescriptor(ptr long)
476 stub -noname SHGetObjectCompatFlags
477 stub -noname SHCreatePropertyBagOnMemory
478 stdcall -noname IUnknown_TranslateAcceleratorIO(ptr ptr)
......
......@@ -327,6 +327,110 @@ static void test_fdsa(void)
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)
{
hShlwapi = LoadLibraryA("shlwapi.dll");
......@@ -345,6 +449,7 @@ START_TEST(ordinal)
test_SHSearchMapInt();
test_alloc_shared();
test_fdsa();
test_GetShellSecurityDescriptor();
FreeLibrary(hShlwapi);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment