From 9727da326008db5007dee907f55b72a5db99422e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Oct 2002 00:19:56 +0000 Subject: Fix based on Jim McDonough's code for ACL inheritance problem. Jeremy. (This used to be commit a6b3acfc7b98066de6f4b0b6044772a4d56795cd) --- source3/smbd/posix_acls.c | 69 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 9 deletions(-) (limited to 'source3/smbd/posix_acls.c') diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 6b1b62417a..87ebddf35a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -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" . +****************************************************************************/ + +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); -- cgit