[PATCH] Fix for XDR Backend of NFS4ACL_XATTR module to get it working with NFS4.0 ACL Spec

Jeremy Allison jra at samba.org
Mon Mar 18 19:21:03 UTC 2019


On Mon, Mar 18, 2019 at 04:44:58PM +0100, Ralph Böhme wrote:
> Hi Jeremy,
> 
> On Fri, Nov 30, 2018 at 02:36:20PM +0100, Ralph Böhme wrote:
> > btw, in case you're watching, while a review is certainly welcome,
> > please don't push this yet as I want to test this on a customer system
> > against a netapp NFS4 server. :)
> 
> customer reported success.
> 
> Attached is the patchset rebased on current master. Please review&push if happy.

Great work Ralph - thanks ! Really clear and nice code.

RB+ and pushed.

Jeremy.


> -- 
> Ralph Boehme, Samba Team                https://samba.org/
> Samba Developer, SerNet GmbH   https://sernet.de/en/samba/
> GPG-Fingerprint   FAE2C6088A24252051C559E4AA1E9B7126399E46

> From 5d8e554e2348a7214afa4542133d204474edc0ba Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Thu, 22 Nov 2018 18:27:47 +0100
> Subject: [PATCH 1/9] nfs4acl_xattr: identifiers are XDR encoded as integers
> 
> The structs nfsacl41 and nfsace4 are not RFC 3530 compliant, let's
> rename them adding a trailing "i" that indicates that the structs store
> identifiers as integers.
> 
>   struct nfsace4  -> struct nfsace4i
>   struct nfsacl41 -> struct nfsacl41i
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/nfs41acl.x          |  6 ++--
>  source3/modules/nfs4acl_xattr_xdr.c | 46 ++++++++++++++---------------
>  2 files changed, 26 insertions(+), 26 deletions(-)
> 
> diff --git a/source3/modules/nfs41acl.x b/source3/modules/nfs41acl.x
> index 9cfbd9f3074..1a2e1d639e5 100644
> --- a/source3/modules/nfs41acl.x
> +++ b/source3/modules/nfs41acl.x
> @@ -70,7 +70,7 @@ const ACE4_SYNCHRONIZE          = 0x00100000;
>  
>  typedef u_int acemask4;
>  
> -struct nfsace4 {
> +struct nfsace4i {
>          acetype4        type;
>          aceflag4        flag;
>          aceiflag4       iflag;
> @@ -88,7 +88,7 @@ const ACL4_DEFAULTED            = 0x00000004;
>  
>  typedef u_int aclflag4;
>  
> -struct nfsacl41 {
> +struct nfsacl41i {
>          aclflag4        na41_flag;
> -        nfsace4         na41_aces<>;
> +        nfsace4i        na41_aces<>;
>  };
> diff --git a/source3/modules/nfs4acl_xattr_xdr.c b/source3/modules/nfs4acl_xattr_xdr.c
> index 399c104faa4..5afeb5bc2e5 100644
> --- a/source3/modules/nfs4acl_xattr_xdr.c
> +++ b/source3/modules/nfs4acl_xattr_xdr.c
> @@ -40,27 +40,27 @@
>  #include "nfs41acl.h"
>  #include "nfs4acl_xattr_xdr.h"
>  
> -static unsigned nfs4acl_get_naces(nfsacl41 *nacl)
> +static unsigned nfs4acl_get_naces(nfsacl41i *nacl)
>  {
>  	return nacl->na41_aces.na41_aces_len;
>  }
>  
> -static void nfs4acl_set_naces(nfsacl41 *nacl, unsigned naces)
> +static void nfs4acl_set_naces(nfsacl41i *nacl, unsigned naces)
>  {
>  	nacl->na41_aces.na41_aces_len = naces;
>  }
>  
> -static unsigned nfs4acl_get_flags(nfsacl41 *nacl)
> +static unsigned nfs4acl_get_flags(nfsacl41i *nacl)
>  {
>  	return nacl->na41_flag;
>  }
>  
> -static void nfs4acl_set_flags(nfsacl41 *nacl, unsigned flags)
> +static void nfs4acl_set_flags(nfsacl41i *nacl, unsigned flags)
>  {
>  	nacl->na41_flag = flags;
>  }
>  
> -static size_t nfs4acl_get_xdrblob_size(nfsacl41 *nacl)
> +static size_t nfs4acl_get_xdrblob_size(nfsacl41i *nacl)
>  {
>  	size_t acl_size;
>  	size_t aces_size;
> @@ -73,7 +73,7 @@ static size_t nfs4acl_get_xdrblob_size(nfsacl41 *nacl)
>  		return 0;
>  	}
>  
> -	aces_size = naces * sizeof(struct nfsace4);
> +	aces_size = naces * sizeof(struct nfsace4i);
>  	if (acl_size + aces_size < acl_size) {
>  		return 0;
>  	}
> @@ -91,13 +91,13 @@ static size_t nfs4acl_get_xdrblob_naces(size_t _blobsize)
>  	if (blobsize > _blobsize) {
>  		return 0;
>  	}
> -	return (blobsize / sizeof(struct nfsace4));
> +	return (blobsize / sizeof(struct nfsace4i));
>  }
>  
> -static nfsacl41 *nfs4acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
> +static nfsacl41i *nfs4acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
>  {
> -	size_t acl_size = sizeof(nfsacl41) + (naces * sizeof(struct nfsace4));
> -	nfsacl41 *nacl = NULL;
> +	size_t acl_size = sizeof(nfsacl41i) + (naces * sizeof(struct nfsace4i));
> +	nfsacl41i *nacl = NULL;
>  
>  	if (naces > NFS4ACL_XDR_MAX_ACES) {
>  		DBG_ERR("Too many ACEs: %d\n", naces);
> @@ -112,12 +112,12 @@ static nfsacl41 *nfs4acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
>  
>  	nfs4acl_set_naces(nacl, naces);
>  	nacl->na41_aces.na41_aces_val =
> -		(nfsace4 *)((char *)nacl + sizeof(nfsacl41));
> +		(nfsace4i *)((char *)nacl + sizeof(nfsacl41i));
>  
>  	return nacl;
>  }
>  
> -static nfsace4 *nfs4acl_get_ace(nfsacl41 *nacl, size_t n)
> +static nfsace4i *nfs4acl_get_ace(nfsacl41i *nacl, size_t n)
>  {
>  	return &nacl->na41_aces.na41_aces_val[n];
>  }
> @@ -142,12 +142,12 @@ static unsigned smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags)
>  static bool smb4acl_to_nfs4acl(vfs_handle_struct *handle,
>  			       TALLOC_CTX *mem_ctx,
>  			       struct SMB4ACL_T *smb4acl,
> -			       nfsacl41 **_nacl)
> +			       nfsacl41i **_nacl)
>  {
>  	struct nfs4acl_config *config = NULL;
>  	struct SMB4ACE_T *smb4ace = NULL;
>  	size_t smb4naces = 0;
> -	nfsacl41 *nacl = NULL;
> +	nfsacl41i *nacl = NULL;
>  	uint16_t smb4acl_flags = 0;
>  	unsigned nacl_flags = 0;
>  
> @@ -169,7 +169,7 @@ static bool smb4acl_to_nfs4acl(vfs_handle_struct *handle,
>  	while (smb4ace != NULL) {
>  		SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
>  		size_t nace_count = nfs4acl_get_naces(nacl);
> -		nfsace4 *nace = nfs4acl_get_ace(nacl, nace_count);
> +		nfsace4i *nace = nfs4acl_get_ace(nacl, nace_count);
>  
>  		nace->type = ace4prop->aceType;
>  		nace->flag = ace4prop->aceFlags;
> @@ -219,7 +219,7 @@ NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
>  				     struct SMB4ACL_T *smb4acl,
>  				     DATA_BLOB *_blob)
>  {
> -	nfsacl41 *nacl = NULL;
> +	nfsacl41i *nacl = NULL;
>  	XDR xdr = {0};
>  	size_t aclblobsize;
>  	DATA_BLOB blob;
> @@ -244,7 +244,7 @@ NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
>  
>  	xdrmem_create(&xdr, (char *)blob.data, blob.length, XDR_ENCODE);
>  
> -	ok = xdr_nfsacl41(&xdr, nacl);
> +	ok = xdr_nfsacl41i(&xdr, nacl);
>  	TALLOC_FREE(nacl);
>  	if (!ok) {
>  		DBG_ERR("xdr_nfs4acl41 failed\n");
> @@ -275,10 +275,10 @@ static uint16_t nfs4acl_to_smb4acl_flags(unsigned nfsacl41_flags)
>  static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle,
>  					    TALLOC_CTX *mem_ctx,
>  					    DATA_BLOB *blob,
> -					    nfsacl41 **_nacl)
> +					    nfsacl41i **_nacl)
>  {
>  	struct nfs4acl_config *config = NULL;
> -	nfsacl41 *nacl = NULL;
> +	nfsacl41i *nacl = NULL;
>  	size_t naces;
>  	XDR xdr = {0};
>  	bool ok;
> @@ -292,7 +292,7 @@ static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle,
>  
>  	xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
>  
> -	ok = xdr_nfsacl41(&xdr, nacl);
> +	ok = xdr_nfsacl41i(&xdr, nacl);
>  	if (!ok) {
>  		DBG_ERR("xdr_nfs4acl41 failed\n");
>  		return NT_STATUS_INTERNAL_ERROR;
> @@ -308,7 +308,7 @@ static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle,
>  
>  static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle,
>  				   TALLOC_CTX *mem_ctx,
> -				   nfsacl41 *nacl,
> +				   nfsacl41i *nacl,
>  				   struct SMB4ACL_T **_smb4acl)
>  {
>  	struct nfs4acl_config *config = NULL;
> @@ -336,7 +336,7 @@ static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle,
>  	DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags, naces);
>  
>  	for (i = 0; i < naces; i++) {
> -		nfsace4 *nace = nfs4acl_get_ace(nacl, i);
> +		nfsace4i *nace = nfs4acl_get_ace(nacl, i);
>  		SMB_ACE4PROP_T smbace = { 0 };
>  
>  		DBG_DEBUG("type [%d] iflag [%x] flag [%x] mask [%x] who [%d]\n",
> @@ -388,7 +388,7 @@ NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
>  				  struct SMB4ACL_T **_smb4acl)
>  {
>  	struct nfs4acl_config *config = NULL;
> -	nfsacl41 *nacl = NULL;
> +	nfsacl41i *nacl = NULL;
>  	struct SMB4ACL_T *smb4acl = NULL;
>  	NTSTATUS status;
>  
> -- 
> 2.17.2
> 
> 
> From a3f1c9050b9a312e7cf7eb5ab6ffe26ffd128593 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Sun, 25 Nov 2018 11:47:48 +0100
> Subject: [PATCH 2/9] nfs4acl_xattr: append 'i' to nfs4acl functions
> 
> This reflects the new struct names the functions use.
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/nfs4acl_xattr_xdr.c | 74 ++++++++++++++---------------
>  1 file changed, 37 insertions(+), 37 deletions(-)
> 
> diff --git a/source3/modules/nfs4acl_xattr_xdr.c b/source3/modules/nfs4acl_xattr_xdr.c
> index 5afeb5bc2e5..ebe990215fa 100644
> --- a/source3/modules/nfs4acl_xattr_xdr.c
> +++ b/source3/modules/nfs4acl_xattr_xdr.c
> @@ -40,31 +40,31 @@
>  #include "nfs41acl.h"
>  #include "nfs4acl_xattr_xdr.h"
>  
> -static unsigned nfs4acl_get_naces(nfsacl41i *nacl)
> +static unsigned nfs4acli_get_naces(nfsacl41i *nacl)
>  {
>  	return nacl->na41_aces.na41_aces_len;
>  }
>  
> -static void nfs4acl_set_naces(nfsacl41i *nacl, unsigned naces)
> +static void nfs4acli_set_naces(nfsacl41i *nacl, unsigned naces)
>  {
>  	nacl->na41_aces.na41_aces_len = naces;
>  }
>  
> -static unsigned nfs4acl_get_flags(nfsacl41i *nacl)
> +static unsigned nfs4acli_get_flags(nfsacl41i *nacl)
>  {
>  	return nacl->na41_flag;
>  }
>  
> -static void nfs4acl_set_flags(nfsacl41i *nacl, unsigned flags)
> +static void nfs4acli_set_flags(nfsacl41i *nacl, unsigned flags)
>  {
>  	nacl->na41_flag = flags;
>  }
>  
> -static size_t nfs4acl_get_xdrblob_size(nfsacl41i *nacl)
> +static size_t nfs4acli_get_xdrblob_size(nfsacl41i *nacl)
>  {
>  	size_t acl_size;
>  	size_t aces_size;
> -	unsigned naces = nfs4acl_get_naces(nacl);
> +	unsigned naces = nfs4acli_get_naces(nacl);
>  
>  	acl_size = sizeof(aclflag4) + sizeof(unsigned);
>  
> @@ -82,7 +82,7 @@ static size_t nfs4acl_get_xdrblob_size(nfsacl41i *nacl)
>  	return acl_size;
>  }
>  
> -static size_t nfs4acl_get_xdrblob_naces(size_t _blobsize)
> +static size_t nfs4acli_get_xdrblob_naces(size_t _blobsize)
>  {
>  	size_t blobsize = _blobsize;
>  
> @@ -94,7 +94,7 @@ static size_t nfs4acl_get_xdrblob_naces(size_t _blobsize)
>  	return (blobsize / sizeof(struct nfsace4i));
>  }
>  
> -static nfsacl41i *nfs4acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
> +static nfsacl41i *nfs4acli_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
>  {
>  	size_t acl_size = sizeof(nfsacl41i) + (naces * sizeof(struct nfsace4i));
>  	nfsacl41i *nacl = NULL;
> @@ -110,14 +110,14 @@ static nfsacl41i *nfs4acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
>  		return NULL;
>  	}
>  
> -	nfs4acl_set_naces(nacl, naces);
> +	nfs4acli_set_naces(nacl, naces);
>  	nacl->na41_aces.na41_aces_val =
>  		(nfsace4i *)((char *)nacl + sizeof(nfsacl41i));
>  
>  	return nacl;
>  }
>  
> -static nfsace4i *nfs4acl_get_ace(nfsacl41i *nacl, size_t n)
> +static nfsace4i *nfs4acli_get_ace(nfsacl41i *nacl, size_t n)
>  {
>  	return &nacl->na41_aces.na41_aces_val[n];
>  }
> @@ -139,10 +139,10 @@ static unsigned smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags)
>  	return nfs4acl_flags;
>  }
>  
> -static bool smb4acl_to_nfs4acl(vfs_handle_struct *handle,
> -			       TALLOC_CTX *mem_ctx,
> -			       struct SMB4ACL_T *smb4acl,
> -			       nfsacl41i **_nacl)
> +static bool smb4acl_to_nfs4acli(vfs_handle_struct *handle,
> +				TALLOC_CTX *mem_ctx,
> +				struct SMB4ACL_T *smb4acl,
> +				nfsacl41i **_nacl)
>  {
>  	struct nfs4acl_config *config = NULL;
>  	struct SMB4ACE_T *smb4ace = NULL;
> @@ -156,20 +156,20 @@ static bool smb4acl_to_nfs4acl(vfs_handle_struct *handle,
>  				return false);
>  
>  	smb4naces = smb_get_naces(smb4acl);
> -	nacl = nfs4acl_alloc(mem_ctx, smb4naces);
> -	nfs4acl_set_naces(nacl, 0);
> +	nacl = nfs4acli_alloc(mem_ctx, smb4naces);
> +	nfs4acli_set_naces(nacl, 0);
>  
>  	if (config->nfs_version > ACL4_XATTR_VERSION_40) {
>  		smb4acl_flags = smbacl4_get_controlflags(smb4acl);
>  		nacl_flags = smb4acl_to_nfs4acl_flags(smb4acl_flags);
> -		nfs4acl_set_flags(nacl, nacl_flags);
> +		nfs4acli_set_flags(nacl, nacl_flags);
>  	}
>  
>  	smb4ace = smb_first_ace4(smb4acl);
>  	while (smb4ace != NULL) {
>  		SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
> -		size_t nace_count = nfs4acl_get_naces(nacl);
> -		nfsace4i *nace = nfs4acl_get_ace(nacl, nace_count);
> +		size_t nace_count = nfs4acli_get_naces(nacl);
> +		nfsace4i *nace = nfs4acli_get_ace(nacl, nace_count);
>  
>  		nace->type = ace4prop->aceType;
>  		nace->flag = ace4prop->aceFlags;
> @@ -206,7 +206,7 @@ static bool smb4acl_to_nfs4acl(vfs_handle_struct *handle,
>  		}
>  
>  		nace_count++;
> -		nfs4acl_set_naces(nacl, nace_count);
> +		nfs4acli_set_naces(nacl, nace_count);
>  		smb4ace = smb_next_ace4(smb4ace);
>  	}
>  
> @@ -225,13 +225,13 @@ NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
>  	DATA_BLOB blob;
>  	bool ok;
>  
> -	ok = smb4acl_to_nfs4acl(handle, talloc_tos(), smb4acl, &nacl);
> +	ok = smb4acl_to_nfs4acli(handle, talloc_tos(), smb4acl, &nacl);
>  	if (!ok) {
>  		DBG_ERR("smb4acl_to_nfs4acl failed\n");
>  		return NT_STATUS_INTERNAL_ERROR;
>  	}
>  
> -	aclblobsize = nfs4acl_get_xdrblob_size(nacl);
> +	aclblobsize = nfs4acli_get_xdrblob_size(nacl);
>  	if (aclblobsize == 0) {
>  		return NT_STATUS_INTERNAL_ERROR;
>  	}
> @@ -272,10 +272,10 @@ static uint16_t nfs4acl_to_smb4acl_flags(unsigned nfsacl41_flags)
>  	return smb4acl_flags;
>  }
>  
> -static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle,
> -					    TALLOC_CTX *mem_ctx,
> -					    DATA_BLOB *blob,
> -					    nfsacl41i **_nacl)
> +static NTSTATUS nfs4acl_xdr_blob_to_nfs4acli(struct vfs_handle_struct *handle,
> +					     TALLOC_CTX *mem_ctx,
> +					     DATA_BLOB *blob,
> +					     nfsacl41i **_nacl)
>  {
>  	struct nfs4acl_config *config = NULL;
>  	nfsacl41i *nacl = NULL;
> @@ -287,8 +287,8 @@ static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle,
>  				struct nfs4acl_config,
>  				return NT_STATUS_INTERNAL_ERROR);
>  
> -	naces = nfs4acl_get_xdrblob_naces(blob->length);
> -	nacl = nfs4acl_alloc(mem_ctx, naces);
> +	naces = nfs4acli_get_xdrblob_naces(blob->length);
> +	nacl = nfs4acli_alloc(mem_ctx, naces);
>  
>  	xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
>  
> @@ -306,16 +306,16 @@ static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle,
>  	return NT_STATUS_OK;
>  }
>  
> -static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle,
> -				   TALLOC_CTX *mem_ctx,
> -				   nfsacl41i *nacl,
> -				   struct SMB4ACL_T **_smb4acl)
> +static NTSTATUS nfs4acli_to_smb4acl(struct vfs_handle_struct *handle,
> +				    TALLOC_CTX *mem_ctx,
> +				    nfsacl41i *nacl,
> +				    struct SMB4ACL_T **_smb4acl)
>  {
>  	struct nfs4acl_config *config = NULL;
>  	struct SMB4ACL_T *smb4acl = NULL;
>  	unsigned nfsacl41_flag = 0;
>  	uint16_t smb4acl_flags = 0;
> -	unsigned naces = nfs4acl_get_naces(nacl);
> +	unsigned naces = nfs4acli_get_naces(nacl);
>  	int i;
>  
>  	SMB_VFS_HANDLE_GET_DATA(handle, config,
> @@ -328,7 +328,7 @@ static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle,
>  	}
>  
>  	if (config->nfs_version > ACL4_XATTR_VERSION_40) {
> -		nfsacl41_flag = nfs4acl_get_flags(nacl);
> +		nfsacl41_flag = nfs4acli_get_flags(nacl);
>  		smb4acl_flags = nfs4acl_to_smb4acl_flags(nfsacl41_flag);
>  		smbacl4_set_controlflags(smb4acl, smb4acl_flags);
>  	}
> @@ -336,7 +336,7 @@ static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle,
>  	DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags, naces);
>  
>  	for (i = 0; i < naces; i++) {
> -		nfsace4i *nace = nfs4acl_get_ace(nacl, i);
> +		nfsace4i *nace = nfs4acli_get_ace(nacl, i);
>  		SMB_ACE4PROP_T smbace = { 0 };
>  
>  		DBG_DEBUG("type [%d] iflag [%x] flag [%x] mask [%x] who [%d]\n",
> @@ -396,12 +396,12 @@ NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
>  				struct nfs4acl_config,
>  				return NT_STATUS_INTERNAL_ERROR);
>  
> -	status = nfs4acl_xdr_blob_to_nfs4acl(handle, talloc_tos(), blob, &nacl);
> +	status = nfs4acl_xdr_blob_to_nfs4acli(handle, talloc_tos(), blob, &nacl);
>  	if (!NT_STATUS_IS_OK(status)) {
>  		return status;
>  	}
>  
> -	status = nfs4acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
> +	status = nfs4acli_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
>  	TALLOC_FREE(nacl);
>  	if (!NT_STATUS_IS_OK(status)) {
>  		return status;
> -- 
> 2.17.2
> 
> 
> From 0053701fcf263de4d4d2f68d46b3da1cb11cfc9a Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Sun, 25 Nov 2018 12:07:26 +0100
> Subject: [PATCH 3/9] nfs4acl_xattr: move some functions to a seperate file
> 
> These functions will be called from another translation unit in a
> subsequent commit.
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/nfs4acl_xattr_util.c | 73 ++++++++++++++++++++++++++++
>  source3/modules/nfs4acl_xattr_util.h | 25 ++++++++++
>  source3/modules/nfs4acl_xattr_xdr.c  | 35 +------------
>  source3/modules/wscript_build        |  1 +
>  4 files changed, 100 insertions(+), 34 deletions(-)
>  create mode 100644 source3/modules/nfs4acl_xattr_util.c
>  create mode 100644 source3/modules/nfs4acl_xattr_util.h
> 
> diff --git a/source3/modules/nfs4acl_xattr_util.c b/source3/modules/nfs4acl_xattr_util.c
> new file mode 100644
> index 00000000000..8ea1e76ad17
> --- /dev/null
> +++ b/source3/modules/nfs4acl_xattr_util.c
> @@ -0,0 +1,73 @@
> +/*
> + * Copyright (C) Ralph Boehme 2018
> + *
> + * 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 "smbd/proto.h"
> +#include "libcli/security/security_descriptor.h"
> +
> +#ifdef HAVE_RPC_XDR_H
> +/* <rpc/xdr.h> uses TRUE and FALSE */
> +#ifdef TRUE
> +#undef TRUE
> +#endif
> +
> +#ifdef FALSE
> +#undef FALSE
> +#endif
> +#endif
> +
> +#include "nfs4_acls.h"
> +#include "nfs41acl.h"
> +#include "nfs4acl_xattr_util.h"
> +
> +#undef DBGC_CLASS
> +#define DBGC_CLASS DBGC_VFS
> +
> +unsigned smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags)
> +{
> +	unsigned nfs4acl_flags = 0;
> +
> +	if (smb4acl_flags & SEC_DESC_DACL_AUTO_INHERITED) {
> +		nfs4acl_flags |= ACL4_AUTO_INHERIT;
> +	}
> +	if (smb4acl_flags & SEC_DESC_DACL_PROTECTED) {
> +		nfs4acl_flags |= ACL4_PROTECTED;
> +	}
> +	if (smb4acl_flags & SEC_DESC_DACL_DEFAULTED) {
> +		nfs4acl_flags |= ACL4_DEFAULTED;
> +	}
> +
> +	return nfs4acl_flags;
> +}
> +
> +uint16_t nfs4acl_to_smb4acl_flags(unsigned nfsacl41_flags)
> +{
> +	uint16_t smb4acl_flags = SEC_DESC_SELF_RELATIVE;
> +
> +	if (nfsacl41_flags & ACL4_AUTO_INHERIT) {
> +		smb4acl_flags |= SEC_DESC_DACL_AUTO_INHERITED;
> +	}
> +	if (nfsacl41_flags & ACL4_PROTECTED) {
> +		smb4acl_flags |= SEC_DESC_DACL_PROTECTED;
> +	}
> +	if (nfsacl41_flags & ACL4_DEFAULTED) {
> +		smb4acl_flags |= SEC_DESC_DACL_DEFAULTED;
> +	}
> +
> +	return smb4acl_flags;
> +}
> diff --git a/source3/modules/nfs4acl_xattr_util.h b/source3/modules/nfs4acl_xattr_util.h
> new file mode 100644
> index 00000000000..2d2c6a158ba
> --- /dev/null
> +++ b/source3/modules/nfs4acl_xattr_util.h
> @@ -0,0 +1,25 @@
> +/*
> + * Copyright (C) Ralph Boehme 2018
> + *
> + * 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/>.
> + *
> + */
> +
> +#ifndef _NFS4ACL_XATTR_UTIL_H_
> +#define _NFS4ACL_XATTR_UTIL_H_
> +
> +unsigned smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags);
> +uint16_t nfs4acl_to_smb4acl_flags(unsigned nfsacl41_flags);
> +
> +#endif /* _NFS4ACL_XATTR_UTIL_H_ */
> diff --git a/source3/modules/nfs4acl_xattr_xdr.c b/source3/modules/nfs4acl_xattr_xdr.c
> index ebe990215fa..1db36e96769 100644
> --- a/source3/modules/nfs4acl_xattr_xdr.c
> +++ b/source3/modules/nfs4acl_xattr_xdr.c
> @@ -39,6 +39,7 @@
>  #include <rpc/xdr.h>
>  #include "nfs41acl.h"
>  #include "nfs4acl_xattr_xdr.h"
> +#include "nfs4acl_xattr_util.h"
>  
>  static unsigned nfs4acli_get_naces(nfsacl41i *nacl)
>  {
> @@ -122,23 +123,6 @@ static nfsace4i *nfs4acli_get_ace(nfsacl41i *nacl, size_t n)
>  	return &nacl->na41_aces.na41_aces_val[n];
>  }
>  
> -static unsigned smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags)
> -{
> -	unsigned nfs4acl_flags = 0;
> -
> -	if (smb4acl_flags & SEC_DESC_DACL_AUTO_INHERITED) {
> -		nfs4acl_flags |= ACL4_AUTO_INHERIT;
> -	}
> -	if (smb4acl_flags & SEC_DESC_DACL_PROTECTED) {
> -		nfs4acl_flags |= ACL4_PROTECTED;
> -	}
> -	if (smb4acl_flags & SEC_DESC_DACL_DEFAULTED) {
> -		nfs4acl_flags |= ACL4_DEFAULTED;
> -	}
> -
> -	return nfs4acl_flags;
> -}
> -
>  static bool smb4acl_to_nfs4acli(vfs_handle_struct *handle,
>  				TALLOC_CTX *mem_ctx,
>  				struct SMB4ACL_T *smb4acl,
> @@ -255,23 +239,6 @@ NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
>  	return NT_STATUS_OK;
>  }
>  
> -static uint16_t nfs4acl_to_smb4acl_flags(unsigned nfsacl41_flags)
> -{
> -	uint16_t smb4acl_flags = SEC_DESC_SELF_RELATIVE;
> -
> -	if (nfsacl41_flags & ACL4_AUTO_INHERIT) {
> -		smb4acl_flags |= SEC_DESC_DACL_AUTO_INHERITED;
> -	}
> -	if (nfsacl41_flags & ACL4_PROTECTED) {
> -		smb4acl_flags |= SEC_DESC_DACL_PROTECTED;
> -	}
> -	if (nfsacl41_flags & ACL4_DEFAULTED) {
> -		smb4acl_flags |= SEC_DESC_DACL_DEFAULTED;
> -	}
> -
> -	return smb4acl_flags;
> -}
> -
>  static NTSTATUS nfs4acl_xdr_blob_to_nfs4acli(struct vfs_handle_struct *handle,
>  					     TALLOC_CTX *mem_ctx,
>  					     DATA_BLOB *blob,
> diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
> index e67a0abe10c..5007d58241a 100644
> --- a/source3/modules/wscript_build
> +++ b/source3/modules/wscript_build
> @@ -278,6 +278,7 @@ bld.SAMBA3_MODULE('vfs_nfs4acl_xattr',
>                             vfs_nfs4acl_xattr.c
>                             nfs4acl_xattr_ndr.c
>                             nfs4acl_xattr_xdr.c
> +                           nfs4acl_xattr_util.c
>                             ''',
>                    deps='NFS4_ACLS sunacl NDR_NFS4ACL VFS_NFS4_XDR',
>                    init_function='',
> -- 
> 2.17.2
> 
> 
> From a5ac55fd2a8baaed8aae2699118e6a5b023ece9e Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Mon, 26 Nov 2018 16:29:43 +0100
> Subject: [PATCH 4/9] nfs4acl_xattr: move a define to a common header file
> 
> In preperation of a adding real NFS backend.
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/nfs4acl_xattr.h     | 2 ++
>  source3/modules/nfs4acl_xattr_xdr.h | 1 -
>  2 files changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/source3/modules/nfs4acl_xattr.h b/source3/modules/nfs4acl_xattr.h
> index 3eeb4703bc8..86416063bf4 100644
> --- a/source3/modules/nfs4acl_xattr.h
> +++ b/source3/modules/nfs4acl_xattr.h
> @@ -19,6 +19,8 @@
>  #ifndef __NFS4ACL_XATTR_H__
>  #define __NFS4ACL_XATTR_H__
>  
> +#define NFS4ACL_XDR_MAX_ACES 8192
> +
>  enum nfs4acl_encoding {NFS4ACL_ENCODING_NDR, NFS4ACL_ENCODING_XDR};
>  
>  struct nfs4acl_config {
> diff --git a/source3/modules/nfs4acl_xattr_xdr.h b/source3/modules/nfs4acl_xattr_xdr.h
> index 8a544349cc8..4a79a0da93f 100644
> --- a/source3/modules/nfs4acl_xattr_xdr.h
> +++ b/source3/modules/nfs4acl_xattr_xdr.h
> @@ -20,7 +20,6 @@
>  #define __NFS4ACL_XATTR_XDR_H__
>  
>  #define NFS4ACL_XDR_XATTR_NAME "security.nfs4acl_xdr"
> -#define NFS4ACL_XDR_MAX_ACES 8192
>  
>  NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
>  				  TALLOC_CTX *mem_ctx,
> -- 
> 2.17.2
> 
> 
> From 4a10c328f522f12ebbc3d239570a387f4313b7e3 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Mon, 26 Nov 2018 16:30:38 +0100
> Subject: [PATCH 5/9] nfs4acl_xattr: add RFC compliant NFS 4.0 and 4.1 ACL
>  defintions
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/nfs41acl.x | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/source3/modules/nfs41acl.x b/source3/modules/nfs41acl.x
> index 1a2e1d639e5..51ac89a0791 100644
> --- a/source3/modules/nfs41acl.x
> +++ b/source3/modules/nfs41acl.x
> @@ -70,6 +70,14 @@ const ACE4_SYNCHRONIZE          = 0x00100000;
>  
>  typedef u_int acemask4;
>  
> +/* ACL structure definition as per RFC 7530 Section-6.2.1 */
> +struct nfsace4 {
> +        acetype4        type;
> +        aceflag4        flag;
> +        acemask4        access_mask;
> +        utf8str_mixed   who;
> +};
> +
>  struct nfsace4i {
>          acetype4        type;
>          aceflag4        flag;
> @@ -88,6 +96,15 @@ const ACL4_DEFAULTED            = 0x00000004;
>  
>  typedef u_int aclflag4;
>  
> +struct nfsacl40 {
> +        nfsace4         na40_aces<>;
> +};
> +
> +struct nfsacl41 {
> +        aclflag4        na41_flag;
> +        nfsace4         na41_aces<>;
> +};
> +
>  struct nfsacl41i {
>          aclflag4        na41_flag;
>          nfsace4i        na41_aces<>;
> -- 
> 2.17.2
> 
> 
> From 8b0ceb0216272c4b919f304e3d219e7886139c71 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Mon, 26 Nov 2018 16:31:42 +0100
> Subject: [PATCH 6/9] nfs4acl_xattr: reformat enum nfs4acl_encoding to one per
>  line
> 
> In preperation of adding another enum value.
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/nfs4acl_xattr.h | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/source3/modules/nfs4acl_xattr.h b/source3/modules/nfs4acl_xattr.h
> index 86416063bf4..d0c0b81fbd1 100644
> --- a/source3/modules/nfs4acl_xattr.h
> +++ b/source3/modules/nfs4acl_xattr.h
> @@ -21,7 +21,10 @@
>  
>  #define NFS4ACL_XDR_MAX_ACES 8192
>  
> -enum nfs4acl_encoding {NFS4ACL_ENCODING_NDR, NFS4ACL_ENCODING_XDR};
> +enum nfs4acl_encoding {
> +	NFS4ACL_ENCODING_NDR,
> +	NFS4ACL_ENCODING_XDR,
> +};
>  
>  struct nfs4acl_config {
>  	unsigned nfs_version;
> -- 
> 2.17.2
> 
> 
> From 6aecdfa22144b3e304caa72ad98d87c404fa13fd Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Thu, 29 Nov 2018 11:01:59 +0100
> Subject: [PATCH 7/9] vfs_nfs4acl_xattr: support for NFS 4.0 and 4.1 ACLs from
>  NFS4 mount
> 
> This adds a new main switch "nfs" to "nfs4acl_xattr:encoding" which
> enables to use NFS4 ACLs from an NFS4 mount on a Linux box. Tested with
> a FreeBSD NFS4 server.
> 
> Supports both NFS 4.0 and 4.1 ACLs.
> 
> By default NFS4 servers send user and group identifiers in ACLs as
> strings in the format "[USER|GROUP]@DNSDOMAIN". Some NFS4 servers
> support sending identifiers as numeric strings. This module does support
> this as well, the config knob "nfs4acl_xattr:nfs4_id_numeric = yes|no"
> controls behaviour.
> 
> When "nfs4acl_xattr:encoding" is set to "nfs", the new option
> "nfs4acl_xattr:validate_mode", which defauts to "yes" is set to "no" to
> avoid checking and munging the mode on files.
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  docs-xml/manpages/vfs_nfs4acl_xattr.8.xml |  34 +-
>  source3/modules/nfs4acl_xattr.h           |   3 +
>  source3/modules/nfs4acl_xattr_nfs.c       | 890 ++++++++++++++++++++++
>  source3/modules/nfs4acl_xattr_nfs.h       |  34 +
>  source3/modules/vfs_nfs4acl_xattr.c       |  33 +
>  source3/modules/wscript_build             |   1 +
>  6 files changed, 994 insertions(+), 1 deletion(-)
>  create mode 100644 source3/modules/nfs4acl_xattr_nfs.c
>  create mode 100644 source3/modules/nfs4acl_xattr_nfs.h
> 
> diff --git a/docs-xml/manpages/vfs_nfs4acl_xattr.8.xml b/docs-xml/manpages/vfs_nfs4acl_xattr.8.xml
> index c8780388184..c0fcee86b8c 100644
> --- a/docs-xml/manpages/vfs_nfs4acl_xattr.8.xml
> +++ b/docs-xml/manpages/vfs_nfs4acl_xattr.8.xml
> @@ -45,12 +45,17 @@
>      <variablelist>
>  
>        <varlistentry>
> -	<term>nfs4acl_xattr:encoding = [ndr|xdr]</term>
> +	<term>nfs4acl_xattr:encoding = [nfs|ndr|xdr]</term>
>  	<listitem>
>  	  <para>This parameter configures the marshaling format used in the ACL
>  	  blob and the default extended attribute name used to store the blob.
>  	  </para>
>  
> +	  <para>When set to <emphasis>nfs</emphasis> - fetch and store the NT
> +	  ACL in NFS 4.0 or 4.1 compatible XDR encoding. By default this uses
> +	  the extended attribute "system.nfs4_acl". This setting also
> +	  disables <emphasis>validate_mode</emphasis>.</para>
> +
>  	  <para>When set to <emphasis>ndr (default)</emphasis> - store the NT
>  	  ACL with POSIX draft NFSv4 compatible NDR encoding. By default this
>  	  uses the extended attribute "security.nfs4acl_ndr".</para>
> @@ -106,6 +111,33 @@
>  	</listitem>
>        </varlistentry>
>  
> +      <varlistentry>
> +	<term>nfs4acl_xattr:nfs4_id_numeric = yes|no (default: no)</term>
> +	<listitem>
> +	  <para>This parameter tells the module how the NFS4 server encodes user
> +	  and group identifiers on the network. With the default setting the
> +	  module expects identifiers encoded as per the NFS4 RFC as
> +	  user at domain.</para>
> +	  <para>When set to <emphasis>yes</emphasis>, the module expects the
> +	  identifiers as numeric string.</para>
> +	  <para>The default for this options<emphasis>no</emphasis>.</para>
> +	</listitem>
> +      </varlistentry>
> +
> +      <varlistentry>
> +	<term>nfs4acl_xattr:validate_mode = yes|no</term>
> +	<listitem>
> +	  <para>This parameter configures whether the module enforces the POSIX
> +	  mode is set to 0777 for directores and 0666 for files. If this
> +	  constrained is not met, the xattr with the ACL blob is
> +	  discarded.</para>
> +	  <para>The default depends on the setting for
> +	  <emphasis>nfs4acl_xattr:encoding</emphasis>: when set to
> +	  <emphasis>nfs</emphasis> this setting is disabled by default,
> +	  otherwise it is enabled.</para>
> +	</listitem>
> +      </varlistentry>
> +
>      </variablelist>
>    </refsect1>
>  
> diff --git a/source3/modules/nfs4acl_xattr.h b/source3/modules/nfs4acl_xattr.h
> index d0c0b81fbd1..0adede156ba 100644
> --- a/source3/modules/nfs4acl_xattr.h
> +++ b/source3/modules/nfs4acl_xattr.h
> @@ -24,6 +24,7 @@
>  enum nfs4acl_encoding {
>  	NFS4ACL_ENCODING_NDR,
>  	NFS4ACL_ENCODING_XDR,
> +	NFS4ACL_ENCODING_NFS
>  };
>  
>  struct nfs4acl_config {
> @@ -32,6 +33,8 @@ struct nfs4acl_config {
>  	char *xattr_name;
>  	struct smbacl4_vfs_params nfs4_params;
>  	enum default_acl_style default_acl_style;
> +	bool nfs4_id_numeric;
> +	bool validate_mode;
>  };
>  
>  #endif /* __NFS4ACL_XATTR_H__ */
> diff --git a/source3/modules/nfs4acl_xattr_nfs.c b/source3/modules/nfs4acl_xattr_nfs.c
> new file mode 100644
> index 00000000000..88f1c04b0ea
> --- /dev/null
> +++ b/source3/modules/nfs4acl_xattr_nfs.c
> @@ -0,0 +1,890 @@
> +/*
> + * Copyright (C) Ralph Boehme 2018
> + *
> + * 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 "smbd/proto.h"
> +#include "system/passwd.h"
> +#include "libcli/security/security_descriptor.h"
> +#include "libcli/security/security_token.h"
> +
> +#ifdef HAVE_RPC_XDR_H
> +/* <rpc/xdr.h> uses TRUE and FALSE */
> +#ifdef TRUE
> +#undef TRUE
> +#endif
> +
> +#ifdef FALSE
> +#undef FALSE
> +#endif
> +
> +#include <rpc/xdr.h>
> +
> +#include "nfs4_acls.h"
> +#include "nfs41acl.h"
> +#include "nfs4acl_xattr.h"
> +#include "nfs4acl_xattr_nfs.h"
> +#include "nfs4acl_xattr_util.h"
> +
> +#undef DBGC_CLASS
> +#define DBGC_CLASS DBGC_VFS
> +
> +#define OVERFLOW_CHECK(val1, val2) ((val1) + (val2) < (val1))
> +#define XDR_UTF8STR_ALIGNMENT 4
> +#define XDR_UTF8STR_ALIGN(l) \
> +	(((l) + ((XDR_UTF8STR_ALIGNMENT) - 1)) & ~((XDR_UTF8STR_ALIGNMENT) - 1))
> +
> +static struct nfs4_to_smb4_id_map {
> +	const char *nfs4_id;
> +	uint32_t smb4_id;
> +} nfs4_to_smb4_id_map[] = {
> +	{"OWNER@",		SMB_ACE4_WHO_OWNER},
> +	{"GROUP@",		SMB_ACE4_WHO_GROUP},
> +	{"EVERYONE@",		SMB_ACE4_WHO_EVERYONE},
> +	{"INTERACTIVE@",	SMB_ACE4_WHO_INTERACTIVE},
> +	{"NETWORK@",		SMB_ACE4_WHO_NETWORK},
> +	{"DIALUP@",		SMB_ACE4_WHO_DIALUP},
> +	{"BATCH@",		SMB_ACE4_WHO_BATCH},
> +	{"ANONYMOUS@",		SMB_ACE4_WHO_ANONYMOUS},
> +	{"AUTHENTICATED@",	SMB_ACE4_WHO_AUTHENTICATED},
> +	{"SERVICE@",		SMB_ACE4_WHO_SERVICE},
> +};
> +
> +static bool is_special_nfs4_id(const char *nfs4_id)
> +{
> +	char *at = NULL;
> +
> +	at = strchr(nfs4_id, '@');
> +	if (at == NULL) {
> +		return false;
> +	}
> +	if (at[1] != '\0') {
> +		return false;
> +	}
> +	return true;
> +}
> +
> +static bool map_special_nfs4_to_smb4_id(const char *nfs4_id, uint32_t *smb4_id)
> +{
> +	size_t i;
> +	int cmp;
> +
> +	for (i = 0; i < ARRAY_SIZE(nfs4_to_smb4_id_map); i++) {
> +		cmp = strcmp(nfs4_to_smb4_id_map[i].nfs4_id, nfs4_id);
> +		if (cmp != 0) {
> +			continue;
> +		}
> +		*smb4_id = nfs4_to_smb4_id_map[i].smb4_id;
> +		return true;
> +	}
> +	return false;
> +}
> +
> +static bool map_special_smb4_to_nfs4_id(uint32_t smb4_id, const char **nfs4_id)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(nfs4_to_smb4_id_map); i++) {
> +		if (nfs4_to_smb4_id_map[i].smb4_id != smb4_id) {
> +			continue;
> +		}
> +		*nfs4_id = nfs4_to_smb4_id_map[i].nfs4_id;
> +		return true;
> +	}
> +	return false;
> +}
> +
> +static unsigned nfs40acl_get_naces(nfsacl40 *nacl)
> +{
> +	return nacl->na40_aces.na40_aces_len;
> +}
> +
> +static unsigned nfs41acl_get_naces(nfsacl41 *nacl)
> +{
> +	return nacl->na41_aces.na41_aces_len;
> +}
> +
> +static void nfs40acl_set_naces(nfsacl40 *nacl, unsigned naces)
> +{
> +	nacl->na40_aces.na40_aces_len = naces;
> +}
> +
> +static void nfs41acl_set_naces(nfsacl41 *nacl, unsigned naces)
> +{
> +	nacl->na41_aces.na41_aces_len = naces;
> +}
> +
> +static unsigned nfs41acl_get_flags(nfsacl41 *nacl)
> +{
> +	return nacl->na41_flag;
> +}
> +
> +static void nfs41acl_set_flags(nfsacl41 *nacl, unsigned flags)
> +{
> +	nacl->na41_flag = flags;
> +}
> +
> +static nfsace4 *nfs40acl_get_ace(nfsacl40 *nacl, size_t n)
> +{
> +	return &nacl->na40_aces.na40_aces_val[n];
> +}
> +
> +static nfsace4 *nfs41acl_get_ace(nfsacl41 *nacl, size_t n)
> +{
> +	return &nacl->na41_aces.na41_aces_val[n];
> +}
> +
> +static size_t nfs40acl_get_xdrblob_size(nfsacl40 *nacl)
> +{
> +	size_t acl_size;
> +	size_t aces_size;
> +	size_t identifier_size;
> +	unsigned i;
> +	unsigned naces = nfs40acl_get_naces(nacl);
> +
> +	/* ACE structure minus actual identifier strings */
> +	struct nfsace4_size {
> +		acetype4 type;
> +		aceflag4 flag;
> +		acemask4 access_mask;
> +		u_int who_length;
> +	};
> +
> +	/*
> +	 * acl_size =
> +	 *   sizeof(ace_count) +
> +	 *   (ace_count * (sizeof(nfsace4_size)) +
> +	 *   length of all identifiers strings
> +	 */
> +
> +	acl_size = sizeof(unsigned);
> +
> +	if (naces > NFS4ACL_XDR_MAX_ACES) {
> +		DBG_ERR("Too many ACEs: %u", naces);
> +		return 0;
> +	}
> +
> +	aces_size = naces * sizeof(struct nfsace4_size);
> +
> +	if (OVERFLOW_CHECK(acl_size, aces_size)) {
> +		DBG_ERR("Integer Overflow error\n");
> +		return 0;
> +	}
> +	acl_size += aces_size;
> +
> +	identifier_size = 0;
> +	for (i = 0;  i < naces; i++) {
> +		nfsace4 *nace = nfs40acl_get_ace(nacl, i);
> +		size_t string_size = nace->who.utf8string_len;
> +		size_t id_size;
> +
> +		id_size = XDR_UTF8STR_ALIGN(string_size);
> +
> +		if (OVERFLOW_CHECK(identifier_size, id_size)) {
> +			DBG_ERR("Integer Overflow error\n");
> +			return 0;
> +		}
> +		identifier_size += id_size;
> +	}
> +
> +	if (OVERFLOW_CHECK(acl_size, identifier_size)) {
> +		DBG_ERR("Integer Overflow error\n");
> +		return 0;
> +	}
> +	acl_size += identifier_size;
> +
> +	DBG_DEBUG("acl_size: %zd\n", acl_size);
> +	return acl_size;
> +}
> +
> +static size_t nfs41acl_get_xdrblob_size(nfsacl41 *nacl)
> +{
> +	size_t acl_size;
> +	size_t aces_size;
> +	size_t identifier_size;
> +	unsigned i;
> +	unsigned naces = nfs41acl_get_naces(nacl);
> +
> +	/* ACE structure minus actual identifier strings */
> +	struct nfsace4_size {
> +		acetype4 type;
> +		aceflag4 flag;
> +		acemask4 access_mask;
> +		u_int who_length;
> +	};
> +
> +	/*
> +	 * acl_size =
> +	 *   sizeof(acl_flag) +
> +	 *   sizeof(ace_count) +
> +	 *   (ace_count * (sizeof(nfsace4_size)) +
> +	 *   length of all identifiers strings
> +	 */
> +
> +	acl_size = 2 * sizeof(unsigned);
> +
> +	if (naces > NFS4ACL_XDR_MAX_ACES) {
> +		DBG_ERR("Too many ACEs: %u", naces);
> +		return 0;
> +	}
> +
> +	aces_size = naces * sizeof(struct nfsace4_size);
> +
> +	if (OVERFLOW_CHECK(acl_size, aces_size)) {
> +		DBG_ERR("Integer Overflow error\n");
> +		return 0;
> +	}
> +	acl_size += aces_size;
> +
> +	identifier_size = 0;
> +	for (i = 0;  i < naces; i++) {
> +		nfsace4 *nace = nfs41acl_get_ace(nacl, i);
> +		size_t string_size = nace->who.utf8string_len;
> +		size_t id_size;
> +
> +		id_size = XDR_UTF8STR_ALIGN(string_size);
> +
> +		if (OVERFLOW_CHECK(identifier_size, id_size)) {
> +			DBG_ERR("Integer Overflow error\n");
> +			return 0;
> +		}
> +		identifier_size += id_size;
> +	}
> +
> +	if (OVERFLOW_CHECK(acl_size, identifier_size)) {
> +		DBG_ERR("Integer Overflow error\n");
> +		return 0;
> +	}
> +	acl_size += identifier_size;
> +
> +	DBG_DEBUG("acl_size: %zd\n", acl_size);
> +	return acl_size;
> +}
> +
> +static nfsacl40 *nfs40acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
> +{
> +	size_t acl_size;
> +	size_t aces_size;
> +	nfsacl40 *nacl = NULL;
> +
> +	if (naces > NFS4ACL_XDR_MAX_ACES) {
> +		DBG_ERR("Too many ACEs: %d\n", naces);
> +		return NULL;
> +	}
> +
> +	acl_size = sizeof(nfsacl40);
> +	aces_size = (naces * sizeof(struct nfsace4));
> +
> +	if (OVERFLOW_CHECK(acl_size, aces_size)) {
> +		DBG_ERR("Integer Overflow error\n");
> +		return NULL;
> +	}
> +	acl_size += aces_size;
> +
> +	nacl = talloc_zero_size(mem_ctx, acl_size);
> +	if (nacl == NULL) {
> +		DBG_ERR("talloc_zero_size failed\n");
> +		return NULL;
> +	}
> +
> +	nfs40acl_set_naces(nacl, naces);
> +	nacl->na40_aces.na40_aces_val =
> +		(nfsace4 *)((uint8_t *)nacl + sizeof(nfsacl40));
> +
> +	return nacl;
> +}
> +
> +static nfsacl41 *nfs41acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
> +{
> +	size_t acl_size;
> +	size_t aces_size;
> +	nfsacl41 *nacl = NULL;
> +
> +	if (naces > NFS4ACL_XDR_MAX_ACES) {
> +		DBG_ERR("Too many ACEs: %d\n", naces);
> +		return NULL;
> +	}
> +
> +	acl_size = sizeof(nfsacl41);
> +	aces_size = (naces * sizeof(struct nfsace4));
> +
> +	if (OVERFLOW_CHECK(acl_size, aces_size)) {
> +		DBG_ERR("Integer Overflow error\n");
> +		return NULL;
> +	}
> +	acl_size += aces_size;
> +
> +	nacl = talloc_zero_size(mem_ctx, acl_size);
> +	if (nacl == NULL) {
> +		DBG_ERR("talloc_zero_size failed\n");
> +		return NULL;
> +	}
> +
> +	nfs41acl_set_naces(nacl, naces);
> +	nacl->na41_aces.na41_aces_val =
> +		(nfsace4 *)((uint8_t *)nacl + sizeof(nfsacl41));
> +
> +	return nacl;
> +}
> +
> +static bool create_special_id(TALLOC_CTX *mem_ctx,
> +			      nfsace4 *nace,
> +			      const char *id)
> +{
> +	char *s = talloc_strdup(mem_ctx, id);
> +
> +	if (s == NULL) {
> +		DBG_ERR("talloc_memdup failed\n");
> +		return false;
> +	}
> +	nace->who.utf8string_val = s;
> +	nace->who.utf8string_len = talloc_get_size(s) - 1;
> +	return true;
> +}
> +
> +static bool map_smb4_to_nfs4_id(TALLOC_CTX *mem_ctx,
> +				struct nfs4acl_config *config,
> +				nfsace4 *nace,
> +				SMB_ACE4PROP_T *sace)
> +{
> +	const char *nfs4_id = NULL;
> +	const char *name = NULL;
> +	char *ace_name = NULL;
> +	uid_t id;
> +	bool ok;
> +
> +	if (sace->flags & SMB_ACE4_ID_SPECIAL) {
> +		ok = map_special_smb4_to_nfs4_id(sace->who.special_id,
> +						 &nfs4_id);
> +		if (!ok) {
> +			DBG_ERR("Unsupported special id [%"PRIu32"]\n",
> +				sace->who.special_id);
> +			return false;
> +		}
> +
> +		ok = create_special_id(mem_ctx, nace, nfs4_id);
> +		if (!ok) {
> +			return false;
> +		}
> +		DBG_DEBUG("Special id [%s]\n", nace->who.utf8string_val);
> +		return true;
> +	}
> +
> +	if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
> +		nace->flag |= ACE4_IDENTIFIER_GROUP;
> +	}
> +
> +	if (config->nfs4_id_numeric) {
> +		char *strid = NULL;
> +
> +		if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
> +			id = sace->who.gid;
> +		} else {
> +			id = sace->who.uid;
> +		}
> +
> +		strid = talloc_asprintf(mem_ctx, "%jd", (intmax_t)id);
> +		if (strid == NULL) {
> +			DBG_ERR("talloc_asprintf failed\n");
> +			return false;
> +		}
> +		nace->who.utf8string_val = strid;
> +		nace->who.utf8string_len = talloc_get_size(strid) - 1;
> +		DBG_DEBUG("Numeric id [%s]\n", nace->who.utf8string_val);
> +		return true;
> +	}
> +
> +	if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
> +		struct group *grp = NULL;
> +
> +		grp = getgrgid(sace->who.gid);
> +		if (grp == NULL) {
> +			DBG_ERR("Unknown gid [%jd]\n", (intmax_t)sace->who.gid);
> +			return false;
> +		}
> +		name = grp->gr_name;
> +	} else {
> +		struct passwd *pwd = NULL;
> +
> +		pwd = getpwuid(sace->who.uid);
> +		if (pwd == NULL) {
> +			DBG_ERR("Unknown uid [%jd]\n", (intmax_t)sace->who.uid);
> +			return false;
> +		}
> +		name = pwd->pw_name;
> +	}
> +
> +	ace_name = talloc_strdup(mem_ctx, name);
> +	if (ace_name == NULL) {
> +		DBG_ERR("talloc_asprintf failed\n");
> +		return false;
> +	}
> +	nace->who.utf8string_val = ace_name;
> +	nace->who.utf8string_len = talloc_get_size(ace_name) - 1;
> +
> +	DBG_DEBUG("id [%s]\n", nace->who.utf8string_val);
> +	return true;
> +}
> +
> +static bool smb4acl_to_nfs40acl(vfs_handle_struct *handle,
> +			       TALLOC_CTX *mem_ctx,
> +			       struct SMB4ACL_T *smb4acl,
> +			       nfsacl40 **_nacl)
> +{
> +	struct nfs4acl_config *config = NULL;
> +	struct SMB4ACE_T *smb4ace = NULL;
> +	nfsacl40 *nacl = NULL;
> +	size_t naces = smb_get_naces(smb4acl);
> +	bool ok;
> +
> +	SMB_VFS_HANDLE_GET_DATA(handle, config,
> +				struct nfs4acl_config,
> +				return false);
> +
> +	nacl = nfs40acl_alloc(mem_ctx, naces);
> +	nfs40acl_set_naces(nacl, 0);
> +
> +	smb4ace = smb_first_ace4(smb4acl);
> +	while (smb4ace != NULL) {
> +		SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
> +		size_t nace_count = nfs40acl_get_naces(nacl);
> +		nfsace4 *nace = nfs40acl_get_ace(nacl, nace_count);
> +
> +		nace->type = ace4prop->aceType;
> +		nace->flag = ace4prop->aceFlags;
> +		nace->access_mask = ace4prop->aceMask;
> +
> +		ok = map_smb4_to_nfs4_id(nacl, config, nace, ace4prop);
> +		if (!ok) {
> +			smb4ace = smb_next_ace4(smb4ace);
> +			continue;
> +		}
> +
> +		nace_count++;
> +		nfs40acl_set_naces(nacl, nace_count);
> +		smb4ace = smb_next_ace4(smb4ace);
> +	}
> +
> +	*_nacl = nacl;
> +	return true;
> +}
> +
> +static bool smb4acl_to_nfs41acl(vfs_handle_struct *handle,
> +			       TALLOC_CTX *mem_ctx,
> +			       struct SMB4ACL_T *smb4acl,
> +			       nfsacl41 **_nacl)
> +{
> +	struct nfs4acl_config *config = NULL;
> +	struct SMB4ACE_T *smb4ace = NULL;
> +	nfsacl41 *nacl = NULL;
> +	size_t naces = smb_get_naces(smb4acl);
> +	uint16_t smb4acl_flags;
> +	unsigned nacl_flags;
> +	bool ok;
> +
> +	SMB_VFS_HANDLE_GET_DATA(handle, config,
> +				struct nfs4acl_config,
> +				return false);
> +
> +	nacl = nfs41acl_alloc(mem_ctx, naces);
> +	nfs41acl_set_naces(nacl, 0);
> +
> +	smb4acl_flags = smbacl4_get_controlflags(smb4acl);
> +	nacl_flags = smb4acl_to_nfs4acl_flags(smb4acl_flags);
> +	nfs41acl_set_flags(nacl, nacl_flags);
> +
> +	smb4ace = smb_first_ace4(smb4acl);
> +	while (smb4ace != NULL) {
> +		SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
> +		size_t nace_count = nfs41acl_get_naces(nacl);
> +		nfsace4 *nace = nfs41acl_get_ace(nacl, nace_count);
> +
> +		nace->type = ace4prop->aceType;
> +		nace->flag = ace4prop->aceFlags;
> +		nace->access_mask = ace4prop->aceMask;
> +
> +		ok = map_smb4_to_nfs4_id(nacl, config, nace, ace4prop);
> +		if (!ok) {
> +			smb4ace = smb_next_ace4(smb4ace);
> +			continue;
> +		}
> +
> +		nace_count++;
> +		nfs41acl_set_naces(nacl, nace_count);
> +		smb4ace = smb_next_ace4(smb4ace);
> +	}
> +
> +	*_nacl = nacl;
> +	return true;
> +}
> +
> +NTSTATUS nfs4acl_smb4acl_to_nfs_blob(vfs_handle_struct *handle,
> +				     TALLOC_CTX *mem_ctx,
> +				     struct SMB4ACL_T *smb4acl,
> +				     DATA_BLOB *_blob)
> +{
> +	struct nfs4acl_config *config = NULL;
> +	nfsacl40 *nacl40 = NULL;
> +	nfsacl41 *nacl41 = NULL;
> +	XDR xdr = {0};
> +	size_t aclblobsize;
> +	DATA_BLOB blob;
> +	bool ok;
> +
> +	SMB_VFS_HANDLE_GET_DATA(handle, config,
> +				struct nfs4acl_config,
> +				return NT_STATUS_INTERNAL_ERROR);
> +
> +	if (config->nfs_version == ACL4_XATTR_VERSION_40) {
> +		ok = smb4acl_to_nfs40acl(handle, mem_ctx, smb4acl, &nacl40);
> +		if (!ok) {
> +			DBG_ERR("smb4acl_to_nfs4acl failed\n");
> +			return NT_STATUS_INTERNAL_ERROR;
> +		}
> +
> +		aclblobsize = nfs40acl_get_xdrblob_size(nacl40);
> +		if (aclblobsize == 0) {
> +			DBG_ERR("Error calculating XDR blob size\n");
> +			return NT_STATUS_INTERNAL_ERROR;
> +		}
> +	} else {
> +		ok = smb4acl_to_nfs41acl(handle, mem_ctx, smb4acl, &nacl41);
> +		if (!ok) {
> +			DBG_ERR("smb4acl_to_nfs4acl failed\n");
> +			return NT_STATUS_INTERNAL_ERROR;
> +		}
> +
> +		aclblobsize = nfs41acl_get_xdrblob_size(nacl41);
> +		if (aclblobsize == 0) {
> +			DBG_ERR("Error calculating XDR blob size\n");
> +			return NT_STATUS_INTERNAL_ERROR;
> +		}
> +	}
> +
> +	blob = data_blob_talloc(mem_ctx, NULL, aclblobsize);
> +	if (blob.data == NULL) {
> +		TALLOC_FREE(nacl40);
> +		TALLOC_FREE(nacl41);
> +		return NT_STATUS_NO_MEMORY;
> +	}
> +
> +	xdrmem_create(&xdr, (char *)blob.data, blob.length, XDR_ENCODE);
> +
> +	if (config->nfs_version == ACL4_XATTR_VERSION_40) {
> +		ok = xdr_nfsacl40(&xdr, nacl40);
> +		TALLOC_FREE(nacl40);
> +		if (!ok) {
> +			DBG_ERR("xdr_nfs4acl40 failed\n");
> +			return NT_STATUS_NO_MEMORY;
> +		}
> +	} else {
> +		ok = xdr_nfsacl41(&xdr, nacl41);
> +		TALLOC_FREE(nacl41);
> +		if (!ok) {
> +			DBG_ERR("xdr_nfs4acl40 failed\n");
> +			return NT_STATUS_NO_MEMORY;
> +		}
> +	}
> +
> +	*_blob = blob;
> +	return NT_STATUS_OK;
> +}
> +
> +static NTSTATUS nfs4acl_nfs_blob_to_nfs40acl(struct vfs_handle_struct *handle,
> +					     TALLOC_CTX *mem_ctx,
> +					     DATA_BLOB *blob,
> +					     nfsacl40 **_nacl)
> +{
> +	nfsacl40 *nacl = NULL;
> +	XDR xdr = {0};
> +	bool ok;
> +
> +	nacl = talloc_zero_size(mem_ctx, sizeof(nfsacl40));
> +	if (nacl == NULL) {
> +		DBG_ERR("talloc_zero_size failed\n");
> +		return NT_STATUS_NO_MEMORY;
> +	}
> +
> +	xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
> +
> +	ok = xdr_nfsacl40(&xdr, nacl);
> +	if (!ok) {
> +		DBG_ERR("xdr_nfsacl40 failed\n");
> +		return NT_STATUS_INTERNAL_ERROR;
> +	}
> +
> +	DBG_DEBUG("naces = %d \n", nacl->na40_aces.na40_aces_len);
> +
> +	*_nacl = nacl;
> +	return NT_STATUS_OK;
> +}
> +
> +static NTSTATUS nfs4acl_nfs_blob_to_nfs41acl(struct vfs_handle_struct *handle,
> +					     TALLOC_CTX *mem_ctx,
> +					     DATA_BLOB *blob,
> +					     nfsacl41 **_nacl)
> +{
> +	nfsacl41 *nacl = NULL;
> +	XDR xdr = {0};
> +	bool ok;
> +
> +	nacl = talloc_zero_size(mem_ctx, sizeof(nfsacl41));
> +	if (nacl == NULL) {
> +		DBG_ERR("talloc_zero_size failed\n");
> +		return NT_STATUS_NO_MEMORY;
> +	}
> +
> +	xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
> +
> +	ok = xdr_nfsacl41(&xdr, nacl);
> +	if (!ok) {
> +		DBG_ERR("xdr_nfsacl40 failed\n");
> +		return NT_STATUS_INTERNAL_ERROR;
> +	}
> +
> +	DBG_DEBUG("naces = %d \n", nacl->na41_aces.na41_aces_len);
> +
> +	*_nacl = nacl;
> +	return NT_STATUS_OK;
> +}
> +
> +static bool map_ace_nfs4_to_smb4(struct nfs4acl_config *config,
> +				 const nfsace4 *nace,
> +				 SMB_ACE4PROP_T *sace)
> +{
> +	char *name = NULL;
> +	char *p = NULL;
> +	uint32_t smb4_id;
> +	bool ok;
> +
> +	name = talloc_strndup(talloc_tos(),
> +			      nace->who.utf8string_val,
> +			      nace->who.utf8string_len);
> +	if (name == NULL) {
> +		return false;
> +	}
> +
> +	sace->aceType = nace->type;
> +	sace->aceFlags = nace->flag;
> +	sace->aceMask = nace->access_mask;
> +
> +	if (is_special_nfs4_id(name)) {
> +		ok = map_special_nfs4_to_smb4_id(name, &smb4_id);
> +		if (!ok) {
> +			DBG_WARNING("Unknown special id [%s]\n", name);
> +			return false;
> +		}
> +		sace->flags |= SMB_ACE4_ID_SPECIAL;
> +		sace->who.special_id = smb4_id;
> +		return true;
> +	}
> +
> +	p = strtok(name, "@");
> +	if (p == NULL && !config->nfs4_id_numeric) {
> +		DBG_ERR("Unqualified name [%s]\n", name);
> +		TALLOC_FREE(name);
> +		return false;
> +	}
> +
> +	/*
> +	 * nametouid() and nametogid() work with both names and numbers...
> +	 */
> +
> +	if (nace->flag & ACE4_IDENTIFIER_GROUP) {
> +		sace->who.gid = nametogid(name);
> +		if (sace->who.gid == (gid_t)-1) {
> +			DBG_ERR("converting id [%s] failed\n", name);
> +			TALLOC_FREE(name);
> +			return false;
> +		}
> +		TALLOC_FREE(name);
> +		return true;
> +	}
> +
> +	sace->who.uid = nametouid(name);
> +	if (sace->who.uid == (gid_t)-1) {
> +		DBG_ERR("converting id [%s] failed\n", name);
> +		TALLOC_FREE(name);
> +		return false;
> +	}
> +	TALLOC_FREE(name);
> +	return true;
> +}
> +
> +static NTSTATUS nfs40acl_to_smb4acl(struct vfs_handle_struct *handle,
> +				   TALLOC_CTX *mem_ctx,
> +				   nfsacl40 *nacl,
> +				   struct SMB4ACL_T **_smb4acl)
> +{
> +	struct nfs4acl_config *config = NULL;
> +	struct SMB4ACL_T *smb4acl = NULL;
> +	unsigned naces = nfs40acl_get_naces(nacl);
> +	unsigned int i;
> +	bool ok;
> +
> +	SMB_VFS_HANDLE_GET_DATA(handle, config,
> +				struct nfs4acl_config,
> +				return NT_STATUS_INTERNAL_ERROR);
> +
> +	smb4acl = smb_create_smb4acl(mem_ctx);
> +	if (smb4acl == NULL) {
> +		return NT_STATUS_INTERNAL_ERROR;
> +	}
> +
> +	DBG_DEBUG("nace [%u]\n", naces);
> +
> +	for (i = 0; i < naces; i++) {
> +		nfsace4 *nace = nfs40acl_get_ace(nacl, i);
> +		SMB_ACE4PROP_T sace = { 0 };
> +
> +		DBG_DEBUG("type [%d] flag [%x] mask [%x] who [%*s]\n",
> +			  nace->type, nace->flag,
> +			  nace->access_mask,
> +			  nace->who.utf8string_len,
> +			  nace->who.utf8string_val);
> +
> +		ok = map_ace_nfs4_to_smb4(config, nace, &sace);
> +		if (!ok) {
> +			continue;
> +		}
> +
> +		smb_add_ace4(smb4acl, &sace);
> +	}
> +
> +	*_smb4acl = smb4acl;
> +	return NT_STATUS_OK;
> +}
> +
> +static NTSTATUS nfs41acl_to_smb4acl(struct vfs_handle_struct *handle,
> +				   TALLOC_CTX *mem_ctx,
> +				   nfsacl41 *nacl,
> +				   struct SMB4ACL_T **_smb4acl)
> +{
> +	struct nfs4acl_config *config = NULL;
> +	struct SMB4ACL_T *smb4acl = NULL;
> +	unsigned nfsacl41_flag = 0;
> +	uint16_t smb4acl_flags = 0;
> +	unsigned naces = nfs41acl_get_naces(nacl);
> +	unsigned int i;
> +	bool ok;
> +
> +	SMB_VFS_HANDLE_GET_DATA(handle, config,
> +				struct nfs4acl_config,
> +				return NT_STATUS_INTERNAL_ERROR);
> +
> +	smb4acl = smb_create_smb4acl(mem_ctx);
> +	if (smb4acl == NULL) {
> +		return NT_STATUS_INTERNAL_ERROR;
> +	}
> +
> +	nfsacl41_flag = nfs41acl_get_flags(nacl);
> +	smb4acl_flags = nfs4acl_to_smb4acl_flags(nfsacl41_flag);
> +	smbacl4_set_controlflags(smb4acl, smb4acl_flags);
> +
> +	DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags, naces);
> +
> +	for (i = 0; i < naces; i++) {
> +		nfsace4 *nace = nfs41acl_get_ace(nacl, i);
> +		SMB_ACE4PROP_T sace = { 0 };
> +
> +		DBG_DEBUG("type [%d] flag [%x] mask [%x] who [%*s]\n",
> +			  nace->type, nace->flag,
> +			  nace->access_mask,
> +			  nace->who.utf8string_len,
> +			  nace->who.utf8string_val);
> +
> +		ok = map_ace_nfs4_to_smb4(config, nace, &sace);
> +		if (!ok) {
> +			continue;
> +		}
> +
> +		smb_add_ace4(smb4acl, &sace);
> +	}
> +
> +	*_smb4acl = smb4acl;
> +	return NT_STATUS_OK;
> +}
> +
> +NTSTATUS nfs4acl_nfs_blob_to_smb4(struct vfs_handle_struct *handle,
> +				  TALLOC_CTX *mem_ctx,
> +				  DATA_BLOB *blob,
> +				  struct SMB4ACL_T **_smb4acl)
> +{
> +	struct nfs4acl_config *config = NULL;
> +	struct SMB4ACL_T *smb4acl = NULL;
> +	NTSTATUS status;
> +
> +	SMB_VFS_HANDLE_GET_DATA(handle, config,
> +				struct nfs4acl_config,
> +				return NT_STATUS_INTERNAL_ERROR);
> +
> +	if (config->nfs_version == ACL4_XATTR_VERSION_40) {
> +		nfsacl40 *nacl = NULL;
> +
> +		status = nfs4acl_nfs_blob_to_nfs40acl(handle,
> +						      talloc_tos(),
> +						      blob,
> +						      &nacl);
> +		if (!NT_STATUS_IS_OK(status)) {
> +			return status;
> +		}
> +
> +		status = nfs40acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
> +		TALLOC_FREE(nacl);
> +		if (!NT_STATUS_IS_OK(status)) {
> +			return status;
> +		}
> +	} else {
> +		nfsacl41 *nacl = NULL;
> +
> +		status = nfs4acl_nfs_blob_to_nfs41acl(handle,
> +						      talloc_tos(),
> +						      blob,
> +						      &nacl);
> +		if (!NT_STATUS_IS_OK(status)) {
> +			return status;
> +		}
> +
> +		status = nfs41acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
> +		TALLOC_FREE(nacl);
> +		if (!NT_STATUS_IS_OK(status)) {
> +			return status;
> +		}
> +	}
> +
> +	*_smb4acl = smb4acl;
> +	return NT_STATUS_OK;
> +}
> +
> +#else /* !HAVE_RPC_XDR_H */
> +#include "nfs4acl_xattr_nfs.h"
> +NTSTATUS nfs4acl_nfs_blob_to_smb4(struct vfs_handle_struct *handle,
> +				  TALLOC_CTX *mem_ctx,
> +				  DATA_BLOB *blob,
> +				  struct SMB4ACL_T **_smb4acl)
> +{
> +	return NT_STATUS_NOT_SUPPORTED;
> +}
> +
> +NTSTATUS nfs4acl_smb4acl_to_nfs_blob(vfs_handle_struct *handle,
> +				     TALLOC_CTX *mem_ctx,
> +				     struct SMB4ACL_T *smbacl,
> +				     DATA_BLOB *blob)
> +{
> +	return NT_STATUS_NOT_SUPPORTED;
> +}
> +#endif /* HAVE_RPC_XDR_H */
> diff --git a/source3/modules/nfs4acl_xattr_nfs.h b/source3/modules/nfs4acl_xattr_nfs.h
> new file mode 100644
> index 00000000000..47e5b1a48c1
> --- /dev/null
> +++ b/source3/modules/nfs4acl_xattr_nfs.h
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (C) Ralph Boehme 2018
> + *
> + * 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/>.
> + *
> + */
> +
> +#ifndef __NFS4ACL_XATTR_NFS_H__
> +#define __NFS4ACL_XATTR_NFS_H__
> +
> +#define NFS4ACL_NFS_XATTR_NAME "system.nfs4_acl"
> +
> +NTSTATUS nfs4acl_nfs_blob_to_smb4(struct vfs_handle_struct *handle,
> +				  TALLOC_CTX *mem_ctx,
> +				  DATA_BLOB *blob,
> +				  struct SMB4ACL_T **_smb4acl);
> +
> +NTSTATUS nfs4acl_smb4acl_to_nfs_blob(vfs_handle_struct *handle,
> +				     TALLOC_CTX *mem_ctx,
> +				     struct SMB4ACL_T *smbacl,
> +				     DATA_BLOB *blob);
> +
> +#endif /* __NFS4ACL_XATTR_NFS_H__ */
> diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c
> index 65387af2c0e..f0995810d8c 100644
> --- a/source3/modules/vfs_nfs4acl_xattr.c
> +++ b/source3/modules/vfs_nfs4acl_xattr.c
> @@ -36,6 +36,7 @@
>  #include "nfs4acl_xattr.h"
>  #include "nfs4acl_xattr_ndr.h"
>  #include "nfs4acl_xattr_xdr.h"
> +#include "nfs4acl_xattr_nfs.h"
>  
>  #undef DBGC_CLASS
>  #define DBGC_CLASS DBGC_VFS
> @@ -43,6 +44,7 @@
>  static const struct enum_list nfs4acl_encoding[] = {
>  	{NFS4ACL_ENCODING_NDR, "ndr"},
>  	{NFS4ACL_ENCODING_XDR, "xdr"},
> +	{NFS4ACL_ENCODING_NFS, "nfs"},
>  };
>  
>  /*
> @@ -61,6 +63,10 @@ static bool nfs4acl_validate_blob(vfs_handle_struct *handle,
>  				struct nfs4acl_config,
>  				return false);
>  
> +	if (!config->validate_mode) {
> +		return true;
> +	}
> +
>  	if (!VALID_STAT(smb_fname->st)) {
>  		/* might be a create */
>  		return true;
> @@ -229,6 +235,9 @@ static NTSTATUS nfs4acl_blob_to_smb4(struct vfs_handle_struct *handle,
>  	case NFS4ACL_ENCODING_XDR:
>  		status = nfs4acl_xdr_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
>  		break;
> +	case NFS4ACL_ENCODING_NFS:
> +		status = nfs4acl_nfs_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
> +		break;
>  	default:
>  		status = NT_STATUS_INTERNAL_ERROR;
>  		break;
> @@ -329,6 +338,10 @@ static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle,
>  		status = nfs4acl_smb4acl_to_xdr_blob(handle, talloc_tos(),
>  						     smb4acl, &blob);
>  		break;
> +	case NFS4ACL_ENCODING_NFS:
> +		status = nfs4acl_smb4acl_to_nfs_blob(handle, talloc_tos(),
> +						     smb4acl, &blob);
> +		break;
>  	default:
>  		status = NT_STATUS_INTERNAL_ERROR;
>  		break;
> @@ -392,6 +405,10 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
>  	} else {
>  		expected_mode = 0666;
>  	}
> +	if (!config->validate_mode) {
> +		existing_mode = 0;
> +		expected_mode = 0;
> +	}
>  	if ((existing_mode & expected_mode) != expected_mode) {
>  		int saved_errno = 0;
>  
> @@ -490,6 +507,7 @@ static int nfs4acl_connect(struct vfs_handle_struct *handle,
>  	struct nfs4acl_config *config = NULL;
>  	const struct enum_list *default_acl_style_list = NULL;
>  	const char *default_xattr_name = NULL;
> +	bool default_validate_mode = true;
>  	int enumval;
>  	unsigned nfs_version;
>  	int ret;
> @@ -529,6 +547,10 @@ static int nfs4acl_connect(struct vfs_handle_struct *handle,
>  	case NFS4ACL_ENCODING_XDR:
>  		default_xattr_name = NFS4ACL_XDR_XATTR_NAME;
>  		break;
> +	case NFS4ACL_ENCODING_NFS:
> +		default_xattr_name = NFS4ACL_NFS_XATTR_NAME;
> +		default_validate_mode = false;
> +		break;
>  	case NFS4ACL_ENCODING_NDR:
>  	default:
>  		default_xattr_name = NFS4ACL_NDR_XATTR_NAME;
> @@ -563,6 +585,17 @@ static int nfs4acl_connect(struct vfs_handle_struct *handle,
>  						   "xattr_name",
>  						   default_xattr_name);
>  
> +	config->nfs4_id_numeric = lp_parm_bool(SNUM(handle->conn),
> +					       "nfs4acl_xattr",
> +					       "nfs4_id_numeric",
> +					       false);
> +
> +
> +	config->validate_mode = lp_parm_bool(SNUM(handle->conn),
> +					     "nfs4acl_xattr",
> +					     "validate_mode",
> +					     default_validate_mode);
> +
>  	SMB_VFS_HANDLE_SET_DATA(handle, config, NULL, struct nfs4acl_config,
>  				return -1);
>  
> diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
> index 5007d58241a..3d19b01908c 100644
> --- a/source3/modules/wscript_build
> +++ b/source3/modules/wscript_build
> @@ -278,6 +278,7 @@ bld.SAMBA3_MODULE('vfs_nfs4acl_xattr',
>                             vfs_nfs4acl_xattr.c
>                             nfs4acl_xattr_ndr.c
>                             nfs4acl_xattr_xdr.c
> +                           nfs4acl_xattr_nfs.c
>                             nfs4acl_xattr_util.c
>                             ''',
>                    deps='NFS4_ACLS sunacl NDR_NFS4ACL VFS_NFS4_XDR',
> -- 
> 2.17.2
> 
> 
> From b3783f426db90370534b9b9e00b5258fc033c285 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Mon, 26 Nov 2018 20:51:14 +0100
> Subject: [PATCH 8/9] selftest: test vfs_nfs4acl_xattr in nfs mode
> 
> The same tests as for the other modes xdr and ndr are marked as
> knownfail.
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  selftest/knownfail        |  9 +++++++++
>  selftest/target/Samba3.pm | 18 ++++++++++++++++++
>  source3/selftest/tests.py |  2 ++
>  3 files changed, 29 insertions(+)
> 
> diff --git a/selftest/knownfail b/selftest/knownfail
> index 750b5f51e3f..fad4daf6c86 100644
> --- a/selftest/knownfail
> +++ b/selftest/knownfail
> @@ -44,6 +44,15 @@
>  ^samba3.raw.acls nfs4acl_xattr-xdr-41.create_owner_file\(nt4_dc\)
>  ^samba3.raw.acls nfs4acl_xattr-xdr-41.create_owner_dir\(nt4_dc\)
>  ^samba3.raw.acls nfs4acl_xattr-xdr-41.nulldacl\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-40.INHERITFLAGS\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-40.create_owner_file\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-40.create_owner_dir\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-40.nulldacl\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-40.inherit_creator_owner\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-40.inherit_creator_group\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-41.create_owner_file\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-41.create_owner_dir\(nt4_dc\)
> +^samba3.raw.acls nfs4acl_xattr-nfs-41.nulldacl\(nt4_dc\)
>  ^samba3.base.delete.deltest16a
>  ^samba3.base.delete.deltest17a
>  ^samba3.unix.whoami anonymous connection.whoami\(ad_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 cbf5309a9a3..647a3b50dfc 100755
> --- a/selftest/target/Samba3.pm
> +++ b/selftest/target/Samba3.pm
> @@ -1973,6 +1973,24 @@ sub provision($$$$$$$$$)
>  	nfs4acl_xattr:encoding = xdr
>  	nfs4acl_xattr:version = 41
>  
> +[nfs4acl_nfs_40]
> +	path = $shrdir
> +	comment = smb username is [%U]
> +	vfs objects = nfs4acl_xattr xattr_tdb
> +	nfs4:mode = simple
> +	nfs4acl_xattr:encoding = nfs
> +	nfs4acl_xattr:version = 40
> +	nfs4acl_xattr:xattr_name = security.nfs4acl_xdr
> +
> +[nfs4acl_nfs_41]
> +	path = $shrdir
> +	comment = smb username is [%U]
> +	vfs objects = nfs4acl_xattr xattr_tdb
> +	nfs4:mode = simple
> +	nfs4acl_xattr:encoding = nfs
> +	nfs4acl_xattr:version = 41
> +	nfs4acl_xattr:xattr_name = security.nfs4acl_xdr
> +
>  [xcopy_share]
>  	path = $shrdir
>  	comment = smb username is [%U]
> diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
> index e8d516573dd..f3fe90fa6ec 100755
> --- a/source3/selftest/tests.py
> +++ b/source3/selftest/tests.py
> @@ -568,6 +568,8 @@ tests = base + raw + smb2 + rpc + unix + local + rap + nbt + libsmbclient + idma
>          plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple_41 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple-41')
>          plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_xdr_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-xdr-40')
>          plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_xdr_41 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-xdr-41')
> +        plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_nfs_40 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-nfs-40')
> +        plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_nfs_41 -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-nfs-41')
>          plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmpcase -U$USERNAME%$PASSWORD')
>      elif t == "smb2.ioctl":
>          plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/fs_specific -U$USERNAME%$PASSWORD', 'fs_specific')
> -- 
> 2.17.2
> 
> 
> From 1378da136f69c6598a5e9a5992fff11b58fadcb4 Mon Sep 17 00:00:00 2001
> From: Ralph Boehme <slow at samba.org>
> Date: Thu, 29 Nov 2018 11:17:08 +0100
> Subject: [PATCH 9/9] vfs_nfs4acl_xattr: check status for
>  NT_STATUS_ACCESS_DENIED in take ownership override
> 
> This was missing in commit 8b1b1cd8cc561378058b915e03996ff567355d81.
> 
> Signed-off-by: Ralph Boehme <slow at samba.org>
> ---
>  source3/modules/vfs_nfs4acl_xattr.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c
> index f0995810d8c..de34929473f 100644
> --- a/source3/modules/vfs_nfs4acl_xattr.c
> +++ b/source3/modules/vfs_nfs4acl_xattr.c
> @@ -448,6 +448,9 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
>  	if (NT_STATUS_IS_OK(status)) {
>  		return NT_STATUS_OK;
>  	}
> +	if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
> +		return status;
> +	}
>  
>  	/*
>  	 * We got access denied. If we're already root, or we didn't
> -- 
> 2.17.2
> 




More information about the samba-technical mailing list