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