From: "Erich E. Hoover" <ehoover@mymail.mines.edu>
Subject: [PATCH 4/5] server: Return more security attribute information.
Message-Id: <CAEU2+vogGYKGn9SknKdNqezJdE2+axkSzpujeanxzRwObomLDw@mail.gmail.com>
Date: Thu, 1 Nov 2012 22:44:44 -0600

This patch changes the security information returned for files such
that the group is returned as a separate DACL and the "Local System"
DACL is only returned when any of the "other user" attributes are set.
 Without this patch, and the preceding patch, attempting to load
Netflix will cause an Internet Connection Problem when the loading bar
gets to 99% (Bug #31858).  With this patch in place then Netflix still
doesn't quite work, but it's very close - it will then play about 1
second of audio before stopping due to Bug #31993 (part 5).

From 92b5f7fbe2df018fbd537b9a423112332cfa66fb Mon Sep 17 00:00:00 2001
From: Erich Hoover <ehoover@mines.edu>
Date: Thu, 1 Nov 2012 22:26:35 -0600
Subject: server: Return more security attribute information.

---
 server/file.c |   62 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 44 insertions(+), 18 deletions(-)

diff --git a/server/file.c b/server/file.c
index 3a8c964..06c1dce 100644
--- a/server/file.c
+++ b/server/file.c
@@ -323,11 +323,15 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
     const SID *world_sid = security_world_sid;
     const SID *local_system_sid = security_local_system_sid;
 
-    dacl_size = sizeof(ACL) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
-        FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]);
+    dacl_size = sizeof(ACL);
     if (mode & S_IRWXU)
         dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
             FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
+    if (mode & S_IRWXG)
+        dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
+            FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) +
+            FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
+            FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]);
     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))))
@@ -359,31 +363,21 @@ 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 = (mode & S_IRWXU ? 1 : 0) + (mode & S_IRWXG ? 1 : 0) + (mode & S_IRWXO ? 2 : 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))))
         dacl->AceCount++;
     dacl->Sbz2 = 0;
 
-    /* always give FILE_ALL_ACCESS for Local System */
     aaa = (ACCESS_ALLOWED_ACE *)(dacl + 1);
     current_ace = &aaa->Header;
-    aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
-    aaa->Header.AceFlags = 0;
-    aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
-        FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]);
-    aaa->Mask = FILE_ALL_ACCESS;
-    sid = (SID *)&aaa->SidStart;
-    memcpy( sid, local_system_sid, FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]) );
 
     if (mode & S_IRWXU)
     {
         /* appropriate access rights for the user */
-        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.AceFlags = OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE;
         aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
                               FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
         aaa->Mask = WRITE_DAC | WRITE_OWNER;
@@ -393,14 +387,33 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
             aaa->Mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
         sid = (SID *)&aaa->SidStart;
         memcpy( sid, user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
+        aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
+        current_ace = &aaa->Header;
+    }
+    if (mode & S_IRWXG)
+    {
+        /* appropriate access rights for the group */
+        aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+        aaa->Header.AceFlags = OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE;
+        aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
+                              FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
+        aaa->Mask = WRITE_DAC | WRITE_OWNER;
+        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, FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) );
+        aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
+        current_ace = &aaa->Header;
     }
     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))))
     {
+        ACCESS_DENIED_ACE *ada = (ACCESS_DENIED_ACE *)aaa;
+
         /* deny just in case the user is a member of the group */
-        ACCESS_DENIED_ACE *ada = (ACCESS_DENIED_ACE *)ace_next( current_ace );
-        current_ace = &ada->Header;
         ada->Header.AceType = ACCESS_DENIED_ACE_TYPE;
         ada->Header.AceFlags = 0;
         ada->Header.AceSize = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
@@ -413,12 +426,12 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
         ada->Mask &= ~STANDARD_RIGHTS_ALL; /* never deny standard rights */
         sid = (SID *)&ada->SidStart;
         memcpy( sid, user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
+        aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
+        current_ace = &aaa->Header;
     }
     if (mode & S_IRWXO)
     {
         /* appropriate access rights for Everyone */
-        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) +
@@ -430,6 +443,19 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
             aaa->Mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
         sid = (SID *)&aaa->SidStart;
         memcpy( sid, world_sid, FIELD_OFFSET(SID, SubAuthority[world_sid->SubAuthorityCount]) );
+        aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
+        current_ace = &aaa->Header;
+
+        /* give FILE_ALL_ACCESS for Local System of Everyone has any rights at all */
+        aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+        aaa->Header.AceFlags = 0;
+        aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
+            FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]);
+        aaa->Mask = FILE_ALL_ACCESS;
+        sid = (SID *)&aaa->SidStart;
+        memcpy( sid, local_system_sid, FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]) );
+        aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
+        current_ace = &aaa->Header;
     }
 
     return sd;
-- 
1.7.9.5