advapi: Implement GetNamedSecurityInfoW on top of GetSecurityInfo.
This commit is contained in:
parent
5851032d07
commit
722c2b1008
|
@ -5456,9 +5456,12 @@ DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
|
||||||
SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
|
SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
|
||||||
PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
|
PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
|
||||||
{
|
{
|
||||||
DWORD needed, offset;
|
OBJECT_ATTRIBUTES attr;
|
||||||
SECURITY_DESCRIPTOR_RELATIVE *relative = NULL;
|
UNICODE_STRING nameW;
|
||||||
BYTE *buffer;
|
IO_STATUS_BLOCK io;
|
||||||
|
DWORD access = 0;
|
||||||
|
HANDLE hFile;
|
||||||
|
DWORD status;
|
||||||
|
|
||||||
TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
|
TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
|
||||||
group, dacl, sacl, descriptor );
|
group, dacl, sacl, descriptor );
|
||||||
|
@ -5473,85 +5476,28 @@ DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
|
||||||
|| ((info & DACL_SECURITY_INFORMATION) && !dacl)
|
|| ((info & DACL_SECURITY_INFORMATION) && !dacl)
|
||||||
|| ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
|
|| ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
if (!RtlDosPathNameToNtPathName_U( name, &nameW, NULL, NULL ))
|
||||||
|
return ERROR_PATH_NOT_FOUND;
|
||||||
|
|
||||||
needed = !descriptor ? 0 : sizeof(SECURITY_DESCRIPTOR_RELATIVE);
|
if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
|
||||||
if (info & OWNER_SECURITY_INFORMATION)
|
access |= READ_CONTROL;
|
||||||
needed += sizeof(sidWorld);
|
|
||||||
if (info & GROUP_SECURITY_INFORMATION)
|
|
||||||
needed += sizeof(sidWorld);
|
|
||||||
if (info & DACL_SECURITY_INFORMATION)
|
|
||||||
needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
|
|
||||||
if (info & SACL_SECURITY_INFORMATION)
|
if (info & SACL_SECURITY_INFORMATION)
|
||||||
needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
|
access |= ACCESS_SYSTEM_SECURITY;
|
||||||
|
attr.Length = sizeof(attr);
|
||||||
|
attr.RootDirectory = 0;
|
||||||
|
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||||
|
attr.ObjectName = &nameW;
|
||||||
|
attr.SecurityDescriptor = NULL;
|
||||||
|
|
||||||
if(descriptor)
|
status = NtCreateFile( &hFile, access, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
|
||||||
{
|
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
|
||||||
/* must be freed by caller */
|
FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
|
||||||
*descriptor = HeapAlloc( GetProcessHeap(), 0, needed );
|
RtlFreeUnicodeString( &nameW );
|
||||||
if (!*descriptor) return ERROR_NOT_ENOUGH_MEMORY;
|
if (status != STATUS_SUCCESS)
|
||||||
|
return RtlNtStatusToDosError( status );
|
||||||
if (!InitializeSecurityDescriptor( *descriptor, SECURITY_DESCRIPTOR_REVISION ))
|
status = GetSecurityInfo( hFile, type, info, owner, group, dacl, sacl, descriptor );
|
||||||
{
|
CloseHandle( hFile );
|
||||||
HeapFree( GetProcessHeap(), 0, *descriptor );
|
return status;
|
||||||
return ERROR_INVALID_SECURITY_DESCR;
|
|
||||||
}
|
|
||||||
|
|
||||||
relative = *descriptor;
|
|
||||||
relative->Control |= SE_SELF_RELATIVE;
|
|
||||||
|
|
||||||
buffer = (BYTE *)relative;
|
|
||||||
offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer = HeapAlloc( GetProcessHeap(), 0, needed );
|
|
||||||
if (!buffer) return ERROR_NOT_ENOUGH_MEMORY;
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info & OWNER_SECURITY_INFORMATION)
|
|
||||||
{
|
|
||||||
memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
|
|
||||||
if(relative)
|
|
||||||
relative->Owner = offset;
|
|
||||||
if (owner)
|
|
||||||
*owner = buffer + offset;
|
|
||||||
offset += sizeof(sidWorld);
|
|
||||||
}
|
|
||||||
if (info & GROUP_SECURITY_INFORMATION)
|
|
||||||
{
|
|
||||||
memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
|
|
||||||
if(relative)
|
|
||||||
relative->Group = offset;
|
|
||||||
if (group)
|
|
||||||
*group = buffer + offset;
|
|
||||||
offset += sizeof(sidWorld);
|
|
||||||
}
|
|
||||||
if (info & DACL_SECURITY_INFORMATION)
|
|
||||||
{
|
|
||||||
GetWorldAccessACL( (PACL)(buffer + offset) );
|
|
||||||
if(relative)
|
|
||||||
{
|
|
||||||
relative->Control |= SE_DACL_PRESENT;
|
|
||||||
relative->Dacl = offset;
|
|
||||||
}
|
|
||||||
if (dacl)
|
|
||||||
*dacl = (PACL)(buffer + offset);
|
|
||||||
offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
|
|
||||||
}
|
|
||||||
if (info & SACL_SECURITY_INFORMATION)
|
|
||||||
{
|
|
||||||
GetWorldAccessACL( (PACL)(buffer + offset) );
|
|
||||||
if(relative)
|
|
||||||
{
|
|
||||||
relative->Control |= SE_SACL_PRESENT;
|
|
||||||
relative->Sacl = offset;
|
|
||||||
}
|
|
||||||
if (sacl)
|
|
||||||
*sacl = (PACL)(buffer + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
|
|
@ -3005,32 +3005,53 @@ static void test_SetEntriesInAclA(void)
|
||||||
|
|
||||||
static void test_GetNamedSecurityInfoA(void)
|
static void test_GetNamedSecurityInfoA(void)
|
||||||
{
|
{
|
||||||
|
char b[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
|
||||||
|
char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100];
|
||||||
|
DWORD sid_size = sizeof(admin_ptr), l = sizeof(b);
|
||||||
char invalid_path[] = "/an invalid file path";
|
char invalid_path[] = "/an invalid file path";
|
||||||
PSECURITY_DESCRIPTOR pSecDesc;
|
PSID admin_sid = (PSID) admin_ptr, user_sid;
|
||||||
DWORD revision;
|
char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
||||||
SECURITY_DESCRIPTOR_CONTROL control;
|
SECURITY_DESCRIPTOR_CONTROL control;
|
||||||
PSID owner;
|
ACL_SIZE_INFORMATION acl_size;
|
||||||
PSID group;
|
CHAR windows_dir[MAX_PATH];
|
||||||
PACL dacl;
|
PSECURITY_DESCRIPTOR pSD;
|
||||||
|
ACCESS_ALLOWED_ACE *ace;
|
||||||
|
BOOL bret = TRUE, isNT4;
|
||||||
|
char tmpfile[MAX_PATH];
|
||||||
|
DWORD error, revision;
|
||||||
BOOL owner_defaulted;
|
BOOL owner_defaulted;
|
||||||
BOOL group_defaulted;
|
BOOL group_defaulted;
|
||||||
DWORD error;
|
HANDLE token, hTemp;
|
||||||
BOOL ret, isNT4;
|
PSID owner, group;
|
||||||
CHAR windows_dir[MAX_PATH];
|
PACL pDacl;
|
||||||
|
|
||||||
if (!pGetNamedSecurityInfoA || !pSetNamedSecurityInfoA)
|
if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid)
|
||||||
{
|
{
|
||||||
win_skip("[Get|Set]NamedSecurityInfoA is not available\n");
|
win_skip("Required functions are not available\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
|
||||||
ok(ret, "GetWindowsDirectory failed with error %d\n", GetLastError());
|
{
|
||||||
|
if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
|
||||||
|
else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
|
||||||
|
}
|
||||||
|
if (!bret)
|
||||||
|
{
|
||||||
|
win_skip("Failed to get current user token\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GetTokenInformation(token, TokenUser, b, l, &l);
|
||||||
|
CloseHandle( token );
|
||||||
|
user_sid = ((TOKEN_USER *)b)->User.Sid;
|
||||||
|
|
||||||
|
bret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
|
||||||
|
ok(bret, "GetWindowsDirectory failed with error %d\n", GetLastError());
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
|
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
|
||||||
OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
|
OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
|
||||||
NULL, NULL, NULL, NULL, &pSecDesc);
|
NULL, NULL, NULL, NULL, &pSD);
|
||||||
if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
|
if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
|
||||||
{
|
{
|
||||||
win_skip("GetNamedSecurityInfoA is not implemented\n");
|
win_skip("GetNamedSecurityInfoA is not implemented\n");
|
||||||
|
@ -3038,8 +3059,8 @@ static void test_GetNamedSecurityInfoA(void)
|
||||||
}
|
}
|
||||||
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
|
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
|
||||||
|
|
||||||
ret = GetSecurityDescriptorControl(pSecDesc, &control, &revision);
|
bret = GetSecurityDescriptorControl(pSD, &control, &revision);
|
||||||
ok(ret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
|
ok(bret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
|
||||||
ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) ||
|
ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) ||
|
||||||
broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */
|
broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */
|
||||||
"control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
|
"control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
|
||||||
|
@ -3047,14 +3068,14 @@ static void test_GetNamedSecurityInfoA(void)
|
||||||
|
|
||||||
isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT;
|
isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT;
|
||||||
|
|
||||||
ret = GetSecurityDescriptorOwner(pSecDesc, &owner, &owner_defaulted);
|
bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
|
||||||
ok(ret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
|
ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
|
||||||
ok(owner != NULL, "owner should not be NULL\n");
|
ok(owner != NULL, "owner should not be NULL\n");
|
||||||
|
|
||||||
ret = GetSecurityDescriptorGroup(pSecDesc, &group, &group_defaulted);
|
bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
|
||||||
ok(ret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
|
ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
|
||||||
ok(group != NULL, "group should not be NULL\n");
|
ok(group != NULL, "group should not be NULL\n");
|
||||||
LocalFree(pSecDesc);
|
LocalFree(pSD);
|
||||||
|
|
||||||
|
|
||||||
/* NULL descriptor tests */
|
/* NULL descriptor tests */
|
||||||
|
@ -3069,12 +3090,12 @@ static void test_GetNamedSecurityInfoA(void)
|
||||||
ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
|
ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
|
||||||
|
|
||||||
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
|
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
|
||||||
NULL, NULL, &dacl, NULL, NULL);
|
NULL, NULL, &pDacl, NULL, NULL);
|
||||||
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
|
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
|
||||||
ok(dacl != NULL, "dacl should not be NULL\n");
|
ok(pDacl != NULL, "DACL should not be NULL\n");
|
||||||
|
|
||||||
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,
|
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,
|
||||||
NULL, NULL, &dacl, NULL, NULL);
|
NULL, NULL, &pDacl, NULL, NULL);
|
||||||
ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
|
ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
|
||||||
|
|
||||||
/* Test behavior of SetNamedSecurityInfo with an invalid path */
|
/* Test behavior of SetNamedSecurityInfo with an invalid path */
|
||||||
|
@ -3083,6 +3104,70 @@ static void test_GetNamedSecurityInfoA(void)
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error);
|
ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error);
|
||||||
ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n");
|
ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n");
|
||||||
|
|
||||||
|
/* Create security descriptor information and test that it comes back the same */
|
||||||
|
pSD = &sd;
|
||||||
|
pDacl = (PACL)&dacl;
|
||||||
|
InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
|
||||||
|
pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
|
||||||
|
bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION);
|
||||||
|
ok(bret, "Failed to initialize ACL.\n");
|
||||||
|
bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
|
||||||
|
ok(bret, "Failed to add Current User to ACL.\n");
|
||||||
|
bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
|
||||||
|
ok(bret, "Failed to add Administrator Group to ACL.\n");
|
||||||
|
bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
|
||||||
|
ok(bret, "Failed to add ACL to security desciptor.\n");
|
||||||
|
GetTempFileNameA(".", "foo", 0, tmpfile);
|
||||||
|
hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||||
|
FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
|
||||||
|
NULL, pDacl, NULL);
|
||||||
|
if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
|
||||||
|
{
|
||||||
|
win_skip("SetNamedSecurityInfoA is not implemented\n");
|
||||||
|
CloseHandle(hTemp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
|
||||||
|
NULL, NULL, &pDacl, NULL, &pSD);
|
||||||
|
if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
|
||||||
|
{
|
||||||
|
win_skip("GetNamedSecurityInfoA is not implemented\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
|
||||||
|
|
||||||
|
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
|
||||||
|
ok(bret, "GetAclInformation failed\n");
|
||||||
|
if (acl_size.AceCount > 0)
|
||||||
|
{
|
||||||
|
bret = pGetAce(pDacl, 0, (VOID **)&ace);
|
||||||
|
ok(bret, "Failed to get Current User ACE.\n");
|
||||||
|
bret = EqualSid(&ace->SidStart, user_sid);
|
||||||
|
todo_wine ok(bret, "Current User ACE != Current User SID.\n");
|
||||||
|
ok(((ACE_HEADER *)ace)->AceFlags == 0,
|
||||||
|
"Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
|
||||||
|
ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||||||
|
ace->Mask);
|
||||||
|
}
|
||||||
|
if (acl_size.AceCount > 1)
|
||||||
|
{
|
||||||
|
bret = pGetAce(pDacl, 1, (VOID **)&ace);
|
||||||
|
ok(bret, "Failed to get Administators Group ACE.\n");
|
||||||
|
bret = EqualSid(&ace->SidStart, admin_sid);
|
||||||
|
todo_wine ok(bret || broken(!bret) /* win2k */,
|
||||||
|
"Administators Group ACE != Administators Group SID.\n");
|
||||||
|
ok(((ACE_HEADER *)ace)->AceFlags == 0,
|
||||||
|
"Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
|
||||||
|
ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */,
|
||||||
|
"Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||||
|
}
|
||||||
|
LocalFree(pSD);
|
||||||
|
CloseHandle(hTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_ConvertStringSecurityDescriptor(void)
|
static void test_ConvertStringSecurityDescriptor(void)
|
||||||
|
|
Loading…
Reference in New Issue