[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Sat Oct 17 14:15:30 MDT 2009


The branch, master has been updated
       via  0463d69... s4-pvfs: change the handling of access checking on create
       via  d1efaf3... smb2-torture: samba4 allows SEC_FLAG_SECURITY to be used with privileges
       via  a319ba4... s4: fixed howto for new binary name
      from  d6351ad... Fix the smbtorture4 build. root_fid is a "union smb_handle". tridge please check. Jeremy.

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


- Log -----------------------------------------------------------------
commit 0463d698835053af680db4f388c732d2557f7c8a
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Oct 17 21:17:29 2009 +1100

    s4-pvfs: change the handling of access checking on create
    
    Previously when a file was created, we produces the resulting access
    mask based on an ACL check against the parent. This change means we
    now calculate the inherited ACL much earlier, and produce the
    resulting access mask from that ACL, or the user supplied ACL.

commit d1efaf39f51102835eda9aca12433e926354da77
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Oct 17 21:14:59 2009 +1100

    smb2-torture: samba4 allows SEC_FLAG_SECURITY to be used with privileges

commit a319ba49e79fdc6ed37996d185aece5dbb5a905e
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Oct 17 20:10:03 2009 +1100

    s4: fixed howto for new binary name

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

Summary of changes:
 howto4.txt                             |   10 +-
 source4/ntvfs/posix/pvfs_acl.c         |  149 ++++++++++++++++++++++----------
 source4/ntvfs/posix/pvfs_open.c        |   22 +++---
 source4/ntvfs/posix/pvfs_resolve.c     |   11 ++-
 source4/ntvfs/posix/pvfs_setfileinfo.c |    2 +-
 source4/torture/smb2/create.c          |    2 +
 6 files changed, 131 insertions(+), 65 deletions(-)


Changeset truncated at 500 lines:

diff --git a/howto4.txt b/howto4.txt
index 3ae225d..3ae5af1 100644
--- a/howto4.txt
+++ b/howto4.txt
@@ -101,18 +101,18 @@ example::
 Step 6: starting Samba4
 -----------------------
 
-The simplest is to just run "smbd", but as a developer you may find
+The simplest is to just run "samba", but as a developer you may find
 the following more useful::
 
-   # smbd -i -M single
+   # samba -i -M single
 
-that means "start smbd without messages in stdout, and running a
-single process. That mode of operation makes debugging smbd with gdb
+that means "start samba without messages in stdout, and running a
+single process. That mode of operation makes debugging samba with gdb
 particularly easy.
 
 Note that now it is no longer necessary to have an instance of nmbd
 from Samba 3 running.  If you are running any smbd or nmbd processes
-they need to be stopped before starting smbd from Samba 4.
+they need to be stopped before starting samba from Samba 4.
 
 Make sure you put the bin and sbin directories from your new install
 in your $PATH. Make sure you run the right version!
diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c
index 26515cf..842aced 100644
--- a/source4/ntvfs/posix/pvfs_acl.c
+++ b/source4/ntvfs/posix/pvfs_acl.c
@@ -485,6 +485,8 @@ static bool pvfs_group_member(struct pvfs_state *pvfs, gid_t gid)
   doing this saves on building a full security descriptor
   for the common case of access check on files with no 
   specific NT ACL
+
+  If name is NULL then treat as a new file creation
 */
 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 
 				struct ntvfs_request *req,
@@ -499,13 +501,14 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	if (uid == name->st.st_uid) {
+	if (name == NULL || uid == name->st.st_uid) {
 		max_bits |= SEC_STD_ALL;
 	} else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
 		max_bits |= SEC_STD_DELETE;
 	}
 
-	if ((name->st.st_mode & S_IWOTH) ||
+	if (name == NULL ||
+	    (name->st.st_mode & S_IWOTH) ||
 	    ((name->st.st_mode & S_IWGRP) && 
 	     pvfs_group_member(pvfs, name->st.st_gid))) {
 		max_bits |= SEC_STD_ALL;
@@ -540,7 +543,7 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
 
 	if (*access_mask & ~max_bits) {
 		DEBUG(0,(__location__ " denied access to '%s' - wanted 0x%08x but got 0x%08x (missing 0x%08x)\n",
-			 name->full_name, *access_mask, max_bits, *access_mask & ~max_bits));
+			 name?name->full_name:"(new file)", *access_mask, max_bits, *access_mask & ~max_bits));
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
@@ -643,26 +646,47 @@ NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
 				  struct ntvfs_request *req,
 				  struct pvfs_filename *name,
-				  uint32_t *access_mask)
+				  uint32_t *access_mask,
+				  bool container,
+				  struct security_descriptor **sd)
 {
 	struct pvfs_filename *parent;
 	NTSTATUS status;
+	struct security_token *token = req->session_info->security_token;
+
+	if (pvfs_read_only(pvfs, *access_mask)) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
 
 	status = pvfs_resolve_parent(pvfs, req, name, &parent);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
 
-	status = pvfs_access_check(pvfs, req, parent, access_mask);
+	status = pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
 
-	if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
-		return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
+	if (*sd == NULL) {
+		status = pvfs_acl_inherited_sd(pvfs, req, req, parent, container, sd);
 	}
 
-	return status;
+	talloc_free(parent);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	/* expand the generic access bits to file specific bits */
+	*access_mask = pvfs_translate_mask(*access_mask);
+	if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
+		*access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
+	}
+
+	if (*sd == NULL) {
+		return pvfs_access_check_unix(pvfs, req, NULL, access_mask);
+	}
+	return sec_access_check(*sd, token, *access_mask, access_mask);
 }
 
 /*
@@ -790,47 +814,42 @@ static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
 
 
 /*
-  setup an ACL on a new file/directory based on the inherited ACL from
-  the parent. If there is no inherited ACL then we don't set anything,
-  as the default ACL applies anyway
+  calculate the ACL on a new file/directory based on the inherited ACL
+  from the parent. If there is no inherited ACL then return a NULL
+  ACL, which means the default ACL should be used
 */
-NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
-			  struct ntvfs_request *req,
-			  struct pvfs_filename *name,
-			  int fd)
+NTSTATUS pvfs_acl_inherited_sd(struct pvfs_state *pvfs, 
+			       TALLOC_CTX *mem_ctx,
+			       struct ntvfs_request *req,
+			       struct pvfs_filename *parent,
+			       bool container,
+			       struct security_descriptor **ret_sd)
 {
 	struct xattr_NTACL *acl;
 	NTSTATUS status;
-	struct pvfs_filename *parent;
 	struct security_descriptor *parent_sd, *sd;
-	bool container;
 	struct id_mapping *ids;
 	struct composite_context *ctx;
+	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 
-	/* form the parents path */
-	status = pvfs_resolve_parent(pvfs, req, name, &parent);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
+	*ret_sd = NULL;
 
 	acl = talloc(req, struct xattr_NTACL);
-	if (acl == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
+	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(acl, tmp_ctx);
 
 	status = pvfs_acl_load(pvfs, parent, -1, acl);
 	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+		talloc_free(tmp_ctx);
 		return NT_STATUS_OK;
 	}
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
+	NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
 
 	switch (acl->version) {
 	case 1:
 		parent_sd = acl->info.sd;
 		break;
 	default:
+		talloc_free(tmp_ctx);
 		return NT_STATUS_INVALID_ACL;
 	}
 
@@ -838,61 +857,99 @@ NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
 	    parent_sd->dacl == NULL ||
 	    parent_sd->dacl->num_aces == 0) {
 		/* go with the default ACL */
+		talloc_free(tmp_ctx);
 		return NT_STATUS_OK;
 	}
 
 	/* create the new sd */
 	sd = security_descriptor_initialise(req);
-	if (sd == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
+	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sd, tmp_ctx);
 
 	ids = talloc_array(sd, struct id_mapping, 2);
-	NT_STATUS_HAVE_NO_MEMORY(ids);
+	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(ids, tmp_ctx);
 
 	ids[0].unixid = talloc(ids, struct unixid);
-	NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
-	ids[0].unixid->id = name->st.st_uid;
+	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(ids[0].unixid, tmp_ctx);
+	ids[0].unixid->id = geteuid();
 	ids[0].unixid->type = ID_TYPE_UID;
 	ids[0].sid = NULL;
 	ids[0].status = NT_STATUS_NONE_MAPPED;
 
 	ids[1].unixid = talloc(ids, struct unixid);
-	NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
-	ids[1].unixid->id = name->st.st_gid;
+	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(ids[1].unixid, tmp_ctx);
+	ids[1].unixid->id = getegid();
 	ids[1].unixid->type = ID_TYPE_GID;
 	ids[1].sid = NULL;
 	ids[1].status = NT_STATUS_NONE_MAPPED;
 
 	ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
-	NT_STATUS_HAVE_NO_MEMORY(ctx);
+	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(ctx, tmp_ctx);
 
 	status = wbc_xids_to_sids_recv(ctx, &ids);
-	NT_STATUS_NOT_OK_RETURN(status);
+	NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
 
 	sd->owner_sid = talloc_steal(sd, ids[0].sid);
 	sd->group_sid = talloc_steal(sd, ids[1].sid);
 
 	sd->type |= SEC_DESC_DACL_PRESENT;
 
-	container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
-
 	/* fill in the aces from the parent */
 	status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
+	NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
 
 	/* if there is nothing to inherit then we fallback to the
 	   default acl */
 	if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
+		talloc_free(tmp_ctx);
 		return NT_STATUS_OK;
 	}
 
-	acl->info.sd = sd;
+	*ret_sd = talloc_steal(mem_ctx, sd);
+
+	talloc_free(tmp_ctx);
+	return NT_STATUS_OK;
+}
+
+
+/*
+  setup an ACL on a new file/directory based on the inherited ACL from
+  the parent. If there is no inherited ACL then we don't set anything,
+  as the default ACL applies anyway
+*/
+NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
+			  struct ntvfs_request *req,
+			  struct pvfs_filename *name,
+			  int fd)
+{
+	struct xattr_NTACL acl;
+	NTSTATUS status;
+	struct security_descriptor *sd;
+	struct pvfs_filename *parent;
+	bool container;
+
+	/* form the parents path */
+	status = pvfs_resolve_parent(pvfs, req, name, &parent);
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
+
+	status = pvfs_acl_inherited_sd(pvfs, req, req, parent, container, &sd);
+	if (!NT_STATUS_IS_OK(status)) {
+		talloc_free(parent);
+		return status;
+	}
+
+	if (sd == NULL) {
+		return NT_STATUS_OK;
+	}
+
+	acl.version = 1;
+	acl.info.sd = sd;
+
+	status = pvfs_acl_save(pvfs, name, fd, &acl);
+	talloc_free(sd);
+	talloc_free(parent);
 
-	status = pvfs_acl_save(pvfs, name, fd, acl);
-	
 	return status;
 }
 
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index e8f1c0c..59bd67b 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -103,10 +103,10 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs,
 					struct ntvfs_request *req,
 					struct pvfs_filename *name,
 					int fd,	struct pvfs_file *f,
-					union smb_open *io)
+					union smb_open *io,
+					struct security_descriptor *sd)
 {
 	NTSTATUS status;
-	struct security_descriptor *sd;
 
 	/* setup any EAs that were asked for */
 	if (io->ntcreatex.in.ea_list) {
@@ -118,7 +118,6 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs,
 		}
 	}
 
-	sd = io->ntcreatex.in.sec_desc;
 	/* setup an initial sec_desc if requested */
 	if (sd && (sd->type & SEC_DESC_DACL_PRESENT)) {
 		union smb_setfileinfo set;
@@ -134,9 +133,6 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs,
 		set.set_secdesc.in.sd = sd;
 
 		status = pvfs_acl_set(pvfs, req, name, fd, SEC_STD_WRITE_DAC, &set);
-	} else {
-		/* otherwise setup an inherited acl from the parent */
-		status = pvfs_acl_inherit(pvfs, req, name, fd);
 	}
 
 	return status;
@@ -185,6 +181,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
 	uint32_t create_options;
 	uint32_t share_access;
 	bool forced;
+	struct security_descriptor *sd = NULL;
 
 	create_options = io->generic.in.create_options;
 	share_access   = io->generic.in.share_access;
@@ -251,8 +248,9 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
 	if (name->exists) {
 		/* check the security descriptor */
 		status = pvfs_access_check(pvfs, req, name, &access_mask);
-	} else {
-		status = pvfs_access_check_create(pvfs, req, name, &access_mask);
+	} else {		
+		sd = io->ntcreatex.in.sec_desc;
+		status = pvfs_access_check_create(pvfs, req, name, &access_mask, true, &sd);
 	}
 	NT_STATUS_NOT_OK_RETURN(status);
 
@@ -352,7 +350,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
 			goto cleanup_delete;
 		}
 
-		status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io);
+		status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io, sd);
 		if (!NT_STATUS_IS_OK(status)) {
 			goto cleanup_delete;
 		}
@@ -616,6 +614,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
 	struct pvfs_filename *parent;
 	uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
 	bool allow_level_II_oplock = false;
+	struct security_descriptor *sd = NULL;
 
 	if (io->ntcreatex.in.file_attr & ~FILE_ATTRIBUTE_ALL_MASK) {
 		return NT_STATUS_INVALID_PARAMETER;
@@ -630,7 +629,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
 		return NT_STATUS_CANNOT_DELETE;
 	}
 
-	status = pvfs_access_check_create(pvfs, req, name, &access_mask);
+	sd = io->ntcreatex.in.sec_desc;
+	status = pvfs_access_check_create(pvfs, req, name, &access_mask, false, &sd);
 	NT_STATUS_NOT_OK_RETURN(status);
 
 	/* check that the parent isn't opened with delete on close set */
@@ -698,7 +698,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
 	}
 
 
-	status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io);
+	status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io, sd);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto cleanup_delete;
 	}
diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c
index 8e8da72..8c5806d 100644
--- a/source4/ntvfs/posix/pvfs_resolve.c
+++ b/source4/ntvfs/posix/pvfs_resolve.c
@@ -498,13 +498,14 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx,
 
      TODO: ../ collapsing, and outside share checking
 */
-NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
+NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, 
+			   struct ntvfs_request *req,
 			   const char *cifs_name,
 			   uint_t flags, struct pvfs_filename **name)
 {
 	NTSTATUS status;
 
-	*name = talloc(mem_ctx, struct pvfs_filename);
+	*name = talloc(req, struct pvfs_filename);
 	if (*name == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -516,6 +517,12 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
 		flags &= ~PVFS_RESOLVE_STREAMS;
 	}
 
+	/* SMB2 doesn't allow a leading slash */
+	if (req->ctx->protocol == PROTOCOL_SMB2 &&
+	    *cifs_name == '\\') {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
 	/* do the basic conversion to a unix formatted path,
 	   also checking for allowable characters */
 	status = pvfs_unix_path(pvfs, cifs_name, flags, *name);
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index 9fe02a8..2445483 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -168,7 +168,7 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
 	}
 
 	/* resolve the new name */
-	status = pvfs_resolve_name(pvfs, name, new_name, 0, &name2);
+	status = pvfs_resolve_name(pvfs, req, new_name, 0, &name2);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c
index be825b2..f93567f 100644
--- a/source4/torture/smb2/create.c
+++ b/source4/torture/smb2/create.c
@@ -249,6 +249,8 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
 
 	if (TARGET_IS_WIN7(torture)) {
 		CHECK_EQUAL(access_mask, 0x0de0fe00);
+	} else if (torture_setting_bool(torture, "samba4", false)) {
+		CHECK_EQUAL(access_mask, 0x0cf0fe00);
 	} else {
 		CHECK_EQUAL(access_mask, 0x0df0fe00);
 	}


-- 
Samba Shared Repository


More information about the samba-cvs mailing list