[PATCH] Add tests for our NFSv4 ACL code

Jeremy Allison jra at samba.org
Tue May 7 18:01:55 MDT 2013


On Fri, May 03, 2013 at 08:56:07AM -0700, Jeremy Allison wrote:
> On Fri, May 03, 2013 at 06:55:23PM +1200, Andrew Bartlett wrote:
> > On Fri, 2013-05-03 at 06:34 +0200, Alexander Werth wrote:
> > > On Fri, 2013-05-03 at 13:59 +1200, Andrew Bartlett wrote:
> > > > On Fri, 2013-05-03 at 03:10 +0200, Alexander Werth wrote:
> > > > 
> > > > > 
> > > > > What else would be needed before the changes can be applied to master?
> > > > 
> > > > The patch for testing creator_owner still has incorrect knownfail
> > > > entries. 
> > > > 
> > > > It doesn't pass make test TESTS=acls
> > > 
> > > Fixed.
> > > ALL OK (77 tests in 8 testsuites)
> > > 
> > > I also added an update to the vfs_gpfs man page.
> > 
> > I've marked these as Reviewed-by: Andrew Bartlett <abartlet at samba.org>
> > in my nfsv4-3 branch.  I just need another team member to review my
> > changes, so we can push this fine collaboration.
> > 
> > Thanks for all your effort and patience here!
> 
> I'm at an offsite for the rest of the week, but
> I'll start a review of these on Monday (Pacific
> Time).

Ok, here is the complete patchset I've reviewed
and added my "Reviewed-by:" lines to.

I fixed a few issues in the code - some missing
TALLOC_FREE(frame) calls, one missing error check
on a TALLOC_REALLOC and an update to Makefile.in
for the autoconf build.

I also added a couple of (small) tidy-up fixes
of my own - so Andrew please just review those
for correctness before pushing to autobuild.

This set also includes Christian Ambach's build
breakage fixes for AIX.

Cheers,

	Jeremy.
-------------- next part --------------
From 1818497f10c4c5e26ad035e7637525fc330a3f8e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 12 Apr 2013 20:24:44 +1000
Subject: [PATCH 01/26] build: Move nfs4acl to the top level

This is to create IDL-stored NFSv4 ACLs, just as we use for posix ACLs
to permit better testing.

Andrew Bartlett

Reviewed-by: Jeremy Allison <jra at samba.org>

---
 librpc/idl/nfs4acl.idl           | 42 ++++++++++++++++++++++++++++++++++++++++
 librpc/idl/wscript_build         |  2 +-
 librpc/wscript_build             |  5 +++++
 source4/librpc/idl/nfs4acl.idl   | 42 ----------------------------------------
 source4/librpc/idl/wscript_build |  2 +-
 source4/librpc/wscript_build     |  7 -------
 6 files changed, 49 insertions(+), 51 deletions(-)
 create mode 100644 librpc/idl/nfs4acl.idl
 delete mode 100644 source4/librpc/idl/nfs4acl.idl

diff --git a/librpc/idl/nfs4acl.idl b/librpc/idl/nfs4acl.idl
new file mode 100644
index 0000000..3d4379a
--- /dev/null
+++ b/librpc/idl/nfs4acl.idl
@@ -0,0 +1,42 @@
+#include "idl_types.h"
+
+/*
+  NFS4 ACL format on disk
+  see http://www.suse.de/~agruen/nfs4acl/
+*/
+
+import "misc.idl", "security.idl";
+
+[ uuid("18763978-8625-abc3-54ca-9892bacdf321"),
+  version(1.0),
+  pointer_default(unique)
+]
+interface nfs4acl
+{
+	const char *NFS4ACL_XATTR_NAME = "system.nfs4acl";
+
+	/* these structures use the same bit values and other constants as
+	   in security.idl */
+	typedef [flag(NDR_BIG_ENDIAN)] struct {
+		uint16 e_type;
+		uint16 e_flags;
+		uint32 e_mask;
+		uint32 e_id;
+		utf8string e_who;
+		[flag(NDR_ALIGN4)]  DATA_BLOB _pad;
+	} nfs4ace;
+
+	typedef [public,flag(NDR_BIG_ENDIAN)] struct {
+		uint8 a_version;
+		uint8 a_flags;
+		uint16 a_count;
+		uint32 a_owner_mask;
+		uint32 a_group_mask;
+		uint32 a_other_mask;
+		nfs4ace ace[a_count];
+	} nfs4acl;
+
+	NTSTATUS nfs4acl_test(
+		[in]  nfs4acl acl
+		);
+}
diff --git a/librpc/idl/wscript_build b/librpc/idl/wscript_build
index 2dbf1a3..854a2e2 100644
--- a/librpc/idl/wscript_build
+++ b/librpc/idl/wscript_build
@@ -32,6 +32,6 @@ bld.SAMBA_PIDL_LIST('PIDL',
                     output_dir='../gen_ndr')
 
 bld.SAMBA_PIDL_LIST('PIDL',
-                    'dnsp.idl',
+		    'dnsp.idl nfs4acl.idl',
                     options='--header --ndr-parser --client --python',
                     output_dir='../gen_ndr')
diff --git a/librpc/wscript_build b/librpc/wscript_build
index 8a4c169..cc5d617 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -217,6 +217,11 @@ bld.SAMBA_SUBSYSTEM('NDR_DNSP',
     public_deps='ndr'
     )
 
+bld.SAMBA_SUBSYSTEM('NDR_NFS4ACL',
+    source='gen_ndr/ndr_nfs4acl.c',
+    public_deps='ndr NDR_SECURITY'
+    )
+
 bld.SAMBA_SUBSYSTEM('NDR_NTPRINTING',
     source='gen_ndr/ndr_ntprinting.c ndr/ndr_ntprinting.c',
     public_deps='ndr'
diff --git a/source4/librpc/idl/nfs4acl.idl b/source4/librpc/idl/nfs4acl.idl
deleted file mode 100644
index 3d4379a..0000000
--- a/source4/librpc/idl/nfs4acl.idl
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "idl_types.h"
-
-/*
-  NFS4 ACL format on disk
-  see http://www.suse.de/~agruen/nfs4acl/
-*/
-
-import "misc.idl", "security.idl";
-
-[ uuid("18763978-8625-abc3-54ca-9892bacdf321"),
-  version(1.0),
-  pointer_default(unique)
-]
-interface nfs4acl
-{
-	const char *NFS4ACL_XATTR_NAME = "system.nfs4acl";
-
-	/* these structures use the same bit values and other constants as
-	   in security.idl */
-	typedef [flag(NDR_BIG_ENDIAN)] struct {
-		uint16 e_type;
-		uint16 e_flags;
-		uint32 e_mask;
-		uint32 e_id;
-		utf8string e_who;
-		[flag(NDR_ALIGN4)]  DATA_BLOB _pad;
-	} nfs4ace;
-
-	typedef [public,flag(NDR_BIG_ENDIAN)] struct {
-		uint8 a_version;
-		uint8 a_flags;
-		uint16 a_count;
-		uint32 a_owner_mask;
-		uint32 a_group_mask;
-		uint32 a_other_mask;
-		nfs4ace ace[a_count];
-	} nfs4acl;
-
-	NTSTATUS nfs4acl_test(
-		[in]  nfs4acl acl
-		);
-}
diff --git a/source4/librpc/idl/wscript_build b/source4/librpc/idl/wscript_build
index 59b1676..7e54e8d 100644
--- a/source4/librpc/idl/wscript_build
+++ b/source4/librpc/idl/wscript_build
@@ -5,7 +5,7 @@ import os
 topinclude=os.path.join(bld.srcnode.abspath(), 'librpc/idl')
 
 bld.SAMBA_PIDL_LIST('PIDL',
-                    source='''irpc.idl nfs4acl.idl ntp_signd.idl
+		    source='''irpc.idl ntp_signd.idl
                               opendb.idl sasl_helpers.idl winbind.idl
                               winsif.idl winsrepl.idl winstation.idl''',
                     options="--includedir=%s --header --ndr-parser --client --python --server" % topinclude,
diff --git a/source4/librpc/wscript_build b/source4/librpc/wscript_build
index c53acef..f49c30d 100755
--- a/source4/librpc/wscript_build
+++ b/source4/librpc/wscript_build
@@ -24,13 +24,6 @@ bld.SAMBA_SUBSYSTEM('NDR_SASL_HELPERS',
 
 
 
-bld.SAMBA_SUBSYSTEM('NDR_NFS4ACL',
-	source='gen_ndr/ndr_nfs4acl.c',
-	public_deps='ndr NDR_SECURITY'
-	)
-
-
-
 bld.SAMBA_SUBSYSTEM('NDR_WINSIF',
 	source='gen_ndr/ndr_winsif.c',
 	public_deps='ndr'
-- 
1.8.2.1


From c57c3596dc423b2c57df0ab5bef9e4120d2656fc Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Sun, 14 Apr 2013 17:31:42 +1000
Subject: [PATCH 02/26] vfs: Add vfs_handle_struct argument to
 smb_set_nt_acl_nfs4 and the callback

This allows the callback to call xattr based storage functions that need this argument.

Andrew Bartlett

Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c   | 4 ++--
 source3/modules/nfs4_acls.h   | 4 ++--
 source3/modules/vfs_aixacl2.c | 9 +++++----
 source3/modules/vfs_gpfs.c    | 8 ++++----
 source3/modules/vfs_zfsacl.c  | 6 +++---
 5 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index 67db6b0..fa9efc1 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -734,7 +734,7 @@ static SMB4ACL_T *smbacl4_win2nfs4(
 	return theacl;
 }
 
-NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
+NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 	uint32 security_info_sent,
 	const struct security_descriptor *psd,
 	set_nfs4acl_native_fn_t set_nfs4_native)
@@ -819,7 +819,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
 	if (set_acl_as_root) {
 		become_root();
 	}
-	result = set_nfs4_native(fsp, theacl);
+	result = set_nfs4_native(handle, fsp, theacl);
 	saved_errno = errno;
 	if (set_acl_as_root) {
 		unbecome_root();
diff --git a/source3/modules/nfs4_acls.h b/source3/modules/nfs4_acls.h
index c461229..f450396 100644
--- a/source3/modules/nfs4_acls.h
+++ b/source3/modules/nfs4_acls.h
@@ -143,9 +143,9 @@ NTSTATUS smb_get_nt_acl_nfs4(connection_struct *conn,
 
 /* Callback function needed to set the native acl
  * when applicable */
-typedef bool (*set_nfs4acl_native_fn_t)(files_struct *, SMB4ACL_T *);
+typedef bool (*set_nfs4acl_native_fn_t)(vfs_handle_struct *handle, files_struct *, SMB4ACL_T *);
 
-NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
+NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 	uint32 security_info_sent,
 	const struct security_descriptor *psd,
 	set_nfs4acl_native_fn_t set_nfs4_native);
diff --git a/source3/modules/vfs_aixacl2.c b/source3/modules/vfs_aixacl2.c
index 65625d1..aca7a65 100644
--- a/source3/modules/vfs_aixacl2.c
+++ b/source3/modules/vfs_aixacl2.c
@@ -338,7 +338,7 @@ static int aixjfs2_query_acl_support(
 	return 1; /* haven't found that ACL type. */
 }
 
-static bool aixjfs2_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
+static bool aixjfs2_process_smbacl(vfs_handle_struct *handle, files_struct *fsp, SMB4ACL_T *smbacl)
 {
 	SMB4ACE_T	*smbace;
 	TALLOC_CTX	*mem_ctx;
@@ -413,20 +413,21 @@ static bool aixjfs2_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
 	return True;
 }
 
-static NTSTATUS aixjfs2_set_nt_acl_common(files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
+static NTSTATUS aixjfs2_set_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
 {
 	acl_type_t	acl_type_info;
 	NTSTATUS	result = NT_STATUS_ACCESS_DENIED;
 	int	rc;
 
 	rc = aixjfs2_query_acl_support(
+		handle,
 		fsp->fsp_name,
 		ACL_NFS4,
 		&acl_type_info);
 
 	if (rc==0)
 	{
-		result = smb_set_nt_acl_nfs4(
+		result = smb_set_nt_acl_nfs4(handle,
 			fsp, security_info_sent, psd,
 			aixjfs2_process_smbacl);
 	} else if (rc==1) { /* assume POSIX ACL - by default... */
@@ -439,7 +440,7 @@ static NTSTATUS aixjfs2_set_nt_acl_common(files_struct *fsp, uint32 security_inf
 
 NTSTATUS aixjfs2_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
 {
-	return aixjfs2_set_nt_acl_common(fsp, security_info_sent, psd);
+	return aixjfs2_set_nt_acl_common(handle, fsp, security_info_sent, psd);
 }
 
 int aixjfs2_sys_acl_set_file(vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 674e101..33a81a0 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -453,7 +453,7 @@ static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
 	return map_nt_error_from_unix(errno);
 }
 
-static bool gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
+static bool gpfsacl_process_smbacl(vfs_handle_struct *handle, files_struct *fsp, SMB4ACL_T *smbacl)
 {
 	int ret;
 	gpfs_aclLen_t gacl_len;
@@ -549,7 +549,7 @@ static bool gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
 	return True;
 }
 
-static NTSTATUS gpfsacl_set_nt_acl_internal(files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
+static NTSTATUS gpfsacl_set_nt_acl_internal(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
 {
 	struct gpfs_acl *acl;
 	NTSTATUS result = NT_STATUS_ACCESS_DENIED;
@@ -570,7 +570,7 @@ static NTSTATUS gpfsacl_set_nt_acl_internal(files_struct *fsp, uint32 security_i
 			return NT_STATUS_NOT_SUPPORTED;
 		}
 
-		result = smb_set_nt_acl_nfs4(
+		result = smb_set_nt_acl_nfs4(handle,
 			fsp, security_info_sent, psd,
 			gpfsacl_process_smbacl);
 	} else { /* assume POSIX ACL - by default... */
@@ -593,7 +593,7 @@ static NTSTATUS gpfsacl_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp
 		return SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
 	}
 
-	return gpfsacl_set_nt_acl_internal(fsp, security_info_sent, psd);
+	return gpfsacl_set_nt_acl_internal(handle, fsp, security_info_sent, psd);
 }
 
 static SMB_ACL_T gpfs2smb_acl(const struct gpfs_acl *pacl, TALLOC_CTX *mem_ctx)
diff --git a/source3/modules/vfs_zfsacl.c b/source3/modules/vfs_zfsacl.c
index 6934ad6..91e31e9c 100644
--- a/source3/modules/vfs_zfsacl.c
+++ b/source3/modules/vfs_zfsacl.c
@@ -106,7 +106,7 @@ static NTSTATUS zfs_get_nt_acl_common(const char *name,
 }
 
 /* call-back function processing the NT acl -> ZFS acl using NFSv4 conv. */
-static bool zfs_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
+static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp, SMB4ACL_T *smbacl)
 {
 	int naces = smb_get_naces(smbacl), i;
 	ace_t *acebuf;
@@ -187,8 +187,8 @@ static NTSTATUS zfs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
 			   uint32 security_info_sent,
 			   const struct security_descriptor *psd)
 {
-	return smb_set_nt_acl_nfs4(fsp, security_info_sent, psd,
-			zfs_process_smbacl);
+        return smb_set_nt_acl_nfs4(handle, fsp, security_info_sent, psd,
+				   zfs_process_smbacl);
 }
 
 static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
-- 
1.8.2.1


From f520b5cc6a3affc197b3d671199aba5d063f6c0e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Sun, 14 Apr 2013 18:13:42 +1000
Subject: [PATCH 03/26] vfs: Allocate SMB4ACL_T on an explict memory context

This ensures the caller knows exactly what the memory lifetime of this
returned object is.  This makes the NFSv4 ACL code consistent with the
POSIX and NT ACL code, to avoid supprising developers who have worked
on those other parts of the ACL code.

Most of this patch is adding a memory context to the callers and passing it in.

Andrew Bartlett
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c   | 33 +++++++++++++++++++++++++--------
 source3/modules/nfs4_acls.h   |  2 +-
 source3/modules/vfs_aixacl2.c | 15 ++++++++++-----
 source3/modules/vfs_gpfs.c    | 28 ++++++++++++++++++++--------
 source3/modules/vfs_zfsacl.c  | 33 ++++++++++++++++++++++-----------
 5 files changed, 78 insertions(+), 33 deletions(-)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index fa9efc1..fa6b2fe 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -142,9 +142,8 @@ static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace)
 	return aceint;
 }
 
-SMB4ACL_T *smb_create_smb4acl(void)
+SMB4ACL_T *smb_create_smb4acl(TALLOC_CTX *mem_ctx)
 {
-	TALLOC_CTX *mem_ctx = talloc_tos();
 	SMB_ACL4_INT_T	*theacl = (SMB_ACL4_INT_T *)TALLOC_ZERO_SIZE(
 		mem_ctx, sizeof(SMB_ACL4_INT_T));
 	if (theacl==NULL)
@@ -379,10 +378,12 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
 	struct security_acl *psa = NULL;
 	TALLOC_CTX *frame = talloc_stackframe();
 
-	if (theacl==NULL || smb_get_naces(theacl)==0)
+	if (theacl==NULL || smb_get_naces(theacl)==0) {
+		TALLOC_FREE(frame);
 		return NT_STATUS_ACCESS_DENIED; /* special because we
 						 * shouldn't alloc 0 for
 						 * win */
+	}
 
 	uid_to_sid(&sid_owner, sbuf->st_ex_uid);
 	gid_to_sid(&sid_group, sbuf->st_ex_gid);
@@ -691,6 +692,7 @@ static int smbacl4_MergeIgnoreReject(
 }
 
 static SMB4ACL_T *smbacl4_win2nfs4(
+	TALLOC_CTX *mem_ctx,
 	const files_struct *fsp,
 	const struct security_acl *dacl,
 	smbacl4_vfs_params *pparams,
@@ -704,7 +706,7 @@ static SMB4ACL_T *smbacl4_win2nfs4(
 
 	DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
 
-	theacl = smb_create_smb4acl();
+	theacl = smb_create_smb4acl(mem_ctx);
 	if (theacl==NULL)
 		return NULL;
 
@@ -748,6 +750,7 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 	uid_t newUID = (uid_t)-1;
 	gid_t newGID = (gid_t)-1;
 	int saved_errno;
+	TALLOC_CTX *frame = talloc_stackframe();
 
 	DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
 
@@ -756,16 +759,21 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 	{
 		DEBUG(9, ("security_info_sent (0x%x) ignored\n",
 			security_info_sent));
+		TALLOC_FREE(frame);
 		return NT_STATUS_OK; /* won't show error - later to be
 				      * refined... */
 	}
 
 	/* Special behaviours */
-	if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, &params))
+	if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, &params)) {
+		TALLOC_FREE(frame);
 		return NT_STATUS_NO_MEMORY;
+	}
 
-	if (smbacl4_fGetFileOwner(fsp, &sbuf))
+	if (smbacl4_fGetFileOwner(fsp, &sbuf)) {
+		TALLOC_FREE(frame);
 		return map_nt_error_from_unix(errno);
+	}
 
 	if (params.do_chown) {
 		/* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
@@ -773,6 +781,7 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 						   security_info_sent, psd);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(8, ("unpack_nt_owners failed"));
+			TALLOC_FREE(frame);
 			return status;
 		}
 		if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) ||
@@ -785,6 +794,7 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 					 (unsigned int)newUID,
 					 (unsigned int)newGID,
 					 nt_errstr(status)));
+				TALLOC_FREE(frame);
 				return status;
 			}
 
@@ -794,6 +804,7 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 			if (smbacl4_GetFileOwner(fsp->conn,
 						 fsp->fsp_name->base_name,
 						 &sbuf))
+				TALLOC_FREE(frame);
 				return map_nt_error_from_unix(errno);
 
 			/* If we successfully chowned, we know we must
@@ -806,13 +817,16 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 	if (!(security_info_sent & SECINFO_DACL) || psd->dacl ==NULL) {
 		DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
 			   security_info_sent));
+		TALLOC_FREE(frame);
 		return NT_STATUS_OK;
 	}
 
-	theacl = smbacl4_win2nfs4(fsp, psd->dacl, &params,
+	theacl = smbacl4_win2nfs4(frame, fsp, psd->dacl, &params,
 				  sbuf.st_ex_uid, sbuf.st_ex_gid);
-	if (!theacl)
+	if (!theacl) {
+		TALLOC_FREE(frame);
 		return map_nt_error_from_unix(errno);
+	}
 
 	smbacl4_dump_nfs4acl(10, theacl);
 
@@ -824,6 +838,9 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 	if (set_acl_as_root) {
 		unbecome_root();
 	}
+
+	TALLOC_FREE(frame);
+
 	if (result!=True) {
 		errno = saved_errno;
 		DEBUG(10, ("set_nfs4_native failed with %s\n",
diff --git a/source3/modules/nfs4_acls.h b/source3/modules/nfs4_acls.h
index f450396..1bde81b 100644
--- a/source3/modules/nfs4_acls.h
+++ b/source3/modules/nfs4_acls.h
@@ -114,7 +114,7 @@ typedef struct _SMB_ACE4PROP_T {
 typedef struct _SMB4ACL_T {char dontuse;} SMB4ACL_T;
 typedef struct _SMB4ACE_T {char dontuse;} SMB4ACE_T;
 
-SMB4ACL_T *smb_create_smb4acl(void);
+SMB4ACL_T *smb_create_smb4acl(TALLOC_CTX *mem_ctx);
 
 /* prop's contents are copied */
 /* it doesn't change the order, appends */
diff --git a/source3/modules/vfs_aixacl2.c b/source3/modules/vfs_aixacl2.c
index aca7a65..c97cd57 100644
--- a/source3/modules/vfs_aixacl2.c
+++ b/source3/modules/vfs_aixacl2.c
@@ -93,7 +93,7 @@ static AIXJFS2_ACL_T *aixjfs2_getacl_alloc(const char *fname, acl_type_t *type)
 	return acl;
 }
 
-static bool aixjfs2_get_nfs4_acl(const char *name,
+static bool aixjfs2_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *name
 	SMB4ACL_T **ppacl, bool *pretryPosix)
 {
 	int32_t i;
@@ -121,7 +121,7 @@ static bool aixjfs2_get_nfs4_acl(const char *name,
 	DEBUG(10, ("len: %d, version: %d, nace: %d, type: 0x%x\n",
 			jfs2_acl->aclLength, jfs2_acl->aclVersion, jfs2_acl->aclEntryN, type.u64));
 
-	*ppacl = smb_create_smb4acl();
+	*ppacl = smb_create_smb4acl(mem_ctx);
 	if (*ppacl==NULL)
 		return False;
 
@@ -158,15 +158,18 @@ static NTSTATUS aixjfs2_fget_nt_acl(vfs_handle_struct *handle,
 	TALLOC_CTX *mem_ctx,
 	struct security_descriptor **ppdesc)
 {
+	NTSTATUS status;
 	SMB4ACL_T *pacl = NULL;
 	bool	result;
 	bool	retryPosix = False;
+	TALLOC_CTX *frame = talloc_stackframe();
 
 	*ppdesc = NULL;
-	result = aixjfs2_get_nfs4_acl(fsp->fsp_name->base_name, &pacl,
+	result = aixjfs2_get_nfs4_acl(frame, fsp->fsp_name->base_name, &pacl,
 				      &retryPosix);
 	if (retryPosix)
 	{
+		TALLOC_FREE(frame);
 		DEBUG(10, ("retrying with posix acl...\n"));
 		return posix_fget_nt_acl(fsp, security_info,
 					 mem_ctx, ppdesc);
@@ -174,8 +177,10 @@ static NTSTATUS aixjfs2_fget_nt_acl(vfs_handle_struct *handle,
 	if (result==False)
 		return NT_STATUS_ACCESS_DENIED;
 
-	return smb_fget_nt_acl_nfs4(fsp, security_info, ppdesc,
-				    mem_ctx, pacl);
+	status = smb_fget_nt_acl_nfs4(fsp, security_info, ppdesc,
+				      mem_ctx, pacl);
+	TALLOC_FREE(frame);
+	return status;
 }
 
 static NTSTATUS aixjfs2_get_nt_acl(vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 33a81a0..39f4bb9 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -299,7 +299,7 @@ again:
  * On failure returns -1 if there is system (GPFS) error, check errno.
  * Returns 0 on success
  */
-static int gpfs_get_nfs4_acl(const char *fname, SMB4ACL_T **ppacl)
+static int gpfs_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *fname, SMB4ACL_T **ppacl)
 {
 	gpfs_aclCount_t i;
 	struct gpfs_acl *gacl = NULL;
@@ -321,7 +321,7 @@ static int gpfs_get_nfs4_acl(const char *fname, SMB4ACL_T **ppacl)
 		return 1;
 	}
 
-	*ppacl = smb_create_smb4acl();
+	*ppacl = smb_create_smb4acl(mem_ctx);
 
 	DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
 		   gacl->acl_len, gacl->acl_level, gacl->acl_version,
@@ -399,20 +399,30 @@ static NTSTATUS gpfsacl_fget_nt_acl(vfs_handle_struct *handle,
 				return NT_STATUS_INTERNAL_ERROR);
 
 	if (!config->acl) {
-		return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
-						mem_ctx, ppdesc);
+		status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
+						  mem_ctx, ppdesc);
+		TALLOC_FREE(frame);
+		return status;
 	}
 
-	result = gpfs_get_nfs4_acl(fsp->fsp_name->base_name, &pacl);
+	result = gpfs_get_nfs4_acl(frame, fsp->fsp_name->base_name, &pacl);
 
-	if (result == 0)
-		return smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
+	if (result == 0) {
+		statys = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
+		TALLOC_FREE(frame);
+		return status;
+	}
 
 	if (result > 0) {
 		DEBUG(10, ("retrying with posix acl...\n"));
-		return posix_fget_nt_acl(fsp, security_info, mem_ctx, ppdesc);
+		status = posix_fget_nt_acl(fsp, security_info, mem_ctx, ppdesc);
+		TALLOC_FREE(frame);
+		return status;
+
 	}
 
+	TALLOC_FREE(frame);
+
 	/* GPFS ACL was not read, something wrong happened, error code is set in errno */
 	return map_nt_error_from_unix(errno);
 }
@@ -425,6 +435,8 @@ static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
 	SMB4ACL_T *pacl = NULL;
 	int	result;
 	struct gpfs_config_data *config;
+	TALLOC_CTX *frame = talloc_stackframe();
+	NTSTATUS status;
 
 	*ppdesc = NULL;
 
diff --git a/source3/modules/vfs_zfsacl.c b/source3/modules/vfs_zfsacl.c
index 91e31e9c..743f33b 100644
--- a/source3/modules/vfs_zfsacl.c
+++ b/source3/modules/vfs_zfsacl.c
@@ -40,14 +40,14 @@
  * read the local file's acls and return it in NT form
  * using the NFSv4 format conversion
  */
-static NTSTATUS zfs_get_nt_acl_common(const char *name,
+static NTSTATUS zfs_get_nt_acl_common(TALLOC_CTX *mem_ctx,
+				      const char *name,
 				      uint32 security_info,
 				      SMB4ACL_T **ppacl)
 {
 	int naces, i;
 	ace_t *acebuf;
 	SMB4ACL_T *pacl;
-	TALLOC_CTX	*mem_ctx;
 
 	/* read the number of file aces */
 	if((naces = acl(name, ACE_GETACLCNT, 0, NULL)) == -1) {
@@ -74,7 +74,7 @@ static NTSTATUS zfs_get_nt_acl_common(const char *name,
 		return map_nt_error_from_unix(errno);
 	}
 	/* create SMB4ACL data */
-	if((pacl = smb_create_smb4acl()) == NULL) {
+	if((pacl = smb_create_smb4acl(mem_ctx)) == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
 	for(i=0; i<naces; i++) {
@@ -199,15 +199,20 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
 {
 	SMB4ACL_T *pacl;
 	NTSTATUS status;
+	TALLOC_CTX *frame = talloc_stackframe();
 
-	status = zfs_get_nt_acl_common(fsp->fsp_name->base_name,
+	status = zfs_get_nt_acl_common(frame,
+				       fsp->fsp_name->base_name,
 				       security_info,
 				       &pacl);
 	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
 		return status;
 	}
 
-	return smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
+	status = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
+	TALLOC_FREE(frame);
+	return status;
 }
 
 static NTSTATUS zfsacl_get_nt_acl(struct vfs_handle_struct *handle,
@@ -217,15 +222,19 @@ static NTSTATUS zfsacl_get_nt_acl(struct vfs_handle_struct *handle,
 {
 	SMB4ACL_T *pacl;
 	NTSTATUS status;
+	TALLOC_CTX *frame = talloc_stackframe();
 
-	status = zfs_get_nt_acl_common(name, security_info, &pacl);
+	status = zfs_get_nt_acl_common(frame, name, security_info, &pacl);
 	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
 		return status;
 	}
 
-	return smb_get_nt_acl_nfs4(handle->conn, name, security_info,
-				   mem_ctx, ppdesc,
-				   pacl);
+	status = smb_get_nt_acl_nfs4(handle->conn, name, security_info,
+				     mem_ctx, ppdesc,
+				     pacl);
+	TALLOC_FREE(frame);
+	return status;
 }
 
 static NTSTATUS zfsacl_fset_nt_acl(vfs_handle_struct *handle,
@@ -269,13 +278,15 @@ static NTSTATUS zfsacl_fset_nt_acl(vfs_handle_struct *handle,
 
 static SMB_ACL_T zfsacl_fail__sys_acl_get_file(vfs_handle_struct *handle,
 					       const char *path_p,
-					       SMB_ACL_TYPE_T type)
+					       SMB_ACL_TYPE_T type,
+					       TALLOC_CTX *mem_ctx)
 {
 	return (SMB_ACL_T)NULL;
 }
 
 static SMB_ACL_T zfsacl_fail__sys_acl_get_fd(vfs_handle_struct *handle,
-					     files_struct *fsp)
+					     files_struct *fsp,
+					     TALLOC_CTX *mem_ctx)
 {
 	return (SMB_ACL_T)NULL;
 }
-- 
1.8.2.1


From db2d18f8e7fee6e7a662d68e58f8acee2623fcd4 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Mon, 15 Apr 2013 16:35:36 +0200
Subject: [PATCH 04/26] vfs: Fix compile of vfs_gpfs.c.

Since the smb4acl is now correctly allocated on mem_ctx and not
the talloc stack frame we can free the stack frame correctly.
And the chmod emulation code now needs the vfs handle since
that is now required by the callback function to set the smb4acl.

Reviewed-By: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/vfs_gpfs.c | 51 ++++++++++++++++++++++++++++++----------------
 1 file changed, 33 insertions(+), 18 deletions(-)

diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 39f4bb9..6056b7e 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -391,6 +391,8 @@ static NTSTATUS gpfsacl_fget_nt_acl(vfs_handle_struct *handle,
 	SMB4ACL_T *pacl = NULL;
 	int	result;
 	struct gpfs_config_data *config;
+	TALLOC_CTX *frame = talloc_stackframe();
+	NTSTATUS status;
 
 	*ppdesc = NULL;
 
@@ -408,17 +410,18 @@ static NTSTATUS gpfsacl_fget_nt_acl(vfs_handle_struct *handle,
 	result = gpfs_get_nfs4_acl(frame, fsp->fsp_name->base_name, &pacl);
 
 	if (result == 0) {
-		statys = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
+		status = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx,
+					      ppdesc, pacl);
 		TALLOC_FREE(frame);
 		return status;
 	}
 
 	if (result > 0) {
 		DEBUG(10, ("retrying with posix acl...\n"));
-		status = posix_fget_nt_acl(fsp, security_info, mem_ctx, ppdesc);
+		status = posix_fget_nt_acl(fsp, security_info,
+					   mem_ctx, ppdesc);
 		TALLOC_FREE(frame);
 		return status;
-
 	}
 
 	TALLOC_FREE(frame);
@@ -445,20 +448,27 @@ static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
 				return NT_STATUS_INTERNAL_ERROR);
 
 	if (!config->acl) {
-		return SMB_VFS_NEXT_GET_NT_ACL(handle, name, security_info,
-					       mem_ctx, ppdesc);
+		status = SMB_VFS_NEXT_GET_NT_ACL(handle, name, security_info,
+						 mem_ctx, ppdesc);
+		TALLOC_FREE(frame);
+		return status;
 	}
 
-	result = gpfs_get_nfs4_acl(name, &pacl);
+	result = gpfs_get_nfs4_acl(frame, name, &pacl);
 
-	if (result == 0)
-		return smb_get_nt_acl_nfs4(handle->conn, name, security_info,
+	if (result == 0) {
+		status = smb_get_nt_acl_nfs4(handle->conn, name, security_info,
 					   mem_ctx, ppdesc, pacl);
+		TALLOC_FREE(frame);
+		return status;
+	}
 
 	if (result > 0) {
 		DEBUG(10, ("retrying with posix acl...\n"));
-		return posix_get_nt_acl(handle->conn, name, security_info,
-					mem_ctx, ppdesc);
+		status =  posix_get_nt_acl(handle->conn, name, security_info,
+					   mem_ctx, ppdesc);
+		TALLOC_FREE(frame);
+		return status;
 	}
 
 	/* GPFS ACL was not read, something wrong happened, error code is set in errno */
@@ -1097,7 +1107,8 @@ static uint32 gpfsacl_mask_filter(uint32 aceType, uint32 aceMask, uint32 rwx)
 	return aceMask;
 }
 
-static int gpfsacl_emu_chmod(const char *path, mode_t mode)
+static int gpfsacl_emu_chmod(vfs_handle_struct *handle,
+			     const char *path, mode_t mode)
 {
 	SMB4ACL_T *pacl = NULL;
 	int     result;
@@ -1105,12 +1116,14 @@ static int gpfsacl_emu_chmod(const char *path, mode_t mode)
 	int     i;
 	files_struct    fake_fsp; /* TODO: rationalize parametrization */
 	SMB4ACE_T       *smbace;
+	TALLOC_CTX *frame = talloc_stackframe();
 	NTSTATUS status;
 
 	DEBUG(10, ("gpfsacl_emu_chmod invoked for %s mode %o\n", path, mode));
 
-	result = gpfs_get_nfs4_acl(path, &pacl);
+	result = gpfs_get_nfs4_acl(frame, path, &pacl);
 	if (result)
+		TALLOC_FREE(frame);
 		return result;
 
 	if (mode & ~(S_IRWXU | S_IRWXG | S_IRWXO)) {
@@ -1176,18 +1189,19 @@ static int gpfsacl_emu_chmod(const char *path, mode_t mode)
 	/* don't add complementary DENY ACEs here */
 	ZERO_STRUCT(fake_fsp);
 	fake_fsp.fsp_name = synthetic_smb_fname(
-		talloc_tos(), path, NULL, NULL);
+		frame, path, NULL, NULL);
 	if (fake_fsp.fsp_name == NULL) {
 		errno = ENOMEM;
+		TALLOC_FREE(frame);
 		return -1;
 	}
 	/* put the acl */
-	if (gpfsacl_process_smbacl(&fake_fsp, pacl) == False) {
-		TALLOC_FREE(fake_fsp.fsp_name);
+	if (gpfsacl_process_smbacl(handle, &fake_fsp, pacl) == False) {
+		TALLOC_FREE(frame);
 		return -1;
 	}
 
-	TALLOC_FREE(fake_fsp.fsp_name);
+	TALLOC_FREE(frame);
 	return 0; /* ok for [f]chmod */
 }
 
@@ -1211,7 +1225,7 @@ static int vfs_gpfs_chmod(vfs_handle_struct *handle, const char *path, mode_t mo
 		return 0;
 	}
 
-	rc = gpfsacl_emu_chmod(path, mode);
+	rc = gpfsacl_emu_chmod(handle, path, mode);
 	if (rc == 1)
 		return SMB_VFS_NEXT_CHMOD(handle, path, mode);
 	return rc;
@@ -1231,7 +1245,8 @@ static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t
 			 return 0;
 		 }
 
-		 rc = gpfsacl_emu_chmod(fsp->fsp_name->base_name, mode);
+		 rc = gpfsacl_emu_chmod(handle, fsp->fsp_name->base_name,
+					mode);
 		 if (rc == 1)
 			 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
 		 return rc;
-- 
1.8.2.1


From 186b0c764cbb1894dc156767a245e803bb9eb12e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Sun, 14 Apr 2013 19:22:37 +1000
Subject: [PATCH 05/26] vfs: Remove unused security_info argument in
 vfz_zfsacl.c

Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/vfs_zfsacl.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/source3/modules/vfs_zfsacl.c b/source3/modules/vfs_zfsacl.c
index 743f33b..93a0faa 100644
--- a/source3/modules/vfs_zfsacl.c
+++ b/source3/modules/vfs_zfsacl.c
@@ -42,7 +42,6 @@
  */
 static NTSTATUS zfs_get_nt_acl_common(TALLOC_CTX *mem_ctx,
 				      const char *name,
-				      uint32 security_info,
 				      SMB4ACL_T **ppacl)
 {
 	int naces, i;
@@ -203,7 +202,6 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
 
 	status = zfs_get_nt_acl_common(frame,
 				       fsp->fsp_name->base_name,
-				       security_info,
 				       &pacl);
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(frame);
@@ -224,7 +222,7 @@ static NTSTATUS zfsacl_get_nt_acl(struct vfs_handle_struct *handle,
 	NTSTATUS status;
 	TALLOC_CTX *frame = talloc_stackframe();
 
-	status = zfs_get_nt_acl_common(frame, name, security_info, &pacl);
+	status = zfs_get_nt_acl_common(frame, name, &pacl);
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(frame);
 		return status;
-- 
1.8.2.1


From 164f5963e19d5f5b2debe359c0f010bb4d9c610c Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Sun, 14 Apr 2013 20:06:57 +1000
Subject: [PATCH 06/26] vfs: Add new VFS module vfs_nfs4acl_xattr to use
 nfs4acl.idl

This uses the xattr format used by the patches at http://users.suse.com/~agruen/nfs4acl/

Andrew Bartlett
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/Makefile.in                 |   5 +
 source3/configure.in                |   2 +-
 source3/modules/vfs_nfs4acl_xattr.c | 414 ++++++++++++++++++++++++++++++++++++
 source3/modules/wscript_build       |   9 +
 source3/wscript                     |   2 +-
 5 files changed, 430 insertions(+), 2 deletions(-)
 create mode 100644 source3/modules/vfs_nfs4acl_xattr.c

diff --git a/source3/Makefile.in b/source3/Makefile.in
index c701fd1..bf60a48 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -883,6 +883,7 @@ VFS_AIXACL_OBJ = modules/vfs_aixacl.o modules/vfs_aixacl_util.o
 VFS_AIXACL2_OBJ = modules/vfs_aixacl2.o modules/vfs_aixacl_util.o $(NFS4ACL_OBJ)
 VFS_SOLARISACL_OBJ = modules/vfs_solarisacl.o
 VFS_ZFSACL_OBJ = modules/vfs_zfsacl.o $(NFS4ACL_OBJ)
+VFS_NFS4ACL_XATTR_OBJ = modules/vfs_nfs4acl_xattr.o
 VFS_HPUXACL_OBJ = modules/vfs_hpuxacl.o
 VFS_TRU64ACL_OBJ = modules/vfs_tru64acl.o
 VFS_CATIA_OBJ = modules/vfs_catia.o
@@ -2838,6 +2839,10 @@ bin/zfsacl. at SHLIBEXT@: $(BINARY_PREREQS) $(VFS_ZFSACL_OBJ)
 	@echo "Building plugin $@"
 	@$(SHLD_MODULE) $(VFS_ZFSACL_OBJ) @ZFSACL_LIBS@
 
+bin/nfs4acl_xattr. at SHLIBEXT@: $(BINARY_PREREQS) $(VFS_NFS4ACL_XATTR_OBJ)
+	@echo "Building plugin $@"
+	@$(SHLD_MODULE) $(VFS_NFS4ACL_XATTR_OBJ)
+
 bin/hpuxacl. at SHLIBEXT@: $(BINARY_PREREQS) $(VFS_HPUXACL_OBJ)
 	@echo "Building plugin $@"
 	@$(SHLD_MODULE) $(VFS_HPUXACL_OBJ)
diff --git a/source3/configure.in b/source3/configure.in
index d2aa215..cb8f730 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -474,7 +474,7 @@ if test "x$developer" = xyes; then
 fi
 
 if test x"$selftest" = x"yes" -o "x$developer" = xyes; then
-   default_shared_modules="$default_shared_modules vfs_fake_acls"
+   default_shared_modules="$default_shared_modules vfs_fake_acls vfs_nfs4acl_xattr"
 fi
 
 #
diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c
new file mode 100644
index 0000000..fedb768
--- /dev/null
+++ b/source3/modules/vfs_nfs4acl_xattr.c
@@ -0,0 +1,414 @@
+/*
+ * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
+ *
+ * Copyright (C) Jiri Sasek, 2007
+ * based on the foobar.c module which is copyrighted by Volker Lendecke
+ * based on pvfs_acl_nfs4.c  Copyright (C) Andrew Tridgell 2006
+ *
+ * based on vfs_fake_acls:
+ * Copyright (C) Tim Potter, 1999-2000
+ * Copyright (C) Alexander Bokovoy, 2002
+ * Copyright (C) Andrew Bartlett, 2002,2012
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "smbd/smbd.h"
+#include "nfs4_acls.h"
+#include "librpc/gen_ndr/ndr_nfs4acl.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
+{
+	enum ndr_err_code ndr_err;
+	struct nfs4acl *acl = talloc(mem_ctx, struct nfs4acl);
+	if (!acl) {
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	ndr_err = ndr_pull_struct_blob(blob, acl, acl,
+		(ndr_pull_flags_fn_t)ndr_pull_nfs4acl);
+
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		DEBUG(0, ("ndr_pull_acl_t failed: %s\n",
+			  ndr_errstr(ndr_err)));
+		TALLOC_FREE(acl);
+		return NULL;
+	}
+	return acl;
+}
+
+static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl)
+{
+	enum ndr_err_code ndr_err;
+	DATA_BLOB blob;
+	ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl,
+		(ndr_push_flags_fn_t)ndr_push_nfs4acl);
+
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		DEBUG(0, ("ndr_push_acl_t failed: %s\n",
+			  ndr_errstr(ndr_err)));
+		return data_blob_null;
+	}
+	return blob;
+}
+
+static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx,
+					 DATA_BLOB *blob,
+					 SMB4ACL_T **ppacl)
+{
+	int i;
+	struct nfs4acl *nfs4acl = NULL;
+	SMB4ACL_T *pacl = NULL;
+	TALLOC_CTX *frame = talloc_stackframe();
+	nfs4acl = nfs4acl_blob2acl(blob, frame);
+
+	/* create SMB4ACL data */
+	if((pacl = smb_create_smb4acl(mem_ctx)) == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+	for(i=0; i<nfs4acl->a_count; i++) {
+		SMB_ACE4PROP_T aceprop;
+
+		aceprop.aceType  = (uint32) nfs4acl->ace[i].e_type;
+		aceprop.aceFlags = (uint32) nfs4acl->ace[i].e_flags;
+		aceprop.aceMask  = (uint32) nfs4acl->ace[i].e_mask;
+		aceprop.who.id   = (uint32) nfs4acl->ace[i].e_id;
+		if (!strcmp(nfs4acl->ace[i].e_who,
+			    NFS4ACL_XATTR_OWNER_WHO)) {
+			aceprop.flags = SMB_ACE4_ID_SPECIAL;
+			aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
+		} else if (!strcmp(nfs4acl->ace[i].e_who,
+				   NFS4ACL_XATTR_GROUP_WHO)) {
+			aceprop.flags = SMB_ACE4_ID_SPECIAL;
+			aceprop.who.special_id = SMB_ACE4_WHO_GROUP;
+		} else if (!strcmp(nfs4acl->ace[i].e_who,
+				   NFS4ACL_XATTR_EVERYONE_WHO)) {
+			aceprop.flags = SMB_ACE4_ID_SPECIAL;
+			aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE;
+		} else {
+			aceprop.flags = 0;
+		}
+		if(smb_add_ace4(pacl, &aceprop) == NULL) {
+			TALLOC_FREE(frame);
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+
+	*ppacl = pacl;
+	TALLOC_FREE(frame);
+	return NT_STATUS_OK;
+}
+
+/* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
+static NTSTATUS nfs4_fget_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
+				   files_struct *fsp, SMB4ACL_T **ppacl)
+{
+	NTSTATUS status;
+	DATA_BLOB blob = data_blob_null;
+	ssize_t length;
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	do {
+		blob.length += 1000;
+		blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
+		if (!blob.data) {
+			TALLOC_FREE(frame);
+			errno = ENOMEM;
+			return NT_STATUS_NO_MEMORY;
+		}
+		length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, NFS4ACL_XATTR_NAME, blob.data, blob.length);
+		blob.length = length;
+	} while (length == -1 && errno == ERANGE);
+	if (length == -1) {
+		TALLOC_FREE(frame);
+		return map_nt_error_from_unix(errno);
+	}
+	status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
+	TALLOC_FREE(frame);
+	return status;
+}
+
+/* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
+static NTSTATUS nfs4_get_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
+				  const char *path, SMB4ACL_T **ppacl)
+{
+	NTSTATUS status;
+	DATA_BLOB blob = data_blob_null;
+	ssize_t length;
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	do {
+		blob.length += 1000;
+		blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
+		if (!blob.data) {
+			TALLOC_FREE(frame);
+			errno = ENOMEM;
+			return NT_STATUS_NO_MEMORY;
+		}
+		length = SMB_VFS_NEXT_GETXATTR(handle, path, NFS4ACL_XATTR_NAME, blob.data, blob.length);
+		blob.length = length;
+	} while (length == -1 && errno == ERANGE);
+	if (length == -1) {
+		TALLOC_FREE(frame);
+		return map_nt_error_from_unix(errno);
+	}
+	status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
+	TALLOC_FREE(frame);
+	return status;
+}
+
+/* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */
+static bool nfs4_process_smbacl(vfs_handle_struct *handle, files_struct *fsp, SMB4ACL_T *smbacl)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	int i;
+	struct nfs4acl *nfs4acl;
+	SMB4ACE_T *smbace;
+	bool have_special_id = false;
+	int ret;
+	DATA_BLOB blob;
+
+	/* allocate the field of NFS4 aces */
+	nfs4acl = talloc_zero(frame, struct nfs4acl);
+	if(nfs4acl == NULL) {
+		TALLOC_FREE(frame);
+		errno = ENOMEM;
+		return false;
+	}
+
+	nfs4acl->a_count = smb_get_naces(smbacl);
+
+	nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace, nfs4acl->a_count);
+	if(nfs4acl->ace == NULL) {
+		TALLOC_FREE(frame);
+		errno = ENOMEM;
+		return false;
+	}
+
+	/* handle all aces */
+	for(smbace = smb_first_ace4(smbacl), i = 0;
+			smbace!=NULL;
+			smbace = smb_next_ace4(smbace), i++) {
+		SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
+
+		nfs4acl->ace[i].e_type        = aceprop->aceType;
+		nfs4acl->ace[i].e_flags       = aceprop->aceFlags;
+		nfs4acl->ace[i].e_mask        = aceprop->aceMask;
+		nfs4acl->ace[i].e_id          = aceprop->who.id;
+		if(aceprop->flags & SMB_ACE4_ID_SPECIAL) {
+			switch(aceprop->who.special_id) {
+			case SMB_ACE4_WHO_EVERYONE:
+				nfs4acl->ace[i].e_who =
+					NFS4ACL_XATTR_EVERYONE_WHO;
+				break;
+			case SMB_ACE4_WHO_OWNER:
+				nfs4acl->ace[i].e_who =
+					NFS4ACL_XATTR_OWNER_WHO;
+				break;
+			case SMB_ACE4_WHO_GROUP:
+				nfs4acl->ace[i].e_who =
+					NFS4ACL_XATTR_GROUP_WHO;
+				break;
+			default:
+				DEBUG(8, ("unsupported special_id %d\n", \
+					aceprop->who.special_id));
+				continue; /* don't add it !!! */
+			}
+			have_special_id = true;
+		} else {
+			nfs4acl->ace[i].e_who = "";
+		}
+	}
+
+	if (!have_special_id
+	    && lp_parm_bool(fsp->conn->params->service, "nfs4acl_xattr",
+			    "denymissingspecial", false)) {
+		TALLOC_FREE(frame);
+		errno = EACCES;
+		return false;
+	}
+
+	SMB_ASSERT(i == nfs4acl->a_count);
+
+	blob = nfs4acl_acl2blob(frame, nfs4acl);
+	if (!blob.data) {
+		DEBUG(0, ("Failed to convert ACL to linear blob for xattr storage\n"));
+		TALLOC_FREE(frame);
+		errno = EINVAL;
+		return false;
+	}
+	ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_XATTR_NAME, blob.data, blob.length, 0);
+	TALLOC_FREE(frame);
+
+	return ret == 0;
+}
+
+/* nfs4_set_nt_acl()
+ * set the local file's acls obtaining it in NT form
+ * using the NFSv4 format conversion
+ */
+static NTSTATUS nfs4_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+			   uint32 security_info_sent,
+			   const struct security_descriptor *psd)
+{
+	return smb_set_nt_acl_nfs4(handle, fsp, security_info_sent, psd,
+			nfs4_process_smbacl);
+}
+
+static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
+				   struct files_struct *fsp,
+				   uint32 security_info,
+				   TALLOC_CTX *mem_ctx,
+				   struct security_descriptor **ppdesc)
+{
+	SMB4ACL_T *pacl;
+	NTSTATUS status;
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	status = nfs4_fget_nfs4_acl(handle, frame, fsp, &pacl);
+	if (!NT_STATUS_IS_OK(status)) {
+		if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+			status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
+							  mem_ctx, ppdesc);
+		}
+		TALLOC_FREE(frame);
+		return status;
+	}
+
+	status = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
+	TALLOC_FREE(frame);
+	return status;
+}
+
+static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle,
+				  const char *name, uint32 security_info,
+				  TALLOC_CTX *mem_ctx,
+				  struct security_descriptor **ppdesc)
+{
+	SMB4ACL_T *pacl;
+	NTSTATUS status;
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	status = nfs4_get_nfs4_acl(handle, frame, name, &pacl);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+		if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+			status = SMB_VFS_NEXT_GET_NT_ACL(handle, name, security_info,
+							 mem_ctx, ppdesc);
+		}
+		TALLOC_FREE(frame);
+		return status;
+	}
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
+		return status;
+	}
+
+	status = smb_get_nt_acl_nfs4(handle->conn, name, security_info,
+				     mem_ctx, ppdesc,
+				     pacl);
+	TALLOC_FREE(frame);
+	return status;
+}
+
+static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
+			 files_struct *fsp,
+			 uint32 security_info_sent,
+			 const struct security_descriptor *psd)
+{
+	return nfs4_set_nt_acl(handle, fsp, security_info_sent, psd);
+}
+
+/*
+   As long as Samba does not support an exiplicit method for a module
+   to define conflicting vfs methods, we should override all conflicting
+   methods here.  That way, we know we are using the NFSv4 storage
+
+   Function declarations taken from vfs_solarisacl
+*/
+
+static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_file(vfs_handle_struct *handle,
+						      const char *path_p,
+						      SMB_ACL_TYPE_T type,
+						      TALLOC_CTX *mem_ctx)
+{
+	return (SMB_ACL_T)NULL;
+}
+
+static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_fd(vfs_handle_struct *handle,
+						    files_struct *fsp,
+						    TALLOC_CTX *mem_ctx)
+{
+	return (SMB_ACL_T)NULL;
+}
+
+static int nfs4acl_xattr_fail__sys_acl_set_file(vfs_handle_struct *handle,
+					 const char *name,
+					 SMB_ACL_TYPE_T type,
+					 SMB_ACL_T theacl)
+{
+	return -1;
+}
+
+static int nfs4acl_xattr_fail__sys_acl_set_fd(vfs_handle_struct *handle,
+				       files_struct *fsp,
+				       SMB_ACL_T theacl)
+{
+	return -1;
+}
+
+static int nfs4acl_xattr_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
+						const char *path)
+{
+	return -1;
+}
+
+static int nfs4acl_xattr_fail__sys_acl_blob_get_file(vfs_handle_struct *handle, const char *path_p, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
+{
+	return -1;
+}
+
+static int nfs4acl_xattr_fail__sys_acl_blob_get_fd(vfs_handle_struct *handle, files_struct *fsp, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
+{
+	return -1;
+}
+
+/* VFS operations structure */
+
+static struct vfs_fn_pointers nfs4acl_xattr_fns = {
+	.sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file,
+	.sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd,
+	.sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file,
+	.sys_acl_blob_get_fd_fn = nfs4acl_xattr_fail__sys_acl_blob_get_fd,
+	.sys_acl_set_file_fn = nfs4acl_xattr_fail__sys_acl_set_file,
+	.sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd,
+	.sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file,
+	.fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl,
+	.get_nt_acl_fn = nfs4acl_xattr_get_nt_acl,
+	.fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl,
+};
+
+NTSTATUS vfs_nfs4acl_xattr_init(void);
+NTSTATUS vfs_nfs4acl_xattr_init(void)
+{
+	return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",
+				&nfs4acl_xattr_fns);
+}
diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
index df4f59a..65e96b2 100644
--- a/source3/modules/wscript_build
+++ b/source3/modules/wscript_build
@@ -21,6 +21,7 @@ VFS_AIXACL_SRC = '''vfs_aixacl.c'''
 VFS_AIXACL2_SRC = '''vfs_aixacl2.c'''
 VFS_SOLARISACL_SRC = '''vfs_solarisacl.c'''
 VFS_ZFSACL_SRC = '''vfs_zfsacl.c'''
+VFS_NFS4ACL_XATTR_SRC = 'vfs_nfs4acl_xattr.c'
 VFS_HPUXACL_SRC = '''vfs_hpuxacl.c'''
 VFS_TRU64ACL_SRC = '''vfs_tru64acl.c'''
 VFS_CATIA_SRC = 'vfs_catia.c'
@@ -247,6 +248,14 @@ bld.SAMBA3_MODULE('vfs_zfsacl',
                  internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_zfsacl'),
                  enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_zfsacl'))
 
+bld.SAMBA3_MODULE('vfs_nfs4acl_xattr',
+		 subsystem='vfs',
+		 source=VFS_NFS4ACL_XATTR_SRC,
+		 deps='NFS4_ACLS sunacl',
+		 init_function='',
+		 internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_nfs4acl_xattr'),
+		 enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_nfs4acl_xattr'))
+
 bld.SAMBA3_MODULE('vfs_hpuxacl',
                  subsystem='vfs',
                  source=VFS_HPUXACL_SRC,
diff --git a/source3/wscript b/source3/wscript
index 28fa11f..24f2932 100644
--- a/source3/wscript
+++ b/source3/wscript
@@ -1741,7 +1741,7 @@ main() {
         default_shared_modules.extend(TO_LIST('auth_skel pdb_test'))
 
     if Options.options.enable_selftest or Options.options.developer:
-        default_shared_modules.extend(TO_LIST('vfs_fake_acls'))
+	default_shared_modules.extend(TO_LIST('vfs_fake_acls vfs_nfs4acl_xattr'))
         
 
     if conf.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'):
-- 
1.8.2.1


From 9275949ecd08c65e122699337eb3fe24b4059a91 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Sun, 14 Apr 2013 19:51:42 +1000
Subject: [PATCH 07/26] librpc: Add special owner/group/other constants to
 nfs4acl.idl

As per nfs4acl-0.9/lib/nfs4acl.c (the package where this structure is originally defined)

Andrew Bartlett
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 librpc/idl/nfs4acl.idl | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/librpc/idl/nfs4acl.idl b/librpc/idl/nfs4acl.idl
index 3d4379a..aeab0a0 100644
--- a/librpc/idl/nfs4acl.idl
+++ b/librpc/idl/nfs4acl.idl
@@ -15,6 +15,10 @@ interface nfs4acl
 {
 	const char *NFS4ACL_XATTR_NAME = "system.nfs4acl";
 
+	const char *NFS4ACL_XATTR_OWNER_WHO	 = "OWNER@";
+	const char *NFS4ACL_XATTR_GROUP_WHO	 = "GROUP@";
+	const char *NFS4ACL_XATTR_EVERYONE_WHO   = "EVERYONE@";
+
 	/* these structures use the same bit values and other constants as
 	   in security.idl */
 	typedef [flag(NDR_BIG_ENDIAN)] struct {
-- 
1.8.2.1


From 1325eb23e1426616aa9328531871477ecde929a7 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Sun, 14 Apr 2013 20:04:45 +1000
Subject: [PATCH 08/26] selftest: Run raw.acls test against the nfs4acl_xattr
 module

This is the first time we have tested the NFSv4 ACL mapping code.
Sadly most tests fail but these can be fixed from here.

This at least shows that the code does not segfault.

Andrew Bartlett
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 selftest/knownfail        | 8 ++++++++
 selftest/target/Samba3.pm | 6 ++++++
 source3/selftest/tests.py | 4 ++++
 3 files changed, 18 insertions(+)

diff --git a/selftest/knownfail b/selftest/knownfail
index 0c96eee..584e0b3 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -45,6 +45,14 @@
 ^samba3.blackbox.smbclient_machine_auth.plain \(s3dc:local\)# the S3dc does not currently set up a self-join
 ^samba3.raw.samba3hide.samba3hide\((s3dc|plugin_s4_dc)\) # This test fails against an smbd environment with NT ACLs enabled
 ^samba3.raw.samba3closeerr.samba3closeerr\(s3dc\) # This test fails against an smbd environment with NT ACLs enabled
+^samba3.raw.acls nfs4acl_xattr.INHERITFLAGS\(s3dc\) # This (and the follow nfs4acl_xattr tests fail because our NFSv4 backend isn't a complete mapping yet.
+^samba3.raw.acls nfs4acl_xattr.dynamic\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr.sd\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr.create_file\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr.create_dir\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr.nulldacl\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr.generic\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr.inheritance\(s3dc\)
 ^samba3.base.delete.deltest16a
 ^samba3.base.delete.deltest17a
 ^samba3.unix.whoami anonymous connection.whoami\(plugin_s4_dc\) # We need to resolve if we should be including SID_NT_WORLD and SID_NT_NETWORK in this token
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 1b14f1c..407642c 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1081,6 +1081,12 @@ sub provision($$$$$$)
 	default devmode = no
 [lp]
 	copy = print1
+
+[nfs4acl_share]
+	path = $shrdir
+	comment = smb username is [%U]
+	vfs objects = $vfs_modulesdir_abs/nfs4acl_xattr.so $vfs_modulesdir_abs/xattr_tdb.so
+
 [xcopy_share]
 	path = $shrdir
 	comment = smb username is [%U]
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 1c123f5..11504c0 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -343,6 +343,10 @@ for t in tests:
         plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
     elif t == "idmap.rfc2307":
         plantestsuite(t, "s3member_rfc2307", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_rfc2307.sh"), '$DOMAIN', 'Administrator', '2000000', '"Domain Users"', '2000001', 'ou=idmap,dc=samba,dc=example,dc=com', '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD'])
+    elif t == "raw.acls":
+        plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
+        plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/nfs4acl_share -U$USERNAME%$PASSWORD', description='nfs4acl_xattr')
+        plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER_IP/tmpcase -U$USERNAME%$PASSWORD')
     else:
         plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
-- 
1.8.2.1


From 68cdfaec877f1fa3bc491a57cc6d0baf4fc62f14 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Tue, 16 Apr 2013 14:11:27 +0200
Subject: [PATCH 09/26] vfs: Add inheritance emulation to vfs_nfs4acl_xattr.

Recursively inherit ACL from parent directory if no acl xattr is
found on the current file.
Use a default ACL if a non-inheriting ACL is encountered.
With this the nfs4acl_xattr.dynamic test passes.
But the nfs4acl_xattr.inheritance test results in an error because
of warnings that cause the test to pass a failed result.

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 selftest/knownfail                  |   1 -
 source3/modules/vfs_nfs4acl_xattr.c | 292 ++++++++++++++++++++++++++++++++----
 2 files changed, 263 insertions(+), 30 deletions(-)

diff --git a/selftest/knownfail b/selftest/knownfail
index 584e0b3..ba76f48 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -46,7 +46,6 @@
 ^samba3.raw.samba3hide.samba3hide\((s3dc|plugin_s4_dc)\) # This test fails against an smbd environment with NT ACLs enabled
 ^samba3.raw.samba3closeerr.samba3closeerr\(s3dc\) # This test fails against an smbd environment with NT ACLs enabled
 ^samba3.raw.acls nfs4acl_xattr.INHERITFLAGS\(s3dc\) # This (and the follow nfs4acl_xattr tests fail because our NFSv4 backend isn't a complete mapping yet.
-^samba3.raw.acls nfs4acl_xattr.dynamic\(s3dc\)
 ^samba3.raw.acls nfs4acl_xattr.sd\(s3dc\)
 ^samba3.raw.acls nfs4acl_xattr.create_file\(s3dc\)
 ^samba3.raw.acls nfs4acl_xattr.create_dir\(s3dc\)
diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c
index fedb768..bdaca82 100644
--- a/source3/modules/vfs_nfs4acl_xattr.c
+++ b/source3/modules/vfs_nfs4acl_xattr.c
@@ -176,30 +176,29 @@ static NTSTATUS nfs4_get_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx
 	return status;
 }
 
-/* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */
-static bool nfs4_process_smbacl(vfs_handle_struct *handle, files_struct *fsp, SMB4ACL_T *smbacl)
+static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx,
+				    SMB4ACL_T *smbacl,
+				    struct nfs4acl **pnfs4acl,
+				    bool denymissingspecial)
 {
-	TALLOC_CTX *frame = talloc_stackframe();
-	int i;
 	struct nfs4acl *nfs4acl;
 	SMB4ACE_T *smbace;
 	bool have_special_id = false;
-	int ret;
-	DATA_BLOB blob;
+	int i;
 
 	/* allocate the field of NFS4 aces */
-	nfs4acl = talloc_zero(frame, struct nfs4acl);
+	nfs4acl = talloc_zero(mem_ctx, struct nfs4acl);
 	if(nfs4acl == NULL) {
-		TALLOC_FREE(frame);
 		errno = ENOMEM;
 		return false;
 	}
 
 	nfs4acl->a_count = smb_get_naces(smbacl);
 
-	nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace, nfs4acl->a_count);
+	nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace,
+					 nfs4acl->a_count);
 	if(nfs4acl->ace == NULL) {
-		TALLOC_FREE(frame);
+		TALLOC_FREE(nfs4acl);
 		errno = ENOMEM;
 		return false;
 	}
@@ -239,26 +238,93 @@ static bool nfs4_process_smbacl(vfs_handle_struct *handle, files_struct *fsp, SM
 		}
 	}
 
-	if (!have_special_id
-	    && lp_parm_bool(fsp->conn->params->service, "nfs4acl_xattr",
-			    "denymissingspecial", false)) {
-		TALLOC_FREE(frame);
+	if (!have_special_id && denymissingspecial) {
+		TALLOC_FREE(nfs4acl);
 		errno = EACCES;
 		return false;
 	}
 
 	SMB_ASSERT(i == nfs4acl->a_count);
 
+	*pnfs4acl = nfs4acl;
+	return true;
+}
+
+static bool nfs4acl_xattr_set_smb4acl(vfs_handle_struct *handle,
+				      const char *path,
+				      SMB4ACL_T *smbacl)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct nfs4acl *nfs4acl;
+	int ret;
+	bool denymissingspecial;
+	DATA_BLOB blob;
+
+	denymissingspecial = lp_parm_bool(handle->conn->params->service,
+					  "nfs4acl_xattr",
+					  "denymissingspecial", false);
+
+	if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
+				     denymissingspecial)) {
+		DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
+		TALLOC_FREE(frame);
+		return false;
+	}
+
 	blob = nfs4acl_acl2blob(frame, nfs4acl);
 	if (!blob.data) {
-		DEBUG(0, ("Failed to convert ACL to linear blob for xattr storage\n"));
+		DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
 		TALLOC_FREE(frame);
 		errno = EINVAL;
 		return false;
 	}
-	ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_XATTR_NAME, blob.data, blob.length, 0);
+	ret = SMB_VFS_NEXT_SETXATTR(handle, path, NFS4ACL_XATTR_NAME,
+				    blob.data, blob.length, 0);
+	if (ret != 0) {
+		DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
+	}
 	TALLOC_FREE(frame);
+	return ret == 0;
+}
 
+/* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */
+static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle,
+				       files_struct *fsp,
+				       SMB4ACL_T *smbacl)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct nfs4acl *nfs4acl;
+	int ret;
+	bool denymissingspecial;
+	DATA_BLOB blob;
+
+	denymissingspecial = lp_parm_bool(fsp->conn->params->service,
+					  "nfs4acl_xattr",
+					  "denymissingspecial", false);
+
+	if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
+				     denymissingspecial)) {
+		DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
+		TALLOC_FREE(frame);
+		return false;
+	}
+
+	blob = nfs4acl_acl2blob(frame, nfs4acl);
+	if (!blob.data) {
+		DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
+		TALLOC_FREE(frame);
+		errno = EINVAL;
+		return false;
+	}
+	if (fsp->fh->fd == -1) {
+		DEBUG(0, ("Error: fsp->fh->fd == -1\n"));
+	}
+	ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_XATTR_NAME,
+				     blob.data, blob.length, 0);
+	if (ret != 0) {
+		DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
+	}
+	TALLOC_FREE(frame);
 	return ret == 0;
 }
 
@@ -271,7 +337,180 @@ static NTSTATUS nfs4_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
 			   const struct security_descriptor *psd)
 {
 	return smb_set_nt_acl_nfs4(handle, fsp, security_info_sent, psd,
-			nfs4_process_smbacl);
+			nfs4acl_xattr_fset_smb4acl);
+}
+
+static SMB4ACL_T *nfs4acls_defaultacl(TALLOC_CTX *mem_ctx)
+{
+	SMB4ACL_T *pacl = NULL;
+	SMB4ACE_T *pace;
+	SMB_ACE4PROP_T ace = { SMB_ACE4_ID_SPECIAL,
+		SMB_ACE4_WHO_EVERYONE,
+		SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
+		0,
+		SMB_ACE4_ALL_MASKS };
+
+	DEBUG(10, ("Building default full access acl\n"));
+
+	pacl = smb_create_smb4acl(mem_ctx);
+	if (pacl == NULL) {
+		DEBUG(0, ("talloc failed\n"));
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	pace = smb_add_ace4(pacl, &ace);
+	if (pace == NULL) {
+		DEBUG(0, ("talloc failed\n"));
+		TALLOC_FREE(pacl);
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	return pacl;
+}
+
+/*
+ * Because there is no good way to guarantee that a new xattr will be
+ * created on file creation there might be no acl xattr on a file when
+ * trying to read the acl. In this case the acl xattr will get
+ * constructed at that time from the parent acl.
+ * If the parent ACL doesn't have an xattr either the call will
+ * recurse to the next parent directory until the share root is
+ * reached. If the share root doesn't contain an ACL xattr either a
+ * default ACL will be used.
+ * Also a default ACL will be set if a non inheriting ACL is encountered.
+ *
+ * Basic algorithm:
+ *   read acl xattr blob
+ *   if acl xattr blob doesn't exist
+ *     stat current directory to know if it's a file or directory
+ *     read acl xattr blob from parent dir
+ *     acl xattr blob to smb nfs4 acl
+ *     calculate inherited smb nfs4 acl
+ *     without inheritance use default smb nfs4 acl
+ *     smb nfs4 acl to acl xattr blob
+ *     set acl xattr blob
+ *     return smb nfs4 acl
+ *   else
+ *     acl xattr blob to smb nfs4 acl
+ *
+ * Todo: Really use mem_ctx after fixing interface of nfs4_acls
+ */
+static SMB4ACL_T *nfs4acls_inheritacl(vfs_handle_struct *handle,
+	const char *path,
+	TALLOC_CTX *mem_ctx)
+{
+	char *parent_dir = NULL;
+	SMB4ACL_T *pparentacl = NULL;
+	SMB4ACL_T *pchildacl = NULL;
+	SMB4ACE_T *pace;
+	SMB_ACE4PROP_T ace;
+	bool isdir;
+	struct smb_filename *smb_fname = NULL;
+	NTSTATUS status;
+	int ret;
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	DEBUG(10, ("nfs4acls_inheritacl invoked for %s\n", path));
+	smb_fname = synthetic_smb_fname(frame, path, NULL, NULL);
+	if (smb_fname == NULL) {
+		TALLOC_FREE(frame);
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	ret = SMB_VFS_STAT(handle->conn, smb_fname);
+	if (ret == -1) {
+		DEBUG(0,("nfs4acls_inheritacl: failed to stat "
+			 "directory %s. Error was %s\n",
+			 smb_fname_str_dbg(smb_fname),
+			 strerror(errno)));
+		TALLOC_FREE(frame);
+		return NULL;
+	}
+	isdir = S_ISDIR(smb_fname->st.st_ex_mode);
+
+	if (!parent_dirname(talloc_tos(),
+			    path,
+			    &parent_dir,
+			    NULL)) {
+		TALLOC_FREE(frame);
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	status = nfs4_get_nfs4_acl(handle, frame, parent_dir, &pparentacl);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)
+	    && strncmp(parent_dir, ".", 2) != 0) {
+		pparentacl = nfs4acls_inheritacl(handle, parent_dir,
+						 frame);
+	}
+	else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+		pparentacl = nfs4acls_defaultacl(frame);
+
+	}
+	else if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
+		return NULL;
+	}
+
+	pchildacl = smb_create_smb4acl(mem_ctx);
+	if (pchildacl == NULL) {
+		DEBUG(0, ("talloc failed\n"));
+		TALLOC_FREE(frame);
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	for (pace = smb_first_ace4(pparentacl); pace != NULL;
+	     pace = smb_next_ace4(pace)) {
+		SMB4ACE_T *pchildace;
+		ace = *smb_get_ace4(pace);
+		if (isdir && !(ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
+		    || !isdir && !(ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
+			DEBUG(10, ("non inheriting ace type: %d, iflags: %x, "
+				   "flags: %x, mask: %x, who: %d\n",
+				   ace.aceType, ace.flags, ace.aceFlags,
+				   ace.aceMask, ace.who.id));
+			continue;
+		}
+		DEBUG(10, ("inheriting ace type: %d, iflags: %x, "
+			   "flags: %x, mask: %x, who: %d\n",
+			   ace.aceType, ace.flags, ace.aceFlags,
+			   ace.aceMask, ace.who.id));
+		ace.aceFlags |= SMB_ACE4_INHERITED_ACE;
+		if ((isdir && (ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
+		     || !isdir && (ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE))
+		    && ace.aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) {
+			ace.aceFlags &= ~SMB_ACE4_INHERIT_ONLY_ACE;
+		}
+		if (ace.aceFlags & SMB_ACE4_NO_PROPAGATE_INHERIT_ACE) {
+			ace.aceFlags &= ~SMB_ACE4_FILE_INHERIT_ACE;
+			ace.aceFlags &= ~SMB_ACE4_DIRECTORY_INHERIT_ACE;
+			ace.aceFlags &= ~SMB_ACE4_NO_PROPAGATE_INHERIT_ACE;
+		}
+		pchildace = smb_add_ace4(pchildacl, &ace);
+		if (pchildace == NULL) {
+			DEBUG(0, ("talloc failed\n"));
+			TALLOC_FREE(frame);
+			errno = ENOMEM;
+			return NULL;
+		}
+	}
+
+	/* Set a default ACL if we didn't inherit anything. */
+	if (smb_first_ace4(pchildacl) == NULL) {
+		TALLOC_FREE(pchildacl);
+		pchildacl = nfs4acls_defaultacl(mem_ctx);
+	}
+
+	/* store the returned ACL to get it directly in the
+	   future and avoid dynamic inheritance behavior. */
+	nfs4acl_xattr_set_smb4acl(handle, path, pchildacl);
+
+	TALLOC_FREE(frame);
+	return pchildacl;
 }
 
 static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
@@ -285,11 +524,11 @@ static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
 	TALLOC_CTX *frame = talloc_stackframe();
 
 	status = nfs4_fget_nfs4_acl(handle, frame, fsp, &pacl);
-	if (!NT_STATUS_IS_OK(status)) {
-		if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
-			status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
-							  mem_ctx, ppdesc);
-		}
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+		pacl = nfs4acls_inheritacl(handle, fsp->fsp_name->base_name,
+					   frame);
+	}
+	else if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(frame);
 		return status;
 	}
@@ -310,14 +549,9 @@ static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle,
 
 	status = nfs4_get_nfs4_acl(handle, frame, name, &pacl);
 	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
-		if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
-			status = SMB_VFS_NEXT_GET_NT_ACL(handle, name, security_info,
-							 mem_ctx, ppdesc);
-		}
-		TALLOC_FREE(frame);
-		return status;
+		pacl = nfs4acls_inheritacl(handle, name, frame);
 	}
-	if (!NT_STATUS_IS_OK(status)) {
+	else if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(frame);
 		return status;
 	}
-- 
1.8.2.1


From c9ec4ceb144f921d0acc97d44669d3f4a7a45591 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Thu, 18 Apr 2013 14:12:34 +0200
Subject: [PATCH 10/26] s4-smbtorture: Set result message when failing the
 inheritance test.

Reviewed-By: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source4/torture/raw/acls.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/source4/torture/raw/acls.c b/source4/torture/raw/acls.c
index 0342bf9..360d937 100644
--- a/source4/torture/raw/acls.c
+++ b/source4/torture/raw/acls.c
@@ -1843,6 +1843,13 @@ done:
 	smbcli_rmdir(cli->tree, dname);
 	smb_raw_exit(cli->session);
 	smbcli_deltree(cli->tree, BASEDIR);
+
+	if (!ret) {
+		torture_result(tctx,
+			TORTURE_FAIL, "(%s) test_inheritance\n",
+			__location__);
+	}
+
 	return ret;
 }
 
-- 
1.8.2.1


From 36a320d4ffd50d5f3be7371656661a300ae8b408 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Mon, 15 Apr 2013 16:08:46 +0200
Subject: [PATCH 11/26] s3: Move up declaration of params struct and related
 function.

    We need the parameters earlier in the code so we move up
    the declaration of the params struct. Since reading the
    parameters is closely related the definition of the function
    smbacl4_get_vfs_params has also been moved up.

Reviewed-By: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c | 98 ++++++++++++++++++++++-----------------------
 1 file changed, 49 insertions(+), 49 deletions(-)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index fa6b2fe..9d0651b 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -54,6 +54,55 @@ typedef struct _SMB_ACL4_INT_T
 	SMB_ACE4_INT_T	*last;
 } SMB_ACL4_INT_T;
 
+enum smbacl4_mode_enum {e_simple=0, e_special=1};
+enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3};
+
+typedef struct _smbacl4_vfs_params {
+	enum smbacl4_mode_enum mode;
+	bool do_chown;
+	enum smbacl4_acedup_enum acedup;
+} smbacl4_vfs_params;
+
+/*
+ * Gather special parameters for NFS4 ACL handling
+ */
+static int smbacl4_get_vfs_params(
+	const char *type_name,
+	files_struct *fsp,
+	smbacl4_vfs_params *params
+)
+{
+	static const struct enum_list enum_smbacl4_modes[] = {
+		{ e_simple, "simple" },
+		{ e_special, "special" },
+		{ -1 , NULL }
+	};
+	static const struct enum_list enum_smbacl4_acedups[] = {
+		{ e_dontcare, "dontcare" },
+		{ e_reject, "reject" },
+		{ e_ignore, "ignore" },
+		{ e_merge, "merge" },
+		{ -1 , NULL }
+	};
+
+	memset(params, 0, sizeof(smbacl4_vfs_params));
+	params->mode = (enum smbacl4_mode_enum)lp_parm_enum(
+		SNUM(fsp->conn), type_name,
+		"mode", enum_smbacl4_modes, e_simple);
+	params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name,
+		"chown", true);
+	params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum(
+		SNUM(fsp->conn), type_name,
+		"acedup", enum_smbacl4_acedups, e_dontcare);
+
+	DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n",
+		enum_smbacl4_modes[params->mode].name,
+		params->do_chown ? "true" : "false",
+		enum_smbacl4_acedups[params->acedup].name));
+
+	return 0;
+}
+
 /************************************************
  Split the ACE flag mapping between nfs4 and Windows
  into two separate functions rather than trying to do
@@ -462,55 +511,6 @@ NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
 					  theacl);
 }
 
-enum smbacl4_mode_enum {e_simple=0, e_special=1};
-enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3};
-
-typedef struct _smbacl4_vfs_params {
-	enum smbacl4_mode_enum mode;
-	bool do_chown;
-	enum smbacl4_acedup_enum acedup;
-} smbacl4_vfs_params;
-
-/*
- * Gather special parameters for NFS4 ACL handling
- */
-static int smbacl4_get_vfs_params(
-	const char *type_name,
-	files_struct *fsp,
-	smbacl4_vfs_params *params
-)
-{
-	static const struct enum_list enum_smbacl4_modes[] = {
-		{ e_simple, "simple" },
-		{ e_special, "special" },
-		{ -1 , NULL }
-	};
-	static const struct enum_list enum_smbacl4_acedups[] = {
-		{ e_dontcare, "dontcare" },
-		{ e_reject, "reject" },
-		{ e_ignore, "ignore" },
-		{ e_merge, "merge" },
-		{ -1 , NULL }
-	};
-
-	memset(params, 0, sizeof(smbacl4_vfs_params));
-	params->mode = (enum smbacl4_mode_enum)lp_parm_enum(
-		SNUM(fsp->conn), type_name,
-		"mode", enum_smbacl4_modes, e_simple);
-	params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name,
-		"chown", True);
-	params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum(
-		SNUM(fsp->conn), type_name,
-		"acedup", enum_smbacl4_acedups, e_dontcare);
-
-	DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n",
-		enum_smbacl4_modes[params->mode].name,
-		params->do_chown ? "true" : "false",
-		enum_smbacl4_acedups[params->acedup].name));
-
-	return 0;
-}
-
 static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *theacl)
 {
 	SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
-- 
1.8.2.1


From c540877bc67477c2ae0d87ac5a41eac260eb6105 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Thu, 26 Jul 2012 17:11:03 +0200
Subject: [PATCH 12/26] s3: Change smbacl4_get_vfs_params to use
 connection_struct instead of fsp.

Reviewed-By: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index 9d0651b..ceaeafb 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -68,7 +68,7 @@ typedef struct _smbacl4_vfs_params {
  */
 static int smbacl4_get_vfs_params(
 	const char *type_name,
-	files_struct *fsp,
+	struct connection_struct *conn,
 	smbacl4_vfs_params *params
 )
 {
@@ -87,12 +87,12 @@ static int smbacl4_get_vfs_params(
 
 	memset(params, 0, sizeof(smbacl4_vfs_params));
 	params->mode = (enum smbacl4_mode_enum)lp_parm_enum(
-		SNUM(fsp->conn), type_name,
+		SNUM(conn), type_name,
 		"mode", enum_smbacl4_modes, e_simple);
-	params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name,
+	params->do_chown = lp_parm_bool(SNUM(conn), type_name,
 		"chown", true);
 	params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum(
-		SNUM(fsp->conn), type_name,
+		SNUM(conn), type_name,
 		"acedup", enum_smbacl4_acedups, e_dontcare);
 
 	DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n",
@@ -765,7 +765,8 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 	}
 
 	/* Special behaviours */
-	if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, &params)) {
+	if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME,
+				   fsp->conn, &params)) {
 		TALLOC_FREE(frame);
 		return NT_STATUS_NO_MEMORY;
 	}
-- 
1.8.2.1


From e2204c99242dd6b2e98c3562ae81d69b2505f506 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Thu, 26 Jul 2012 17:29:12 +0200
Subject: [PATCH 13/26] s3: Add params parameter to smbacl4_nfs42win function.

Reviewed-By: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index ceaeafb..f7a37dc 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -307,7 +307,9 @@ static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf)
 	return 0;
 }
 
-static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *theacl, /* in */
+static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
+	smbacl4_vfs_params *params,
+	SMB4ACL_T *theacl, /* in */
 	struct dom_sid *psid_owner, /* in */
 	struct dom_sid *psid_group, /* in */
 	bool is_directory, /* in */
@@ -417,10 +419,13 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *theacl, /* in */
 }
 
 static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
-					   uint32 security_info, TALLOC_CTX *mem_ctx,
-	struct security_descriptor **ppdesc, SMB4ACL_T *theacl)
+					   smbacl4_vfs_params *params,
+					   uint32 security_info,
+					   TALLOC_CTX *mem_ctx,
+					   struct security_descriptor **ppdesc,
+					   SMB4ACL_T *theacl)
 {
-	int	good_aces = 0;
+	int good_aces = 0;
 	struct dom_sid sid_owner, sid_group;
 	size_t sd_size = 0;
 	struct security_ace *nt_ace_list = NULL;
@@ -437,7 +442,7 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
 	uid_to_sid(&sid_owner, sbuf->st_ex_uid);
 	gid_to_sid(&sid_group, sbuf->st_ex_gid);
 
-	if (smbacl4_nfs42win(mem_ctx, theacl, &sid_owner, &sid_group,
+	if (smbacl4_nfs42win(mem_ctx, params, theacl, &sid_owner, &sid_group,
 			     S_ISDIR(sbuf->st_ex_mode),
 				&nt_ace_list, &good_aces)==False) {
 		DEBUG(8,("smbacl4_nfs42win failed\n"));
@@ -479,6 +484,7 @@ NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
 			      SMB4ACL_T *theacl)
 {
 	SMB_STRUCT_STAT sbuf;
+	smbacl4_vfs_params params;
 
 	DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
 
@@ -486,9 +492,13 @@ NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
 		return map_nt_error_from_unix(errno);
 	}
 
-	return smb_get_nt_acl_nfs4_common(&sbuf, security_info,
-					  mem_ctx, ppdesc,
-					  theacl);
+	/* Special behaviours */
+	if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp->conn, &params)) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	return smb_get_nt_acl_nfs4_common(&sbuf, &params, security_info,
+					  mem_ctx, ppdesc, theacl);
 }
 
 NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
@@ -499,6 +509,7 @@ NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
 			     SMB4ACL_T *theacl)
 {
 	SMB_STRUCT_STAT sbuf;
+	smbacl4_vfs_params params;
 
 	DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", name));
 
@@ -506,9 +517,13 @@ NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
 		return map_nt_error_from_unix(errno);
 	}
 
-	return smb_get_nt_acl_nfs4_common(&sbuf, security_info,
-					  mem_ctx, ppdesc,
-					  theacl);
+	/* Special behaviours */
+	if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, conn, &params)) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	return smb_get_nt_acl_nfs4_common(&sbuf, &params, security_info,
+					  mem_ctx, ppdesc, theacl);
 }
 
 static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *theacl)
@@ -548,7 +563,7 @@ static SMB_ACE4PROP_T *smbacl4_find_equal_special(
 	     aceint=(SMB_ACE4_INT_T *)aceint->next) {
 		SMB_ACE4PROP_T *ace = &aceint->prop;
 
-                DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
+		DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
 			  "new type:0x%x flags:0x%x aceFlags:0x%x\n",
 			  ace->aceType, ace->flags, ace->aceFlags,
 			  aceNew->aceType, aceNew->flags,aceNew->aceFlags));
-- 
1.8.2.1


From 14ab3e69edcd2d8670a3b1b4d2ccc54eb7872e69 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Wed, 25 Apr 2012 15:10:20 +0200
Subject: [PATCH 14/26] s3: Mapping of special entries to creator owner in mode
 simple.

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c | 66 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 6 deletions(-)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index f7a37dc..3214a28 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -326,10 +326,11 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
 
 	aclint = get_validated_aclint(theacl);
 	/* We do not check for naces being 0 or theacl being NULL here
-	 * because it is done upstream */
-	/* in smb_get_nt_acl_nfs4(). */
+	   because it is done upstream in smb_get_nt_acl_nfs4().
+	   We reserve twice the number of input aces because one nfs4
+	   ace might result in 2 nt aces.*/
 	nt_ace_list = (struct security_ace *)TALLOC_ZERO_SIZE(
-		mem_ctx, aclint->naces * sizeof(struct security_ace));
+		mem_ctx, 2 * aclint->naces * sizeof(struct security_ace));
 	if (nt_ace_list==NULL)
 	{
 		DEBUG(10, ("talloc error"));
@@ -407,9 +408,62 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
 		if(ace->aceType == SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE) {
 			mask = ace->aceMask | SMB_ACE4_SYNCHRONIZE;
 		}
-		init_sec_ace(&nt_ace_list[good_aces++], &sid,
-			ace->aceType, mask,
-			win_ace_flags);
+
+		/* Mapping of owner@ and group@ to creator owner and
+		   creator group. Keep old behavior in mode special. */
+		if (params->mode != e_special &&
+		    ace->flags & SMB_ACE4_ID_SPECIAL &&
+		    (ace->who.special_id == SMB_ACE4_WHO_OWNER ||
+		     ace->who.special_id == SMB_ACE4_WHO_GROUP)) {
+			DEBUG(10, ("Map special entry\n"));
+			if (!(win_ace_flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
+				DEBUG(10, ("Map current sid\n"));
+				uint32_t win_ace_flags_current;
+				win_ace_flags_current = win_ace_flags &
+					~(SEC_ACE_FLAG_OBJECT_INHERIT |
+					  SEC_ACE_FLAG_CONTAINER_INHERIT);
+				init_sec_ace(&nt_ace_list[good_aces++], &sid,
+					     ace->aceType, mask,
+					     win_ace_flags_current);
+			}
+			if (ace->who.special_id == SMB_ACE4_WHO_OWNER &&
+			    win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
+					     SEC_ACE_FLAG_CONTAINER_INHERIT)) {
+				uint32_t win_ace_flags_creator;
+				DEBUG(10, ("Map creator owner\n"));
+				win_ace_flags_creator = win_ace_flags |
+					SMB_ACE4_INHERIT_ONLY_ACE;
+				init_sec_ace(&nt_ace_list[good_aces++],
+					     &global_sid_Creator_Owner,
+					     ace->aceType, mask,
+					     win_ace_flags_creator);
+			}
+			if (ace->who.special_id == SMB_ACE4_WHO_GROUP &&
+			    win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
+					     SEC_ACE_FLAG_CONTAINER_INHERIT)) {
+				uint32_t win_ace_flags_creator;
+				DEBUG(10, ("Map creator owner group\n"));
+				win_ace_flags_creator = win_ace_flags |
+					SMB_ACE4_INHERIT_ONLY_ACE;
+				init_sec_ace(&nt_ace_list[good_aces++],
+					     &global_sid_Creator_Group,
+					     ace->aceType, mask,
+					     win_ace_flags_creator);
+			}
+		} else {
+			DEBUG(10, ("Map normal sid\n"));
+			init_sec_ace(&nt_ace_list[good_aces++], &sid,
+				     ace->aceType, mask,
+				     win_ace_flags);
+		}
+	}
+
+	nt_ace_list = (struct security_ace *)TALLOC_REALLOC(mem_ctx,
+					nt_ace_list,
+					good_aces * sizeof(struct security_ace));
+	if (nt_ace_list == NULL) {
+		errno = ENOMEM;
+		return false;
 	}
 
 	*ppnt_ace_list = nt_ace_list;
-- 
1.8.2.1


From 6f9e6ee041ab4c648d583f02434bf46370fd2c6b Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Thu, 10 May 2012 14:19:41 +0200
Subject: [PATCH 15/26] s3: Mapping of cifs creator owner to nfs owner@ ace.

This is ignored in nfs4mode special for compatibility.
Also ensure that we drop non inheriting creator owner
aces since these don't contribute to who can access
a file.

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index 3214a28..d3b9aff 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -694,6 +694,30 @@ static bool smbacl4_fill_ace4(
 	if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) {
 		ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE;
 		ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
+	} else if (params->mode!=e_special &&
+		   dom_sid_equal(&ace_nt->trustee,
+				 &global_sid_Creator_Owner)) {
+		DEBUG(10, ("Map creator owner\n"));
+		ace_v4->who.special_id = SMB_ACE4_WHO_OWNER;
+		ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
+		/* A non inheriting creator owner entry has no effect. */
+		ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
+		if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
+		    && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
+			return False;
+		}
+	} else if (params->mode!=e_special &&
+		   dom_sid_equal(&ace_nt->trustee,
+				 &global_sid_Creator_Group)) {
+		DEBUG(10, ("Map creator owner group\n"));
+		ace_v4->who.special_id = SMB_ACE4_WHO_GROUP;
+		ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
+		/* A non inheriting creator group entry has no effect. */
+		ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
+		if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
+		    && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
+			return False;
+		}
 	} else {
 		uid_t uid;
 		gid_t gid;
-- 
1.8.2.1


From 3ce044aab84c1359839e9ff6d498719dc95042ca Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Thu, 2 May 2013 16:50:55 +0200
Subject: [PATCH 16/26] s3: Add changes that keep nfs4:mode special behavior.

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index d3b9aff..e906fcd 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -601,7 +601,7 @@ static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *theacl)
 	}
 }
 
-/* 
+/*
  * Find 2 NFS4 who-special ACE property (non-copy!!!)
  * match nonzero if "special" and who is equal
  * return ace if found matching; otherwise NULL
@@ -784,6 +784,42 @@ static int smbacl4_MergeIgnoreReject(
 	return result;
 }
 
+static int smbacl4_substitute_special(
+	SMB4ACL_T *theacl,
+	uid_t ownerUID,
+	gid_t ownerGID
+)
+{
+	SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
+	SMB_ACE4_INT_T *aceint;
+
+	for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
+		SMB_ACE4PROP_T *ace = &aceint->prop;
+
+		DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
+			  "mask: %x, who: %d\n",
+			  ace->aceType, ace->flags, ace->aceFlags,
+			  ace->aceMask, ace->who.id));
+
+		if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
+		    !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
+		    ace->who.uid == ownerUID) {
+			ace->flags |= SMB_ACE4_ID_SPECIAL;
+			ace->who.special_id = SMB_ACE4_WHO_OWNER;
+			DEBUG(10,("replaced with special owner ace\n"));
+		}
+
+		if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
+		    ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
+		    ace->who.uid == ownerGID) {
+			ace->flags |= SMB_ACE4_ID_SPECIAL;
+			ace->who.special_id = SMB_ACE4_WHO_GROUP;
+			DEBUG(10,("replaced with special group ace\n"));
+		}
+	}
+	return True; /* OK */
+}
+
 static SMB4ACL_T *smbacl4_win2nfs4(
 	TALLOC_CTX *mem_ctx,
 	const files_struct *fsp,
@@ -826,6 +862,10 @@ static SMB4ACL_T *smbacl4_win2nfs4(
 			smb_add_ace4(theacl, &ace_v4);
 	}
 
+	if (pparams->mode==e_special) {
+		smbacl4_substitute_special(theacl, ownerUID, ownerGID);
+	}
+
 	return theacl;
 }
 
-- 
1.8.2.1


From cf09f6daed27bb63283bcf713f4f8a42a125e438 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Thu, 2 May 2013 16:53:35 +0200
Subject: [PATCH 17/26] s3: Use mode bits in some cases in mode simple.

Non inheriting ACL entries will show mode bits.
With this an file owner change does affect the effective ACL because
the special owner acl will now refer to the new owner.
This could be fixed by updating the ACL on a file owner change.

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/nfs4_acls.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index e906fcd..3f6d8d8 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -820,6 +820,48 @@ static int smbacl4_substitute_special(
 	return True; /* OK */
 }
 
+static int smbacl4_substitute_simple(
+	SMB4ACL_T *theacl,
+	uid_t ownerUID,
+	gid_t ownerGID
+)
+{
+	SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
+	SMB_ACE4_INT_T *aceint;
+
+	for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
+		SMB_ACE4PROP_T *ace = &aceint->prop;
+
+		DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
+			  "mask: %x, who: %d\n",
+			  ace->aceType, ace->flags, ace->aceFlags,
+			  ace->aceMask, ace->who.id));
+
+		if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
+		    !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
+		    ace->who.uid == ownerUID &&
+		    !(ace->aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) &&
+		    !(ace->aceFlags & SMB_ACE4_FILE_INHERIT_ACE) &&
+		    !(ace->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) {
+			ace->flags |= SMB_ACE4_ID_SPECIAL;
+			ace->who.special_id = SMB_ACE4_WHO_OWNER;
+			DEBUG(10,("replaced with special owner ace\n"));
+		}
+
+		if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
+		    ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
+		    ace->who.uid == ownerGID &&
+		    !(ace->aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) &&
+		    !(ace->aceFlags & SMB_ACE4_FILE_INHERIT_ACE) &&
+		    !(ace->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) {
+			ace->flags |= SMB_ACE4_ID_SPECIAL;
+			ace->who.special_id = SMB_ACE4_WHO_GROUP;
+			DEBUG(10,("replaced with special group ace\n"));
+		}
+	}
+	return True; /* OK */
+}
+
 static SMB4ACL_T *smbacl4_win2nfs4(
 	TALLOC_CTX *mem_ctx,
 	const files_struct *fsp,
@@ -862,6 +904,10 @@ static SMB4ACL_T *smbacl4_win2nfs4(
 			smb_add_ace4(theacl, &ace_v4);
 	}
 
+	if (pparams->mode==e_simple) {
+		smbacl4_substitute_simple(theacl, ownerUID, ownerGID);
+	}
+
 	if (pparams->mode==e_special) {
 		smbacl4_substitute_special(theacl, ownerUID, ownerGID);
 	}
-- 
1.8.2.1


From 919225b47dbed54fd48f929e2b8156528645ccc6 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Thu, 2 May 2013 17:45:23 +0200
Subject: [PATCH 18/26] s3: Update README.nfs4acls.txt

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/README.nfs4acls.txt | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/source3/modules/README.nfs4acls.txt b/source3/modules/README.nfs4acls.txt
index 1cb0887..3594aaf 100644
--- a/source3/modules/README.nfs4acls.txt
+++ b/source3/modules/README.nfs4acls.txt
@@ -1,7 +1,7 @@
 Configuring NFS4 ACLs in Samba3
 ===============================
 Created: Peter Somogyi, 2006-JUN-06
-Last modified: Peter Somogyi, 2006-JUL-20
+Last modified: Alexander Werth, 2013-MAY-02
 Revision no.: 4 
 -------------------------------
 
@@ -13,13 +13,20 @@ Each parameter must have a prefix "nfs4:".
 Each one affects the behaviour only when _setting_ an acl on a file/dir:
 
 mode = [simple|special]
-- simple: don't use OWNER@ and GROUP@ special IDs in ACEs. - default
-- special: use OWNER@ and GROUP@ special IDs in ACEs instead of simple user&group ids.
-Note: EVERYONE@ is always processed (if found such an ACE).
-Note2: special mode will have side effect when _only_ chown is performed. Later this may be worked out.
-
-Use "simple" mode when the share is used mainly by windows users and unix side is not significant. You will loose unix bits in this case.
-It's strongly advised setting "store dos attributes = yes" in smb.conf.
+- simple: Use OWNER@ and GROUP@ special IDs for non inheriting ACEs only.
+  This mode is the default.
+- special: use OWNER@ and GROUP@ special IDs in ACEs instead of simple
+  user&group ids. This mode is deprecated.
+
+Note1: EVERYONE@ is always processed (if found such an ACE).
+Note2: There is a side effect when _only_ chown is performed.
+       Later this may be worked out.
+Note3: Mode special inherits incorrect ACL entries when the user creating
+       a file is different from the owner of the caurrent folder.
+Note4: Mode simple uses inheriting OWNER@ and GROUP@ special IDs to
+       support Creator Owner and Creator Group.
+
+It's strongly advised to set "store dos attributes = yes" in smb.conf.
 
 chown = [true|false]
 - true => enable changing owner and group - default.
-- 
1.8.2.1


From 9f7de2a0e9217f0c2d9454c2e25953335f43c196 Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Fri, 3 May 2013 05:46:25 +0200
Subject: [PATCH 19/26] s3: Update vfs_gpfs man page with new nfs4:mode help
 text.

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 docs-xml/manpages/vfs_gpfs.8.xml | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/docs-xml/manpages/vfs_gpfs.8.xml b/docs-xml/manpages/vfs_gpfs.8.xml
index 3ddf946..7f560ca 100644
--- a/docs-xml/manpages/vfs_gpfs.8.xml
+++ b/docs-xml/manpages/vfs_gpfs.8.xml
@@ -311,16 +311,16 @@
 		<term>nfs4:mode = [ simple | special ]</term>
 		<listitem>
 		<para>
-		Enable/Disable substitution of special IDs on GPFS. This parameter
-		should not affect the windows users in anyway. It only ensures that Samba
-		sets the special IDs - OWNER@ and GROUP@ ( mappings to simple uids )
-		that are relevant to GPFS.
+		Controls substitution of special IDs (OWNER@ and GROUP@) on GPFS.
+                The use of mode simple is recommended.
+                In this mode only non inheriting ACL entries for the file owner
+                and group are mapped to special IDs.
 		</para>
 
 		<para>The following MODEs are understood by the module:</para>
 		<itemizedlist>
-		<listitem><para><command>simple(default)</command> - do not use special IDs in GPFS ACEs</para></listitem>
-		<listitem><para><command>special</command> - use special IDs in GPFS ACEs. </para> </listitem>
+		<listitem><para><command>simple(default)</command> - use OWNER@ and GROUP@ special IDs for non inheriting ACEs only.</para></listitem>
+		<listitem><para><command>special(deprecated)</command> - use OWNER@ and GROUP@ special IDs in ACEs for all file owner and group ACEs.</para></listitem>
 		</itemizedlist>
 		</listitem>
 
-- 
1.8.2.1


From 9d7ea560ab1b45ebcde00457f13646f4a5ea5694 Mon Sep 17 00:00:00 2001
From: Abhidnya Joshi <achirmul at in.ibm.com>
Date: Mon, 22 Apr 2013 10:59:02 +0530
Subject: [PATCH 20/26] s4-smbtorture: Test creator inheritance with nfs4 acls

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 selftest/knownfail         |   1 +
 source4/torture/raw/acls.c | 368 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 369 insertions(+)

diff --git a/selftest/knownfail b/selftest/knownfail
index ba76f48..c5c6596 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -136,6 +136,7 @@
 ^samba4.raw.acls.INHERITFLAGS
 ^samba4.raw.acls.*.create_dir
 ^samba4.raw.acls.*.create_file
+^samba4.raw.acls.*.inherit_creator_group
 ^samba4.smb2.create.*.acldir
 ^samba4.smb2.acls.*.generic
 ^samba4.smb2.acls.*.inheritflags
diff --git a/source4/torture/raw/acls.c b/source4/torture/raw/acls.c
index 360d937..6cedf46 100644
--- a/source4/torture/raw/acls.c
+++ b/source4/torture/raw/acls.c
@@ -2233,6 +2233,370 @@ done:
 	return ret;
 }
 
+static bool test_inherit_creator_owner(struct torture_context *tctx,
+				struct smbcli_state *cli)
+{
+	NTSTATUS status;
+	bool ret = true;
+	union smb_open io;
+	union smb_fileinfo q;
+	union smb_setfileinfo si;
+	struct security_descriptor *sd, *sd1;
+	int fnum = 0;
+	const char *dname = BASEDIR "\\test_creator_owner_dir";
+	const char *fname = BASEDIR "\\test_creator_owner_dir\\testfile";
+	const char *dname1 = BASEDIR "\\test_creator_owner_dir\\testdir";
+	struct dom_sid *sid_world = NULL, *sid_creator = NULL;
+
+	if (!torture_setup_dir(cli, BASEDIR))
+		return false;
+
+	torture_comment(tctx, "TESTING CREATOR OWNER INHERITANCE\n");
+
+	/*Create parent dir with inheritable CREATOR_OWNER ACE */
+	sd = security_descriptor_dacl_create(tctx,
+					     0, NULL, NULL,
+					     SID_WORLD,
+					     SEC_ACE_TYPE_ACCESS_ALLOWED,
+					     SEC_RIGHTS_FILE_ALL,
+					     SEC_ACE_FLAG_OBJECT_INHERIT |
+					     SEC_ACE_FLAG_CONTAINER_INHERIT,
+					     SID_CREATOR_OWNER,
+					     SEC_ACE_TYPE_ACCESS_ALLOWED,
+					     SEC_STD_READ_CONTROL |
+					     SEC_STD_WRITE_DAC |
+					     SEC_STD_WRITE_OWNER,
+					     SEC_ACE_FLAG_OBJECT_INHERIT |
+					     SEC_ACE_FLAG_CONTAINER_INHERIT |
+					     SEC_ACE_FLAG_INHERIT_ONLY,
+					     NULL);
+	io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
+	io.ntcreatex.in.root_fid.fnum = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
+	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access =
+		NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = dname;
+	io.ntcreatex.in.sec_desc = sd;
+	io.ntcreatex.in.ea_list = NULL;
+	status = smb_raw_open(cli->tree, tctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	fnum = io.ntcreatex.out.file.fnum;
+
+	/* Close dir */
+	status = smbcli_close(cli->tree, fnum);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/*Open child file */
+	io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
+	io.ntcreatex.in.root_fid.fnum = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
+	io.ntcreatex.in.create_options = 0;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access =
+		NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = fname;
+	io.ntcreatex.in.ea_list = NULL;
+	io.ntcreatex.in.sec_desc = NULL;
+	status = smb_raw_open(cli->tree, tctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	fnum = io.ntcreatex.out.file.fnum;
+
+	/*Query sec desc */
+	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+	q.query_secdesc.in.file.fnum = fnum;
+	q.query_secdesc.in.secinfo_flags =
+		SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
+	status = smb_raw_fileinfo(cli->tree, tctx, &q);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	sd1 = q.query_secdesc.out.sd;
+	sid_world = dom_sid_parse_talloc(tctx, SID_WORLD);
+
+	/*
+	 * Compare number of aces, trustees and respective masks
+	 * Owner should get new ACE same as CREATOR_OWNER
+	 */
+	if ((sd1->dacl == NULL) || (sd1->dacl->num_aces != 2) ||
+	    (sd1->dacl->aces[0].access_mask != SEC_RIGHTS_FILE_ALL) ||
+	    (sd1->dacl->aces[1].access_mask &
+	     !(SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC |
+		SEC_STD_WRITE_OWNER)) != 0
+	    || !dom_sid_equal(&sd1->dacl->aces[0].trustee, sid_world)
+	    || !dom_sid_equal(&sd1->dacl->aces[1].trustee, sd1->owner_sid)) {
+		torture_warning(tctx, "Bad sd in child file\n");
+		NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
+		ret = false;
+		torture_result(tctx, TORTURE_FAIL,
+			       "(%s) Incorrect Inheritance for Creator Owner\n",
+				__location__);
+		goto done;
+	}
+
+	/* Close file */
+	status = smbcli_close(cli->tree, fnum);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	talloc_free(sd1);
+
+	/* Create child dir */
+	io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
+	io.ntcreatex.in.root_fid.fnum = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
+	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access =
+		NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = dname1;
+	io.ntcreatex.in.ea_list = NULL;
+	io.ntcreatex.in.sec_desc = NULL;
+	status = smb_raw_open(cli->tree, tctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	fnum = io.ntcreatex.out.file.fnum;
+
+	/*Query sec desc */
+	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+	q.query_secdesc.in.file.fnum = fnum;
+	q.query_secdesc.in.secinfo_flags =
+		SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
+	status = smb_raw_fileinfo(cli->tree, tctx, &q);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Comapre aces */
+	sd1 = q.query_secdesc.out.sd;
+	sid_creator = dom_sid_parse_talloc(tctx, SID_CREATOR_OWNER);
+
+	if (sd1->dacl == NULL || sd1->dacl->num_aces != 3 ||
+	    sd1->dacl->aces[0].access_mask != SEC_RIGHTS_FILE_ALL ||
+	    (sd1->dacl->aces[1].access_mask &
+	     !(SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC |
+	       SEC_STD_WRITE_OWNER)) != 0 ||
+	    (sd1->dacl->aces[2].access_mask &
+	     !(SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC |
+	       SEC_STD_WRITE_OWNER)) != 0
+	    || !dom_sid_equal(&sd1->dacl->aces[0].trustee, sid_world)
+	    || !dom_sid_equal(&sd1->dacl->aces[1].trustee, sd1->owner_sid)
+	    || !dom_sid_equal(&sd1->dacl->aces[2].trustee, sid_creator)) {
+		torture_warning(tctx, "Bad sd in child dir\n");
+		NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
+		ret = false;
+		torture_result(tctx, TORTURE_FAIL,
+			       "(%s) Incorrect Inheritance for Creator Owner\n",
+				__location__);
+	}
+
+      done:
+	smbcli_close(cli->tree, fnum);
+	smbcli_unlink(cli->tree, fname);
+	smbcli_unlink(cli->tree, dname1);
+	smbcli_unlink(cli->tree, dname);
+	smb_raw_exit(cli->session);
+	smbcli_deltree(cli->tree, BASEDIR);
+
+	return ret;
+}
+
+static bool test_inherit_creator_group(struct torture_context *tctx,
+			       struct smbcli_state *cli)
+{
+
+	NTSTATUS status;
+	bool ret = true;
+	union smb_open io;
+	union smb_fileinfo q;
+	union smb_setfileinfo si;
+	struct security_descriptor *sd, *sd1;
+	int fnum = 0;
+	const char *dname = BASEDIR "\\test_creator_group_dir";
+	const char *fname = BASEDIR "\\test_creator_group_dir\\testfile";
+	const char *dname1 = BASEDIR "\\test_creator_group_dir\\testdir";
+	struct dom_sid *sid_world = NULL, *sid_creator = NULL;
+
+	if (!torture_setup_dir(cli, BASEDIR))
+		return false;
+
+	torture_comment(tctx, "TESTING CREATOR GROUP\n");
+
+	/*Create parent dir with inheritable CREATOR_GROUP ACE */
+	sd = security_descriptor_dacl_create(tctx,
+					     0, NULL, NULL,
+					     SID_WORLD,
+					     SEC_ACE_TYPE_ACCESS_ALLOWED,
+					     SEC_RIGHTS_FILE_ALL,
+					     SEC_ACE_FLAG_OBJECT_INHERIT |
+					     SEC_ACE_FLAG_CONTAINER_INHERIT,
+					     SID_CREATOR_GROUP,
+					     SEC_ACE_TYPE_ACCESS_ALLOWED,
+					     SEC_STD_READ_CONTROL |
+					     SEC_STD_WRITE_DAC |
+					     SEC_STD_WRITE_OWNER,
+					     SEC_ACE_FLAG_OBJECT_INHERIT |
+					     SEC_ACE_FLAG_CONTAINER_INHERIT |
+					     SEC_ACE_FLAG_INHERIT_ONLY,
+					     NULL);
+
+	io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
+	io.ntcreatex.in.root_fid.fnum = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
+	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access =
+	    NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = dname;
+	io.ntcreatex.in.sec_desc = sd;
+	io.ntcreatex.in.ea_list = NULL;
+	status = smb_raw_open(cli->tree, tctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	fnum = io.ntcreatex.out.file.fnum;
+
+	/* Close dir */
+	status = smbcli_close(cli->tree, fnum);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Open child file */
+	io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
+	io.ntcreatex.in.root_fid.fnum = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
+	io.ntcreatex.in.create_options = 0;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access =
+	    NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = fname;
+	io.ntcreatex.in.ea_list = NULL;
+	io.ntcreatex.in.sec_desc = NULL;
+	status = smb_raw_open(cli->tree, tctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	fnum = io.ntcreatex.out.file.fnum;
+
+	/*Query sec desc */
+	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+	q.query_secdesc.in.file.fnum = fnum;
+	q.query_secdesc.in.secinfo_flags =
+	    SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
+	status = smb_raw_fileinfo(cli->tree, tctx, &q);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/*
+	 * Compare number of aces, trustees and respective masks
+	 * Group should get new ACE same as CREATOR_GROUP
+	 */
+
+	sid_world = dom_sid_parse_talloc(tctx, SID_WORLD);
+	sd1 = q.query_secdesc.out.sd;
+
+	if (sd1->dacl == NULL || sd1->dacl->num_aces != 2 ||
+	    sd1->dacl->aces[0].access_mask != SEC_RIGHTS_FILE_ALL ||
+	    (sd1->dacl->aces[1].access_mask &
+	     !(SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC |
+	       SEC_STD_WRITE_OWNER)) != 0
+	    || !dom_sid_equal(&sd1->dacl->aces[0].trustee, sid_world)
+	    || !dom_sid_equal(&sd1->dacl->aces[1].trustee, sd1->group_sid)) {
+		torture_warning(tctx, "Bad sd in child file\n");
+		NDR_PRINT_DEBUG(security_descriptor, sd1);
+		ret = false;
+		torture_result(tctx, TORTURE_FAIL,
+			       "(%s) Incorrect Inheritance for Creator Group\n",
+			       __location__);
+		goto done;
+	}
+
+	/* Close file */
+	status = smbcli_close(cli->tree, fnum);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/*Open dir */
+	io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
+	io.ntcreatex.in.root_fid.fnum = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
+	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access =
+	    NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = dname1;
+	io.ntcreatex.in.ea_list = NULL;
+	io.ntcreatex.in.sec_desc = NULL;
+	status = smb_raw_open(cli->tree, tctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	fnum = io.ntcreatex.out.file.fnum;
+
+	/*Query sec desc */
+	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+	q.query_secdesc.in.file.fnum = fnum;
+	q.query_secdesc.in.secinfo_flags =
+	    SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
+	status = smb_raw_fileinfo(cli->tree, tctx, &q);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/*
+	 * Compare number of aces, trustees and respective masks
+	 * Group should get new ACE same as CREATOR_GROUP
+	 */
+
+	talloc_free(sd1);
+	sid_creator = dom_sid_parse_talloc(tctx, SID_CREATOR_GROUP);
+	sd1 = q.query_secdesc.out.sd;
+
+	if (sd1->dacl == NULL || sd1->dacl->num_aces != 3 ||
+	    sd1->dacl->aces[0].access_mask != SEC_RIGHTS_FILE_ALL
+	    || (sd1->dacl->aces[1].access_mask &
+		!(SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC |
+		  SEC_STD_WRITE_OWNER)) != 0
+	    || (sd1->dacl->aces[2].access_mask &
+		!(SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC |
+		  SEC_STD_WRITE_OWNER)) != 0
+	    || !dom_sid_equal(&sd1->dacl->aces[0].trustee, sid_world)
+	    || !dom_sid_equal(&sd1->dacl->aces[1].trustee, sd1->group_sid)
+	    || !dom_sid_equal(&sd1->dacl->aces[2].trustee, sid_creator)) {
+		torture_warning(tctx, "Bad sd in child dir\n");
+		NDR_PRINT_DEBUG(security_descriptor, sd1);
+		ret = false;
+		torture_result(tctx, TORTURE_FAIL,
+			       "(%s) Incorrect Inheritance for Creator Group\n",
+			       __location__);
+		goto done;
+	}
+
+      done:
+	smbcli_close(cli->tree, fnum);
+	smbcli_unlink(cli->tree, fname);
+	smbcli_unlink(cli->tree, dname);
+	smbcli_unlink(cli->tree, dname1);
+	smb_raw_exit(cli->session);
+	smbcli_deltree(cli->tree, BASEDIR);
+
+	return ret;
+}
+
 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
 	if (!(bits & desired_64)) {\
 		CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
@@ -2472,6 +2836,10 @@ struct torture_suite *torture_raw_acls(TALLOC_CTX *mem_ctx)
 
 	torture_suite_add_1smb_test(suite, "INHERITFLAGS", test_inheritance_flags);
 	torture_suite_add_1smb_test(suite, "dynamic", test_inheritance_dynamic);
+	torture_suite_add_1smb_test(suite, "inherit_creator_owner",
+					test_inherit_creator_owner);
+	torture_suite_add_1smb_test(suite, "inherit_creator_group",
+					test_inherit_creator_group);
 #if 0
 	/* XXX This test does not work against XP or Vista. */
 	torture_suite_add_1smb_test(suite, "GETSET", test_sd_get_set);
-- 
1.8.2.1


From ce3db25bd19b612033421d15f44262e991489f2f Mon Sep 17 00:00:00 2001
From: Alexander Werth <alexander.werth at de.ibm.com>
Date: Sun, 28 Apr 2013 19:06:59 +0200
Subject: [PATCH 21/26] s4-smbtorture: Run tests for nfs4:modes simple and
 special.

Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 selftest/knownfail        | 23 ++++++++++++++++-------
 selftest/target/Samba3.pm |  9 ++++++++-
 source3/selftest/tests.py |  3 ++-
 3 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/selftest/knownfail b/selftest/knownfail
index c5c6596..ad5db590 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -45,13 +45,22 @@
 ^samba3.blackbox.smbclient_machine_auth.plain \(s3dc:local\)# the S3dc does not currently set up a self-join
 ^samba3.raw.samba3hide.samba3hide\((s3dc|plugin_s4_dc)\) # This test fails against an smbd environment with NT ACLs enabled
 ^samba3.raw.samba3closeerr.samba3closeerr\(s3dc\) # This test fails against an smbd environment with NT ACLs enabled
-^samba3.raw.acls nfs4acl_xattr.INHERITFLAGS\(s3dc\) # This (and the follow nfs4acl_xattr tests fail because our NFSv4 backend isn't a complete mapping yet.
-^samba3.raw.acls nfs4acl_xattr.sd\(s3dc\)
-^samba3.raw.acls nfs4acl_xattr.create_file\(s3dc\)
-^samba3.raw.acls nfs4acl_xattr.create_dir\(s3dc\)
-^samba3.raw.acls nfs4acl_xattr.nulldacl\(s3dc\)
-^samba3.raw.acls nfs4acl_xattr.generic\(s3dc\)
-^samba3.raw.acls nfs4acl_xattr.inheritance\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-simple.INHERITFLAGS\(s3dc\) # This (and the follow nfs4acl_xattr tests fail because our NFSv4 backend isn't a complete mapping yet.
+^samba3.raw.acls nfs4acl_xattr-simple.sd\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-simple.create_file\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-simple.create_dir\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-simple.nulldacl\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-simple.generic\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-simple.inheritance\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.INHERITFLAGS\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.sd\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.create_file\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.create_dir\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.nulldacl\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.generic\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.inheritance\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.inherit_creator_owner\(s3dc\)
+^samba3.raw.acls nfs4acl_xattr-special.inherit_creator_group\(s3dc\)
 ^samba3.base.delete.deltest16a
 ^samba3.base.delete.deltest17a
 ^samba3.unix.whoami anonymous connection.whoami\(plugin_s4_dc\) # We need to resolve if we should be including SID_NT_WORLD and SID_NT_NETWORK in this token
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 407642c..f907386 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1082,9 +1082,16 @@ sub provision($$$$$$)
 [lp]
 	copy = print1
 
-[nfs4acl_share]
+[nfs4acl_simple]
 	path = $shrdir
 	comment = smb username is [%U]
+	nfs4:mode = simple
+	vfs objects = $vfs_modulesdir_abs/nfs4acl_xattr.so $vfs_modulesdir_abs/xattr_tdb.so
+
+[nfs4acl_special]
+	path = $shrdir
+	comment = smb username is [%U]
+	nfs4:mode = special
 	vfs objects = $vfs_modulesdir_abs/nfs4acl_xattr.so $vfs_modulesdir_abs/xattr_tdb.so
 
 [xcopy_share]
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 11504c0..3fc6684 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -345,7 +345,8 @@ for t in tests:
         plantestsuite(t, "s3member_rfc2307", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_rfc2307.sh"), '$DOMAIN', 'Administrator', '2000000', '"Domain Users"', '2000001', 'ou=idmap,dc=samba,dc=example,dc=com', '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD'])
     elif t == "raw.acls":
         plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
-        plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/nfs4acl_share -U$USERNAME%$PASSWORD', description='nfs4acl_xattr')
+        plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/nfs4acl_simple -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple')
+        plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/nfs4acl_special -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-special')
         plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER_IP/tmpcase -U$USERNAME%$PASSWORD')
     else:
         plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
-- 
1.8.2.1


From ab5048dfbd5853a2b6d77a285624609880b4e54c Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Sun, 28 Apr 2013 18:20:04 +1000
Subject: [PATCH 22/26] vfs: Allow CREATOR GROUP to be used with vfs_zfsacl

The solaris acl() code requires that both ACE_GROUP|ACE_IDENTIFIER_GROUP be
set to indicate the @group permissions.

Otherwise, it would return Invalid Paramter to clients.

Andrew Bartlett
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/vfs_zfsacl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/modules/vfs_zfsacl.c b/source3/modules/vfs_zfsacl.c
index 93a0faa..dbae50b 100644
--- a/source3/modules/vfs_zfsacl.c
+++ b/source3/modules/vfs_zfsacl.c
@@ -142,7 +142,7 @@ static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp, SMB
 				acebuf[i].a_flags |= ACE_OWNER;
 				break;
 			case SMB_ACE4_WHO_GROUP:
-				acebuf[i].a_flags |= ACE_GROUP;
+				acebuf[i].a_flags |= ACE_GROUP|ACE_IDENTIFIER_GROUP;
 				break;
 			default:
 				DEBUG(8, ("unsupported special_id %d\n", \
-- 
1.8.2.1


From ab31b7ba0177cb581b80d0d83379d53480747bac Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 7 May 2013 13:58:26 -0700
Subject: [PATCH 23/26] Tidy up old bool usage. False -> false, True -> true.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/modules/nfs4_acls.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index 3f6d8d8..ceae6d9 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -335,7 +335,7 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
 	{
 		DEBUG(10, ("talloc error"));
 		errno = ENOMEM;
-		return False;
+		return false;
 	}
 
 	for (aceint=aclint->first;
@@ -469,7 +469,7 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
 	*ppnt_ace_list = nt_ace_list;
 	*pgood_aces = good_aces;
 
-	return True;
+	return true;
 }
 
 static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
@@ -498,7 +498,7 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
 
 	if (smbacl4_nfs42win(mem_ctx, params, theacl, &sid_owner, &sid_group,
 			     S_ISDIR(sbuf->st_ex_mode),
-				&nt_ace_list, &good_aces)==False) {
+				&nt_ace_list, &good_aces)==false) {
 		DEBUG(8,("smbacl4_nfs42win failed\n"));
 		TALLOC_FREE(frame);
 		return map_nt_error_from_unix(errno);
@@ -704,7 +704,7 @@ static bool smbacl4_fill_ace4(
 		ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
 		if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
 		    && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
-			return False;
+			return false;
 		}
 	} else if (params->mode!=e_special &&
 		   dom_sid_equal(&ace_nt->trustee,
@@ -716,7 +716,7 @@ static bool smbacl4_fill_ace4(
 		ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
 		if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
 		    && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
-			return False;
+			return false;
 		}
 	} else {
 		uid_t uid;
@@ -743,11 +743,11 @@ static bool smbacl4_fill_ace4(
 				  "convert %s to uid or gid\n",
 				  filename->base_name,
 				  sid_string_dbg(&ace_nt->trustee)));
-			return False;
+			return false;
 		}
 	}
 
-	return True; /* OK */
+	return true; /* OK */
 }
 
 static int smbacl4_MergeIgnoreReject(
@@ -765,12 +765,12 @@ static int smbacl4_MergeIgnoreReject(
 		switch(acedup)
 		{
 		case e_merge: /* "merge" flags */
-			*paddNewACE = False;
+			*paddNewACE = false;
 			ace4found->aceFlags |= ace->aceFlags;
 			ace4found->aceMask |= ace->aceMask;
 			break;
 		case e_ignore: /* leave out this record */
-			*paddNewACE = False;
+			*paddNewACE = false;
 			break;
 		case e_reject: /* do an error */
 			DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i));
@@ -817,7 +817,7 @@ static int smbacl4_substitute_special(
 			DEBUG(10,("replaced with special group ace\n"));
 		}
 	}
-	return True; /* OK */
+	return true; /* OK */
 }
 
 static int smbacl4_substitute_simple(
@@ -859,7 +859,7 @@ static int smbacl4_substitute_simple(
 			DEBUG(10,("replaced with special group ace\n"));
 		}
 	}
-	return True; /* OK */
+	return true; /* OK */
 }
 
 static SMB4ACL_T *smbacl4_win2nfs4(
@@ -883,7 +883,7 @@ static SMB4ACL_T *smbacl4_win2nfs4(
 
 	for(i=0; i<dacl->num_aces; i++) {
 		SMB_ACE4PROP_T	ace_v4;
-		bool	addNewACE = True;
+		bool	addNewACE = true;
 
 		if (!smbacl4_fill_ace4(fsp->fsp_name, pparams,
 				       ownerUID, ownerGID,
@@ -1021,7 +1021,7 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
 
 	TALLOC_FREE(frame);
 
-	if (result!=True) {
+	if (result!=true) {
 		errno = saved_errno;
 		DEBUG(10, ("set_nfs4_native failed with %s\n",
 			   strerror(errno)));
-- 
1.8.2.1


From c172255aa3711f7e4eb06c7587cc93b8432e58e5 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 7 May 2013 14:04:24 -0700
Subject: [PATCH 24/26] Fix missing TALLOC_FREE of stackframes.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/modules/vfs_aixacl2.c | 4 +++-
 source3/modules/vfs_gpfs.c    | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/source3/modules/vfs_aixacl2.c b/source3/modules/vfs_aixacl2.c
index c97cd57..4ac6ada 100644
--- a/source3/modules/vfs_aixacl2.c
+++ b/source3/modules/vfs_aixacl2.c
@@ -174,8 +174,10 @@ static NTSTATUS aixjfs2_fget_nt_acl(vfs_handle_struct *handle,
 		return posix_fget_nt_acl(fsp, security_info,
 					 mem_ctx, ppdesc);
 	}
-	if (result==False)
+	if (result==False) {
+		TALLOC_FREE(frame);
 		return NT_STATUS_ACCESS_DENIED;
+	}
 
 	status = smb_fget_nt_acl_nfs4(fsp, security_info, ppdesc,
 				      mem_ctx, pacl);
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 6056b7e..7f00eac 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -472,6 +472,7 @@ static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
 	}
 
 	/* GPFS ACL was not read, something wrong happened, error code is set in errno */
+	TALLOC_FREE(frame);
 	return map_nt_error_from_unix(errno);
 }
 
@@ -1122,9 +1123,10 @@ static int gpfsacl_emu_chmod(vfs_handle_struct *handle,
 	DEBUG(10, ("gpfsacl_emu_chmod invoked for %s mode %o\n", path, mode));
 
 	result = gpfs_get_nfs4_acl(frame, path, &pacl);
-	if (result)
+	if (result) {
 		TALLOC_FREE(frame);
 		return result;
+	}
 
 	if (mode & ~(S_IRWXU | S_IRWXG | S_IRWXO)) {
 		DEBUG(2, ("WARNING: cutting extra mode bits %o on %s\n", mode, path));
-- 
1.8.2.1


From ed4a3f80328485250048a39b9d41852ad61525f9 Mon Sep 17 00:00:00 2001
From: Christian Ambach <ambi at samba.org>
Date: Mon, 6 May 2013 16:56:09 +0000
Subject: [PATCH 25/26] s3:modules/vfs_aixacl2 fix compile errors

fix various compile errors that were introduced with latest ACL changes

Signed-off-by: Christian Ambach <ambi at samba.org>
Pair-Programmed-With: Alexander Werth <alexander.werth at de.ibm.com>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source3/modules/vfs_aixacl2.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/source3/modules/vfs_aixacl2.c b/source3/modules/vfs_aixacl2.c
index 4ac6ada..d7487d8 100644
--- a/source3/modules/vfs_aixacl2.c
+++ b/source3/modules/vfs_aixacl2.c
@@ -93,7 +93,7 @@ static AIXJFS2_ACL_T *aixjfs2_getacl_alloc(const char *fname, acl_type_t *type)
 	return acl;
 }
 
-static bool aixjfs2_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *name
+static bool aixjfs2_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *name,
 	SMB4ACL_T **ppacl, bool *pretryPosix)
 {
 	int32_t i;
@@ -196,7 +196,7 @@ static NTSTATUS aixjfs2_get_nt_acl(vfs_handle_struct *handle,
 	bool	retryPosix = False;
 
 	*ppdesc = NULL;
-	result = aixjfs2_get_nfs4_acl(name, &pacl, &retryPosix);
+	result = aixjfs2_get_nfs4_acl(mem_ctx, name, &pacl, &retryPosix);
 	if (retryPosix)
 	{
 		DEBUG(10, ("retrying with posix acl...\n"));
@@ -217,8 +217,7 @@ static int aixjfs2_sys_acl_blob_get_file(vfs_handle_struct *handle, const char *
 	bool	result;
 	bool	retryPosix = False;
 
-	*ppdesc = NULL;
-	result = aixjfs2_get_nfs4_acl(path_p, &pacl, &retryPosix);
+	result = aixjfs2_get_nfs4_acl(mem_ctx, path_p, &pacl, &retryPosix);
 	if (retryPosix)
 	{
 		return posix_sys_acl_blob_get_file(handle, path_p, mem_ctx,
@@ -235,7 +234,7 @@ static int aixjfs2_sys_acl_blob_get_fd(vfs_handle_struct *handle, files_struct *
 	bool	result;
 	bool	retryPosix = False;
 
-	result = aixjfs2_get_nfs4_acl(fsp->fsp_name->base_name, &pacl,
+	result = aixjfs2_get_nfs4_acl(mem_ctx, fsp->fsp_name->base_name, &pacl,
 				      &retryPosix);
 	if (retryPosix)
 	{
@@ -304,12 +303,13 @@ SMB_ACL_T aixjfs2_sys_acl_get_file(vfs_handle_struct *handle,
 }
 
 SMB_ACL_T aixjfs2_sys_acl_get_fd(vfs_handle_struct *handle,
-                                  files_struct *fsp)
+				 files_struct *fsp, TALLOC_CTX *mem_ctx)
 {
         acl_type_t aixjfs2_type;
         aixjfs2_type.u64 = ACL_AIXC;
 
-	return aixjfs2_get_posix_acl(fsp->fsp_name->base_name, aixjfs2_type);
+	return aixjfs2_get_posix_acl(fsp->fsp_name->base_name,
+				     aixjfs2_type, mem_ctx);
 }
 
 /*
@@ -427,8 +427,7 @@ static NTSTATUS aixjfs2_set_nt_acl_common(vfs_handle_struct *handle, files_struc
 	int	rc;
 
 	rc = aixjfs2_query_acl_support(
-		handle,
-		fsp->fsp_name,
+		fsp->fsp_name->base_name,
 		ACL_NFS4,
 		&acl_type_info);
 
-- 
1.8.2.1


From bb1edc3f6c7dd9e51ea223990fbe7f6fb74cea2c Mon Sep 17 00:00:00 2001
From: Christian Ambach <ambi at samba.org>
Date: Mon, 6 May 2013 19:00:29 +0200
Subject: [PATCH 26/26] s4:torture fix a build break on AIX

Signed-off-by: Christian Ambach <ambi at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>

---
 source4/torture/smb2/delete-on-close.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/source4/torture/smb2/delete-on-close.c b/source4/torture/smb2/delete-on-close.c
index 0eef8fa..a12c2ab 100644
--- a/source4/torture/smb2/delete-on-close.c
+++ b/source4/torture/smb2/delete-on-close.c
@@ -19,7 +19,6 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "unistd.h"
 #include "includes.h"
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
-- 
1.8.2.1



More information about the samba-technical mailing list