summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-12-23 17:19:22 -0800
committerJeremy Allison <jra@samba.org>2009-12-23 17:19:22 -0800
commit6dcbb84d485b8a8ccf0c3a70d9f5f7e951aaf1c6 (patch)
tree02dd86f6643a7da76c01c3d37cb6e25677532499 /source3
parent3d85b1ebe5e3484250b6810f1a45c1ba5a4900f7 (diff)
downloadsamba-6dcbb84d485b8a8ccf0c3a70d9f5f7e951aaf1c6.tar.gz
samba-6dcbb84d485b8a8ccf0c3a70d9f5f7e951aaf1c6.tar.bz2
samba-6dcbb84d485b8a8ccf0c3a70d9f5f7e951aaf1c6.zip
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.
Diffstat (limited to 'source3')
-rw-r--r--source3/modules/vfs_acl_common.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c
index 06bcfb856b..1eec448083 100644
--- a/source3/modules/vfs_acl_common.c
+++ b/source3/modules/vfs_acl_common.c
@@ -157,6 +157,85 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
}
/*******************************************************************
+ 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
filesystem sd.
@@ -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)) {