[SCM] Samba Shared Repository - branch master updated - 7c5f369fafee42b555c3e2b3e3482689b508fe4a

Jeremy Allison jra at samba.org
Wed Oct 29 20:31:04 GMT 2008


The branch, master has been updated
       via  7c5f369fafee42b555c3e2b3e3482689b508fe4a (commit)
       via  7c53ffea28a5752bf28c23b4741ceba77ff1fe1f (commit)
      from  c7dcf7da55224bc2b704d8c86ba4867c251e9eac (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 7c5f369fafee42b555c3e2b3e3482689b508fe4a
Merge: 7c53ffea28a5752bf28c23b4741ceba77ff1fe1f c7dcf7da55224bc2b704d8c86ba4867c251e9eac
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Oct 29 13:27:59 2008 -0700

    Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba

commit 7c53ffea28a5752bf28c23b4741ceba77ff1fe1f
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Oct 29 13:27:14 2008 -0700

    Allow a new file to inherit the Windows ACL from its parent.
    Now to do the same for directories.
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 source3/include/proto.h         |   13 ++-
 source3/lib/secdesc.c           |  194 ++++++++++++++++++++----------
 source3/modules/vfs_acl_xattr.c |  256 ++++++++++++++++++++++++++-------------
 source3/printing/nt_printing.c  |    6 +-
 4 files changed, 319 insertions(+), 150 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index e4a445b..b227a30 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -758,8 +758,17 @@ SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src);
 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size);
 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask);
 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size);
-SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
-				      bool child_container);
+NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
+                                        SEC_DESC **ppsd,
+					size_t *psize,
+                                        const SEC_DESC *parent_ctr,
+                                        const DOM_SID *owner_sid,
+                                        const DOM_SID *group_sid,
+                                        bool container);
+NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
+					SEC_DESC_BUF **ppsdb,
+					const SEC_DESC *parent_ctr,
+					bool container);
 
 /* The following definitions come from lib/select.c  */
 
diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c
index 52ff067..6afc165 100644
--- a/source3/lib/secdesc.c
+++ b/source3/lib/secdesc.c
@@ -429,19 +429,47 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
 	return NT_STATUS_OK;
 }
 
+/*
+ * Determine if an ACE is inheritable
+ */
+
+static bool is_inheritable_ace(const SEC_ACE *ace,
+				bool container)
+{
+	if (!container) {
+		return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
+	}
+
+	if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
+		return true;
+	}
+
+	if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
+			!(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
+		return true;
+	}
+
+	return false;
+}
+
 /* Create a child security descriptor using another security descriptor as
    the parent container.  This child object can either be a container or
    non-container object. */
 
-SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
-				      bool child_container)
+NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
+					SEC_DESC **ppsd,
+					size_t *psize,
+					const SEC_DESC *parent_ctr,
+					const DOM_SID *owner_sid,
+					const DOM_SID *group_sid,
+					bool container)
 {
-	SEC_DESC_BUF *sdb;
-	SEC_DESC *sd;
-	SEC_ACL *new_dacl, *the_acl;
+	SEC_ACL *new_dacl = NULL, *the_acl = NULL;
 	SEC_ACE *new_ace_list = NULL;
 	unsigned int new_ace_list_ndx = 0, i;
-	size_t size;
+
+	*ppsd = NULL;
+	*psize = 0;
 
 	/* Currently we only process the dacl when creating the child.  The
 	   sacl should also be processed but this is left out as sacls are
@@ -450,71 +478,78 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
 	the_acl = parent_ctr->dacl;
 
 	if (the_acl->num_aces) {
-		if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces))) 
-			return NULL;
+		if (2*the_acl->num_aces < the_acl->num_aces) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE,
+						2*the_acl->num_aces))) {
+			return NT_STATUS_NO_MEMORY;
+		}
 	} else {
 		new_ace_list = NULL;
 	}
 
 	for (i = 0; i < the_acl->num_aces; i++) {
-		SEC_ACE *ace = &the_acl->aces[i];
+		const SEC_ACE *ace = &the_acl->aces[i];
 		SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
-		uint8 new_flags = 0;
-		bool inherit = False;
+		const DOM_SID *ptrustee = &ace->trustee;
+		const DOM_SID *creator = NULL;
+		uint8 new_flags = ace->flags;
 
-		/* The OBJECT_INHERIT_ACE flag causes the ACE to be
-		   inherited by non-container children objects.  Container
-		   children objects will inherit it as an INHERIT_ONLY
-		   ACE. */
+		if (!is_inheritable_ace(ace, container)) {
+			continue;
+		}
 
-		if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
+		/* see the RAW-ACLS inheritance test for details on these rules */
+		if (!container) {
+			new_flags = 0;
+		} else {
+			new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
 
-			if (!child_container) {
-				new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
-			} else {
+			if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
 				new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
 			}
-
-			inherit = True;
+			if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
+				new_flags = 0;
+			}
 		}
 
-		/* The CONAINER_INHERIT_ACE flag means all child container
-		   objects will inherit and use the ACE. */
-
-		if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
-			if (!child_container) {
-				inherit = False;
-			} else {
-				new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
-			}
+		/* The CREATOR sids are special when inherited */
+		if (sid_equal(ptrustee, &global_sid_Creator_Owner)) {
+			creator = &global_sid_Creator_Owner;
+			ptrustee = owner_sid;
+		} else if (sid_equal(ptrustee, &global_sid_Creator_Group)) {
+			creator = &global_sid_Creator_Group;
+			ptrustee = group_sid;
 		}
 
-		/* The INHERIT_ONLY_ACE is not used by the se_access_check()
-		   function for the parent container, but is inherited by
-		   all child objects as a normal ACE. */
+		if (creator && container &&
+				(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
 
-		if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
-			/* Move along, nothing to see here */
-		}
+			/* First add the regular ACE entry with flags = 0. */
+			init_sec_ace(new_ace, ptrustee, ace->type,
+			     	ace->access_mask, 0);
 
-		/* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
-		   is inherited by child objects but not grandchildren
-		   objects.  We clear the object inherit and container
-		   inherit flags in the inherited ACE. */
+			DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
+				" inherited as %s:%d/0x%02x/0x%08x\n",
+				sid_string_dbg(&ace->trustee),
+				ace->type, ace->flags, ace->access_mask,
+				sid_string_dbg(&new_ace->trustee),
+				new_ace->type, new_ace->flags,
+				new_ace->access_mask));
 
-		if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
-			new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
-				       SEC_ACE_FLAG_CONTAINER_INHERIT);
-		}
+			new_ace_list_ndx++;
 
-		/* Add ACE to ACE list */
+			/* Now add the extra creator ACE. */
+			new_ace = &new_ace_list[new_ace_list_ndx];
 
-		if (!inherit)
-			continue;
+			ptrustee = creator;
+			new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
+		}
 
-		new_ace->access_mask = ace->access_mask;
-		init_sec_ace(new_ace, &ace->trustee, ace->type,
-			     new_ace->access_mask, new_flags);
+		init_sec_ace(new_ace, ptrustee, ace->type,
+			     ace->access_mask, new_flags);
 
 		DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
 			  " inherited as %s:%d/0x%02x/0x%08x\n",
@@ -528,21 +563,54 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
 	}
 
 	/* Create child security descriptor to return */
-	
-	new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
 
-	/* Use the existing user and group sids.  I don't think this is
-	   correct.  Perhaps the user and group should be passed in as
-	   parameters by the caller? */
+	new_dacl = make_sec_acl(ctx,
+				ACL_REVISION,
+				new_ace_list_ndx,
+				new_ace_list);
 
-	sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
-			   SEC_DESC_SELF_RELATIVE,
-			   parent_ctr->owner_sid,
-			   parent_ctr->group_sid,
-			   parent_ctr->sacl,
-			   new_dacl, &size);
+	if (!new_dacl) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	*ppsd = make_sec_desc(ctx,
+			SECURITY_DESCRIPTOR_REVISION_1,
+			SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
+				SEC_DESC_DACL_DEFAULTED,
+			owner_sid,
+			group_sid,
+			NULL,
+			new_dacl,
+			psize);
+	if (!*ppsd) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	return NT_STATUS_OK;
+}
 
-	sdb = make_sec_desc_buf(ctx, size, sd);
+NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
+					SEC_DESC_BUF **ppsdb,
+					const SEC_DESC *parent_ctr,
+					bool container)
+{
+	NTSTATUS status;
+	size_t size = 0;
+	SEC_DESC *sd = NULL;
+
+	*ppsdb = NULL;
+	status = se_create_child_secdesc(ctx,
+					&sd,
+					&size,
+					parent_ctr,
+					parent_ctr->owner_sid,
+					parent_ctr->group_sid,
+					container);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
 
-	return sdb;
+	*ppsdb = make_sec_desc_buf(ctx, size, sd);
+	if (!*ppsdb) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	return NT_STATUS_OK;
 }
diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c
index 241751c..a802dac 100644
--- a/source3/modules/vfs_acl_xattr.c
+++ b/source3/modules/vfs_acl_xattr.c
@@ -36,7 +36,6 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
 	struct xattr_NTACL xacl;
 	enum ndr_err_code ndr_err;
 	size_t sd_size;
-	struct timespec ts;
 
 	ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
 			(ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
@@ -51,17 +50,29 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
 		return NT_STATUS_REVISION_MISMATCH;
 	}
 
-	/*
-	 * Check that the ctime timestamp is ealier
-	 * than the stored timestamp.
-	 */
-
-	ts = nt_time_to_unix_timespec(&xacl.info.sd_ts->last_changed);
-
-	if (timespec_compare(&cts, &ts) > 0) {
-		DEBUG(5, ("parse_acl_blob: stored ACL out of date.\n"));
-		return NT_STATUS_EA_CORRUPT_ERROR;
+#if 0
+	{
+		struct timespec ts;
+		/* Arg. This doesn't work. Too many activities
+		 * change the ctime. May have to roll back to
+		 * version 1.
+		 */
+		/*
+		 * Check that the ctime timestamp is ealier
+		 * than the stored timestamp.
+		 */
+
+		ts = nt_time_to_unix_timespec(&xacl.info.sd_ts->last_changed);
+
+		if (timespec_compare(&cts, &ts) > 0) {
+			DEBUG(5, ("parse_acl_blob: stored ACL out of date "
+				"(%s > %s.\n",
+				timestring(ctx, cts.tv_sec),
+				timestring(ctx, ts.tv_sec)));
+			return NT_STATUS_EA_CORRUPT_ERROR;
+		}
 	}
+#endif
 
 	*ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
 			(security_info & OWNER_SECURITY_INFORMATION)
@@ -133,6 +144,78 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS create_acl_blob(const SEC_DESC *psd, DATA_BLOB *pblob)
+{
+	struct xattr_NTACL xacl;
+	struct security_descriptor_timestamp sd_ts;
+	enum ndr_err_code ndr_err;
+	TALLOC_CTX *ctx = talloc_tos();
+	struct timespec curr = timespec_current();
+
+	ZERO_STRUCT(xacl);
+	ZERO_STRUCT(sd_ts);
+
+	/* Horrid hack as setting an xattr changes the ctime
+ 	 * on Linux. This gives a race of 1 second during
+ 	 * which we would not see a POSIX ACL set.
+ 	 */
+	curr.tv_sec += 1;
+
+	xacl.version = 2;
+	xacl.info.sd_ts = &sd_ts;
+	xacl.info.sd_ts->sd = CONST_DISCARD(SEC_DESC *, psd);
+	unix_timespec_to_nt_time(&xacl.info.sd_ts->last_changed, curr);
+
+	DEBUG(10, ("create_acl_blob: timestamp stored as %s\n",
+		timestring(ctx, curr.tv_sec) ));
+
+	ndr_err = ndr_push_struct_blob(
+			pblob, ctx, NULL, &xacl,
+			(ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
+
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
+			ndr_errstr(ndr_err)));
+		return ndr_map_error2ntstatus(ndr_err);;
+	}
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS store_acl_blob(files_struct *fsp,
+				DATA_BLOB *pblob)
+{
+	int ret;
+	int saved_errno = 0;
+
+	DEBUG(10,("store_acl_blob: storing blob length %u on file %s\n",
+			(unsigned int)pblob->length, fsp->fsp_name));
+
+	become_root();
+	if (fsp->fh->fd != -1) {
+		ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME,
+			pblob->data, pblob->length, 0);
+	} else {
+		ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name,
+				XATTR_NTACL_NAME,
+				pblob->data, pblob->length, 0);
+	}
+	if (ret) {
+		saved_errno = errno;
+	}
+	unbecome_root();
+	if (ret) {
+		errno = saved_errno;
+		DEBUG(5, ("store_acl_blob: setting attr failed for file %s"
+			"with error %s\n",
+			fsp->fsp_name,
+			strerror(errno) ));
+		return map_nt_error_from_unix(errno);
+	}
+	return NT_STATUS_OK;
+}
+
+
 static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
 					files_struct *fsp,
 					const char *name,
@@ -188,10 +271,72 @@ static int mkdir_acl_xattr(vfs_handle_struct *handle,  const char *path, mode_t
  * inheritance for new files.
 *********************************************************************/
 
-static int open_acl_xattr(vfs_handle_struct *handle,  const char *fname, files_struct *fsp, int flags, mode_t mode)
+static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
+					const char *fname,
+					files_struct *fsp)
+{
+	TALLOC_CTX *ctx = talloc_tos();
+	NTSTATUS status;
+	SEC_DESC *parent_desc = NULL;
+	SEC_DESC *psd = NULL;
+	DATA_BLOB blob;
+	size_t size;
+	char *parent_name;
+
+	if (!parent_dirname_talloc(ctx,
+				fname,
+				&parent_name,
+				NULL)) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	DEBUG(10,("inherit_new_acl: check directory %s\n",
+			parent_name));
+
+	status = get_nt_acl_xattr_internal(handle,
+					NULL,
+					parent_name,
+					DACL_SECURITY_INFORMATION,
+					&parent_desc);
+        if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(10,("inherit_new_acl: directory %s failed "
+			"to get acl %s\n",
+			parent_name,
+			nt_errstr(status) ));
+		return status;
+	}
+
+	/* Create an inherited descriptor from the parent. */
+	status = se_create_child_secdesc(ctx,
+				&psd,
+				&size,
+				parent_desc,
+				&handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
+				&handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
+				false);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+	status = create_acl_blob(psd, &blob);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+	return store_acl_blob(fsp, &blob);
+}
+
+/*********************************************************************
+ Check ACL on open. For new files inherit from parent directory.
+*********************************************************************/
+
+static int open_acl_xattr(vfs_handle_struct *handle,
+					const char *fname,
+					files_struct *fsp,
+					int flags,
+					mode_t mode)
 {
 	uint32_t access_granted = 0;
 	SEC_DESC *pdesc = NULL;
+	bool file_existed = true;
 	NTSTATUS status = get_nt_acl_xattr_internal(handle,
 					NULL,
 					fname,
@@ -209,9 +354,24 @@ static int open_acl_xattr(vfs_handle_struct *handle,  const char *fname, files_s
 			errno = map_errno_from_nt_status(status);
 			return -1;
 		}
-        }
+        } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		file_existed = false;
+	}
+
+	DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
+		"file %s returned %s\n",
+		fname,
+		nt_errstr(status) ));
+
+	fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+
+	if (!file_existed && fsp->fh->fd != -1) {
+		/* File was created. Inherit from parent directory. */
+		string_set(&fsp->fsp_name, fname);
+		inherit_new_acl(handle, fname, fsp);
+	}
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list