Piotr Caban : advapi32: Add DACL inheritance support in SetSecurityInfo.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Mar 27 08:55:18 CDT 2015
Module: wine
Branch: master
Commit: f974d726720eff4fcd7371bca95e6cdcc4b4a848
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f974d726720eff4fcd7371bca95e6cdcc4b4a848
Author: Piotr Caban <piotr at codeweavers.com>
Date: Fri Mar 27 11:12:04 2015 +0100
advapi32: Add DACL inheritance support in SetSecurityInfo.
---
dlls/advapi32/security.c | 130 ++++++++++++++++++++++++++++++++++++++++-
dlls/advapi32/tests/security.c | 23 ++++----
2 files changed, 139 insertions(+), 14 deletions(-)
diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c
index e8cdcc5..71a8c92 100644
--- a/dlls/advapi32/security.c
+++ b/dlls/advapi32/security.c
@@ -4052,6 +4052,8 @@ DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
}
break;
case SE_FILE_OBJECT:
+ if (SecurityInfo & DACL_SECURITY_INFORMATION)
+ access |= READ_CONTROL;
if (!(err = get_security_file( pObjectName, access, &handle )))
{
err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
@@ -5729,6 +5731,7 @@ DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
PSID psidGroup, PACL pDacl, PACL pSacl)
{
SECURITY_DESCRIPTOR sd;
+ PACL dacl = pDacl;
NTSTATUS status;
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
@@ -5739,7 +5742,130 @@ DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
if (SecurityInfo & GROUP_SECURITY_INFORMATION)
SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
if (SecurityInfo & DACL_SECURITY_INFORMATION)
- SetSecurityDescriptorDacl(&sd, TRUE, pDacl, FALSE);
+ {
+ if (ObjectType == SE_FILE_OBJECT)
+ {
+ SECURITY_DESCRIPTOR_CONTROL control;
+ PSECURITY_DESCRIPTOR psd;
+ OBJECT_NAME_INFORMATION *name_info;
+ DWORD size, rev;
+
+ status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
+ if (status != STATUS_BUFFER_TOO_SMALL)
+ return RtlNtStatusToDosError(status);
+
+ psd = heap_alloc(size);
+ if (!psd)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
+ if (status)
+ {
+ heap_free(psd);
+ return RtlNtStatusToDosError(status);
+ }
+
+ status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
+ heap_free(psd);
+ if (status)
+ return RtlNtStatusToDosError(status);
+ /* TODO: copy some control flags to new sd */
+
+ /* inherit parent directory DACL */
+ if (!(control & SE_DACL_PROTECTED))
+ {
+ status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
+ if (status != STATUS_INFO_LENGTH_MISMATCH)
+ return RtlNtStatusToDosError(status);
+
+ name_info = heap_alloc(size);
+ if (!name_info)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
+ if (status)
+ {
+ heap_free(name_info);
+ return RtlNtStatusToDosError(status);
+ }
+
+ for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
+ if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
+ name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
+ break;
+ if (name_info->Name.Length)
+ {
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+ HANDLE parent;
+ PSECURITY_DESCRIPTOR parent_sd;
+ ACL *parent_dacl;
+ DWORD err = ERROR_ACCESS_DENIED;
+
+ name_info->Name.Buffer[name_info->Name.Length/2] = 0;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.Attributes = 0;
+ attr.ObjectName = &name_info->Name;
+ attr.SecurityDescriptor = NULL;
+ status = NtOpenFile(&parent, READ_CONTROL, &attr, &io,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN_FOR_BACKUP_INTENT);
+ heap_free(name_info);
+ if (!status)
+ {
+ err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, &parent_dacl, NULL, &parent_sd);
+ CloseHandle(parent);
+ }
+
+ if (!err)
+ {
+ int i;
+
+ dacl = heap_alloc_zero(pDacl->AclSize+parent_dacl->AclSize);
+ if (!dacl)
+ {
+ LocalFree(parent_sd);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ memcpy(dacl, pDacl, pDacl->AclSize);
+ dacl->AclSize = pDacl->AclSize+parent_dacl->AclSize;
+
+ for (i=0; i<parent_dacl->AceCount; i++)
+ {
+ ACE_HEADER *ace;
+
+ if (!GetAce(parent_dacl, i, (void*)&ace))
+ continue;
+ if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
+ continue;
+ if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
+ (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
+ {
+ FIXME("unsupported flags: %x\n", ace->AceFlags);
+ continue;
+ }
+
+ if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
+ ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
+ ace->AceFlags &= ~INHERIT_ONLY_ACE;
+ ace->AceFlags |= INHERITED_ACE;
+
+ if(!AddAce(dacl, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
+ WARN("error adding inherited ACE\n");
+ }
+ LocalFree(parent_sd);
+ }
+ }
+ else
+ heap_free(name_info);
+ }
+ }
+
+ SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
+ }
if (SecurityInfo & SACL_SECURITY_INFORMATION)
SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
@@ -5753,6 +5879,8 @@ DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
status = NtSetSecurityObject(handle, SecurityInfo, &sd);
break;
}
+ if (dacl != pDacl)
+ heap_free(dacl);
return RtlNtStatusToDosError(status);
}
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 6d3f9ac..15c3b1d 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3417,25 +3417,22 @@ static void test_GetNamedSecurityInfoA(void)
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
NULL, NULL, &pDacl, NULL, &pSD);
- todo_wine ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
- if (!error)
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ if (acl_size.AceCount > 0)
{
- 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 ACE.\n");
- ok(((ACE_HEADER *)ace)->AceFlags & INHERITED_ACE,
- "ACE has unexpected flags: 0x%x\n", ((ACE_HEADER *)ace)->AceFlags);
- }
- LocalFree(pSD);
+ bret = pGetAce(pDacl, 0, (VOID **)&ace);
+ ok(bret, "Failed to get ACE.\n");
+ todo_wine ok(((ACE_HEADER *)ace)->AceFlags & INHERITED_ACE,
+ "ACE has unexpected flags: 0x%x\n", ((ACE_HEADER *)ace)->AceFlags);
}
+ LocalFree(pSD);
h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
- todo_wine ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
CloseHandle(h);
/* NtSetSecurityObject doesn't inherit DACL entries */
More information about the wine-cvs
mailing list