summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/posix_acls.c69
1 files changed, 60 insertions, 9 deletions
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
@@ -1873,6 +1873,45 @@ static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2)
}
/****************************************************************************
+ 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
security descriptor. This should be the only external function needed for
@@ -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.
@@ -2021,14 +2060,22 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
}
/*
+ * 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);