[1/2] server: Include group permissions in reported file dacl's.

Vincent Povirk madewokherd at gmail.com
Tue Apr 15 13:29:56 CDT 2014


This requires adding a todo, but that test only passed earlier by
coincidence. It expected 2 entries (current user and Administrators)
and got 2 entries (Local System and current user). Now it gets 3
entries (Local System, current user, and Administrator). So even
though we have an additional todo, I would argue that the new behavior
is closer to what the test expects.

This makes it possible to round-trip file security descriptors and
preserve the group permissions (which we already map to unix file
modes when setting permissions). Office uses this technique to save
over an existing file (by moving a new one on top of it) while
preserving the file's permissions.
-------------- next part --------------
From c5bbd4c5ac0ed87e486c34c342d85d7651ce65f9 Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Mon, 14 Apr 2014 09:58:02 -0500
Subject: [PATCH 1/2] server: Include group permissions in reported file
 dacl's.

---
 dlls/advapi32/tests/security.c |  2 +-
 server/change.c                |  2 +-
 server/file.c                  | 22 ++++++++++++++++++++--
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index bd45189..9960109 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3098,7 +3098,7 @@ static void test_CreateDirectoryA(void)
 
     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
     ok(bret, "GetAclInformation failed\n");
-    ok(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2).\n",
+    todo_wine ok(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2).\n",
                                acl_size.AceCount);
     if (acl_size.AceCount > 0)
     {
diff --git a/server/change.c b/server/change.c
index f6d56b0..213e87d 100644
--- a/server/change.c
+++ b/server/change.c
@@ -298,7 +298,7 @@ static struct security_descriptor *dir_get_sd( struct object *obj )
 
     /* mode and uid the same? if so, no need to re-generate security descriptor */
     if (obj->sd &&
-        (st.st_mode & (S_IRWXU|S_IRWXO)) == (dir->mode & (S_IRWXU|S_IRWXO)) &&
+        (st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) == (dir->mode & (S_IRWXU|S_IRWXG|S_IRWXO)) &&
         (st.st_uid == dir->uid))
         return obj->sd;
 
diff --git a/server/file.c b/server/file.c
index cceb8ad..358adf0 100644
--- a/server/file.c
+++ b/server/file.c
@@ -324,6 +324,8 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
         security_sid_len( local_system_sid );
     if (mode & S_IRWXU)
         dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + security_sid_len( user );
+    if (mode & S_IRWXG)
+        dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + security_sid_len( group );
     if ((!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) ||
         (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) ||
         (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))))
@@ -352,7 +354,7 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
     dacl->AclRevision = ACL_REVISION;
     dacl->Sbz1 = 0;
     dacl->AclSize = dacl_size;
-    dacl->AceCount = 1 + (mode & S_IRWXU ? 1 : 0) + (mode & S_IRWXO ? 1 : 0);
+    dacl->AceCount = 1 + (mode & S_IRWXU ? 1 : 0) + (mode & S_IRWXG ? 1 : 0) + (mode & S_IRWXO ? 1 : 0);
     if ((!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) ||
         (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) ||
         (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))))
@@ -385,6 +387,22 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
         sid = (SID *)&aaa->SidStart;
         memcpy( sid, user, security_sid_len( user ));
     }
+    if (mode & S_IRWXG)
+    {
+        /* appropriate access rights for the group */
+        aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
+        current_ace = &aaa->Header;
+        aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+        aaa->Header.AceFlags = 0;
+        aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + security_sid_len( group );
+        aaa->Mask = 0;
+        if (mode & S_IRGRP)
+            aaa->Mask |= FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
+        if (mode & S_IWGRP)
+            aaa->Mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
+        sid = (SID *)&aaa->SidStart;
+        memcpy( sid, group, security_sid_len( group ));
+    }
     if ((!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) ||
         (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) ||
         (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))))
@@ -439,7 +457,7 @@ static struct security_descriptor *file_get_sd( struct object *obj )
         return obj->sd;
 
     /* mode and uid the same? if so, no need to re-generate security descriptor */
-    if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (file->mode & (S_IRWXU|S_IRWXO)) &&
+    if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) == (file->mode & (S_IRWXU|S_IRWXG|S_IRWXO)) &&
         (st.st_uid == file->uid))
         return obj->sd;
 
-- 
1.8.3.2



More information about the wine-patches mailing list