Fix based on Jim McDonough's code for ACL inheritance problem.
authorJeremy Allison <jra@samba.org>
Tue, 8 Oct 2002 00:20:17 +0000 (00:20 +0000)
committerJeremy Allison <jra@samba.org>
Tue, 8 Oct 2002 00:20:17 +0000 (00:20 +0000)
Jeremy.
(This used to be commit 3343efaaa8b80d5bc549afebbc06e02e125a6af9)

source3/smbd/posix_acls.c

index 6b1b62417a651585b680e0e1e8b944997b2c6802..87ebddf35a6a3445ea3a49f44d147d4bd995d821 100644 (file)
@@ -1872,6 +1872,45 @@ static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2)
        return 1;
 }
 
+/****************************************************************************
+  Incoming NT ACLs on a directory can be split into a default POSIX acl (CI|OI|IO) and
+  a normal POSIX acl. Win2k needs these split acls re-merging into one ACL
+  with CI|OI set so it is inherited and also applies to the directory.
+  Based on code from "Jim McDonough" <jmcd@us.ibm.com>.
+****************************************************************************/
+
+static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces)
+{
+       size_t i, j;
+
+       for (i = 0; i < num_aces; i++) {
+               for (j = i+1; j < num_aces; j++) {
+                       /* We know the lower number ACE's are file entries. */
+                       if ((nt_ace_list[i].type == nt_ace_list[j].type) &&
+                               (nt_ace_list[i].size == nt_ace_list[j].size) &&
+                               (nt_ace_list[i].info.mask == nt_ace_list[j].info.mask) &&
+                               sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) &&
+                               (nt_ace_list[i].flags == 0) &&
+                               (nt_ace_list[j].flags == (SEC_ACE_FLAG_OBJECT_INHERIT|
+                                                         SEC_ACE_FLAG_CONTAINER_INHERIT|
+                                                         SEC_ACE_FLAG_INHERIT_ONLY))) {
+                               /*
+                                * These are identical except for the flags.
+                                * Merge the inherited ACE onto the non-inherited ACE.
+                                */
+
+                               nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT;
+                               if (num_aces - j - 1 > 0)
+                                       memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) *
+                                                       sizeof(SEC_ACE));
+                               num_aces--;
+                               break;
+                       }
+               }
+       }
+
+       return num_aces;
+}
 /****************************************************************************
  Reply to query a security descriptor from an fsp. If it succeeds it allocates
  the space for the return elements and returns the size needed to return the
@@ -1978,7 +2017,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
                goto done;
        }
 
-       memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) );
+       memset(nt_ace_list, '\0', (num_acls + num_profile_acls + num_dir_acls) * sizeof(SEC_ACE) );
 
        /*
         * Create the NT ACE list from the canonical ace lists.
@@ -2020,15 +2059,23 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
                                        SEC_ACE_FLAG_INHERIT_ONLY);
                }
 
+               /*
+                * Merge POSIX default ACLs and normal ACLs into one NT ACE.
+                * Win2K needs this to get the inheritance correct when replacing ACLs
+                * on a directory tree. Based on work by Jim @ IBM.
+                */
+
+               num_aces = merge_default_aces(nt_ace_list, num_aces);
+
                /*
                 * Sort to force deny entries to the front.
                 */
 
-               if (num_acls + num_dir_acls)
-                       qsort( nt_ace_list, num_acls + num_dir_acls, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp);
+               if (num_aces)
+                       qsort( nt_ace_list, num_aces, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp);
        }
 
-       if (num_acls) {
+       if (num_aces) {
                if((psa = make_sec_acl( main_loop_talloc_get(), ACL_REVISION, num_aces, nt_ace_list)) == NULL) {
                        DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n"));
                        goto done;
@@ -2055,14 +2102,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
        return sd_size;
 }
 
-/*
-  try to chown a file. We will be able to chown it under the following conditions
+/****************************************************************************
+ Try to chown a file. We will be able to chown it under the following conditions.
 
-  1) if we have root privileges, then it will just work
-  2) if we have write permission to the file and dos_filemodes is set
+  1) If we have root privileges, then it will just work.
+  2) If we have write permission to the file and dos_filemodes is set
      then allow chown to the currently authenticated user.
+****************************************************************************/
 
- */
 static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
 {
        int ret;
@@ -2409,6 +2456,10 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode)
        return ret;
 }
 
+/****************************************************************************
+ Check for an existing default POSIX ACL on a directory.
+****************************************************************************/
+
 BOOL directory_has_default_acl(connection_struct *conn, const char *fname)
 {
         SMB_ACL_T dir_acl = conn->vfs_ops.sys_acl_get_file( conn, fname, SMB_ACL_TYPE_DEFAULT);