From 6dcbb84d485b8a8ccf0c3a70d9f5f7e951aaf1c6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Dec 2009 17:19:22 -0800 Subject: [PATCH] Attempt to fix one of the last two bugs with the full Windows ACL support. When returning an underlying ACL on a directory, normally on a POSIX system it has no inheritable entries, which breaks the Windows ACL when a user does a get/set of a Windows ACL on a POSIX directory with no existing stored Windows ACL from the Windows ACL editor. What happens is any new entry added by the user gets set inheritable, but none of the others entries are (as returned by default). So any new files then only inherit the single new ACE entry (the one marked inheritable by the ACL editor). Fix this by faking up a default 3 element inheritable ACL that represents what a user creating a POSIX file or directory will get by default from the smbd code. Jeremy. --- source3/modules/vfs_acl_common.c | 106 +++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c index 06bcfb856b1..1eec4480837 100644 --- a/source3/modules/vfs_acl_common.c +++ b/source3/modules/vfs_acl_common.c @@ -156,6 +156,85 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd, return NT_STATUS_OK; } +/******************************************************************* + Add in 3 inheritable components for a non-inheritable directory ACL. + CREATOR_OWNER/CREATOR_GROUP/WORLD. +*******************************************************************/ + +static void add_directory_inheritable_components(vfs_handle_struct *handle, + const char *name, + SMB_STRUCT_STAT *psbuf, + struct security_descriptor *psd) +{ + struct connection_struct *conn = handle->conn; + int num_aces = (psd->dacl ? psd->dacl->num_aces : 0); + struct smb_filename smb_fname; + enum security_ace_type acl_type; + uint32_t access_mask; + mode_t dir_mode; + mode_t file_mode; + mode_t mode; + struct security_ace *new_ace_list = TALLOC_ZERO_ARRAY(talloc_tos(), + struct security_ace, + num_aces + 3); + + if (new_ace_list == NULL) { + return; + } + + /* Fake a quick smb_filename. */ + ZERO_STRUCT(smb_fname); + smb_fname.st = *psbuf; + smb_fname.base_name = CONST_DISCARD(char *, name); + + dir_mode = unix_mode(conn, + FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL); + file_mode = unix_mode(conn, + FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL); + + mode = dir_mode | file_mode; + + DEBUG(10, ("add_directory_inheritable_components: directory %s, " + "mode = 0%o\n", + name, + (unsigned int)mode )); + + if (num_aces) { + memcpy(new_ace_list, psd->dacl->aces, + num_aces * sizeof(struct security_ace)); + } + access_mask = map_canon_ace_perms(SNUM(conn), &acl_type, + mode & 0700, false); + + init_sec_ace(&new_ace_list[num_aces], + &global_sid_Creator_Owner, + acl_type, + access_mask, + SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY); + access_mask = map_canon_ace_perms(SNUM(conn), &acl_type, + (mode << 3) & 0700, false); + init_sec_ace(&new_ace_list[num_aces+1], + &global_sid_Creator_Group, + acl_type, + access_mask, + SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY); + access_mask = map_canon_ace_perms(SNUM(conn), &acl_type, + (mode << 6) & 0700, false); + init_sec_ace(&new_ace_list[num_aces+2], + &global_sid_World, + acl_type, + access_mask, + SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY); + psd->dacl->aces = new_ace_list; + psd->dacl->num_aces += 3; +} + /******************************************************************* Pull a DATA_BLOB from an xattr given a pathname. If the hash doesn't match, or doesn't exist - return the underlying @@ -261,6 +340,33 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle, /* We're returning the blob, throw * away the filesystem SD. */ TALLOC_FREE(pdesc_next); + } else { + SMB_STRUCT_STAT sbuf; + SMB_STRUCT_STAT *psbuf = &sbuf; + bool is_directory = false; + /* + * We're returning the underlying ACL from the + * filesystem. If it's a directory, and has no + * inheritable ACE entries we have to fake them. + */ + if (fsp) { + is_directory = fsp->is_directory; + psbuf = &fsp->fsp_name->st; + } else { + if (vfs_stat_smb_fname(handle->conn, + name, + &sbuf) == 0) { + is_directory = S_ISDIR(sbuf.st_ex_mode); + } + } + if (is_directory && + !sd_has_inheritable_components(psd, + true)) { + add_directory_inheritable_components(handle, + name, + psbuf, + psd); + } } if (!(security_info & OWNER_SECURITY_INFORMATION)) { -- 2.34.1