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

Ralph Böhme slow at samba.org
Mon Nov 26 15:48:03 UTC 2018


On Wed, Nov 21, 2018 at 06:21:28PM +0100, Ralph Böhme via samba-technical wrote:
>On Tue, Oct 30, 2018 at 03:57:06PM +0000, Sandeep Nashikkar via samba-technical wrote:
>>It's been couple of months my XDR patch for NFS4ACL_XATTR module is 
>>pending for review.  Can we please expedite this?
>
>sorry, please bear with me, I've had customers sitting on my back all 
>the time. This is now next on my list, so there's light at the end of 
>the tunnel. :)

ok, so what about this one?

The basic idea, for compatibilty with the existing encodings, is adding a new 
nfs4acl_xattr:encoding setting "nfs" and backend. To use the new NFS4 mount 
compatible mode you just set "nfs4acl_xattr:encoding = nfs" and all the rest, 
including xattr name, gets setup automagically.

The patchset supports both 4.0 and 4.1 ACLs.

Support for numeric string NFS4 identifiers is optional and can be enabled with 
"nfs4acl_xattr:nfs4_id_numeric = yes".

The patchset passes basic testing. I'm using a FreeBSD 11 NFS4 server, NFS4 
client is a Linux box with Ubuntu. Both systems are joined to a Samba AD domain 
"SDOM1".

File on the FreeBSD server:

[root at freebsd ~/git/s3]# getfacl /data/slow/file                                                                                                                                                          
# file: /data/slow/file
# owner: SDOM1\administrator
# group: SDOM1\domain users
   user:SDOM1\slow:rwxpDdaARWcCos:-------:allow
            owner@:rw-p--aARWcCos:-------:allow
            group@:rw-p--a-R-c--s:-------:allow
         everyone@:rw-p--a-R-c--s:-------:allow

File on the Linux client:

slow at titan:~/git/samba/scratch$ ls -l /mnt/slow/file 
-rw-rw-rw- 1 SDOM1\administrator SDOM1\domain users 0 Nov 26 13:28 /mnt/slow/file

slow at titan:~/git/samba/scratch$ nfs4_getfacl /mnt/slow/file 
A::2161110:rwadxtTnNcCoy
A::OWNER@:rwatTnNcCoy
A:g:GROUP@:rwatncy
A::EVERYONE@:rwatncy

Looks like nfs4_getfacl doesn't work with numeric mode I'm currently using. :)

But over SMB2 with smbcacls it works correct:

bin/smbcacls -U Administrator%x -m smb3 //localhost/nfs4 file
Unable to initialize messaging context
REVISION:1
CONTROL:SR|DP
OWNER:SDOM1\administrator
GROUP:SDOM1\domain users
ACL:SDOM1\slow:ALLOWED/0x0/FULL
ACL:SDOM1\administrator:ALLOWED/0x0/RWPO
ACL:SDOM1\domain users:ALLOWED/0x0/0x0012008f
ACL:Everyone:ALLOWED/0x0/0x0012008f

Can you give it a whirl and report back? Thanks!

-slow

-- 
Ralph Boehme, Samba Team                https://samba.org/
Samba Developer, SerNet GmbH   https://sernet.de/en/samba/
GPG-Fingerprint   FAE2C6088A24252051C559E4AA1E9B7126399E46
-------------- next part --------------
From cb31aa865c482e19200db1f0027a072283c39b7e 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/8] nfs4acl_xattr: identifiers are XDR encoded as integers

The struct are no RFC 3530 compliant, rename the nfs4 structs, the
trailing i indicates that the struct stores identifiers as integers.

Rename

  struct nfsace4

to

  struct nfsace4i

add

  struct nfsacl41

to

  struct nfsacl41i
---
 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 52ef504775f7b3f3a786459ff67807839cc16e4f 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/8] nfs4acl_xattr: append 'i' to nfs4acl functions

This reflect the new struct names we're working on.
---
 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 a8067451d0571b59affd987a04baac9da82b05e6 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/8] nfs4acl_xattr: move some functions to a seperate file

These functions will be called from another translation unit in a
subsequent commit.
---
 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 db083f50646..3c593bab7f3 100644
--- a/source3/modules/wscript_build
+++ b/source3/modules/wscript_build
@@ -259,6 +259,7 @@ vfs_nfs4acl_xattr_source = '''
                            vfs_nfs4acl_xattr.c
                            nfs4acl_xattr_ndr.c
                            nfs4acl_xattr_xdr.c
+                           nfs4acl_xattr_util.c
                            '''
 
 if bld.CONFIG_SET("HAVE_RPC_XDR_H"):
-- 
2.17.2


From 562ffff5b8a14b3b78bd6bc1bc8dcd1898a23607 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 26 Nov 2018 16:27:28 +0100
Subject: [PATCH 4/8] s3:build: add tirpc to vfs_nfs4acl_xattr

This is needed on modern Linux distros.

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/wscript_build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
index 3c593bab7f3..a14a370777f 100644
--- a/source3/modules/wscript_build
+++ b/source3/modules/wscript_build
@@ -268,7 +268,7 @@ vfs_nfs4acl_xattr_source = '''
 bld.SAMBA3_MODULE('vfs_nfs4acl_xattr',
                   subsystem='vfs',
                   source=vfs_nfs4acl_xattr_source,
-                  deps='NFS4_ACLS sunacl NDR_NFS4ACL',
+                  deps='NFS4_ACLS sunacl NDR_NFS4ACL tirpc',
                   init_function='',
                   internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_nfs4acl_xattr'),
                   enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_nfs4acl_xattr'))
-- 
2.17.2


From 91f9d85946018b1e387f1f5b02459a1d0533c1b0 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 5/8] 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 25dddbdd0ca962ac515b475bfbc0d832773a34e9 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 6/8] nfs4acl_xattr: add RFC compliant NFS 4.0 and 4.1 ACL
 defintions

---
 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 09f0923a613390b51b4f76d5041037667779f7dd 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 7/8] 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 f06b3df23ef1f3550b659efef6b41e683ceaebc1 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 26 Nov 2018 16:33:04 +0100
Subject: [PATCH 8/8] WIP: nfs4acl_xattr: support for NFS 4.0 and 4.1 ACLs from
 NFS4 mount

---
 docs-xml/manpages/vfs_nfs4acl_xattr.8.xml |  34 +-
 source3/modules/nfs4acl_xattr.h           |   3 +
 source3/modules/nfs4acl_xattr_nfs.c       | 889 ++++++++++++++++++++++
 source3/modules/nfs4acl_xattr_nfs.h       |  34 +
 source3/modules/vfs_nfs4acl_xattr.c       |  25 +
 source3/modules/wscript_build             |   1 +
 6 files changed, 985 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..e1ed9e7e355
--- /dev/null
+++ b/source3/modules/nfs4acl_xattr_nfs.c
@@ -0,0 +1,889 @@
+/*
+ * 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)
+
+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_is(const char *nfs4_id)
+{
+	char *at = NULL;
+
+	at = strchr(nfs4_id, '@');
+	if (at != NULL && at[1] == '\0') {
+		return true;
+	}
+	return false;
+}
+
+static bool map_special_nfs4_to_smb4_id(const char *nfs4_id, uint32_t *smb4_id)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(nfs4_to_smb4_id_map); i++) {
+		int cmp;
+
+		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;
+
+	DBG_DEBUG("aces_size: %zd\n", 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 (id_size < string_size) {
+			DBG_ERR("Integer Overflow error\n");
+			return 0;
+		}
+
+		DBG_DEBUG("identifier[%u] size: %zd\n", i, id_size);
+		identifier_size += id_size;
+	}
+
+	DBG_DEBUG("identifier_size: %zd\n", identifier_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(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;
+
+	DBG_DEBUG("aces_size: %zd\n", 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 (id_size < string_size) {
+			DBG_ERR("Integer Overflow error\n");
+			return 0;
+		}
+
+		DBG_DEBUG("identifier[%u] size: %zd\n", i, id_size);
+		identifier_size += id_size;
+	}
+
+	DBG_DEBUG("identifier_size: %zd\n", identifier_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)
+{
+	nace->who.utf8string_val = talloc_strdup(mem_ctx, id);
+	if (nace->who.utf8string_val == NULL) {
+		DBG_ERR("talloc_memdup failed\n");
+		return false;
+	}
+	nace->who.utf8string_len = talloc_get_size(nace->who.utf8string_val) - 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;
+	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;
+		}
+		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;
+		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;
+	}
+
+	nace->who.utf8string_val = talloc_strdup(mem_ctx, name);
+	if (nace->who.utf8string_val == NULL) {
+		DBG_ERR("talloc_asprintf failed\n");
+		return false;
+	}
+	nace->who.utf8string_len = talloc_get_size(nace->who.utf8string_val) - 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) {
+			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) {
+			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_is(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;
+	}
+
+	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 0e52782075b..a69d6127168 100644
--- a/source3/modules/vfs_nfs4acl_xattr.c
+++ b/source3/modules/vfs_nfs4acl_xattr.c
@@ -35,6 +35,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
@@ -42,6 +43,7 @@
 static const struct enum_list nfs4acl_encoding[] = {
 	{NFS4ACL_ENCODING_NDR, "ndr"},
 	{NFS4ACL_ENCODING_XDR, "xdr"},
+	{NFS4ACL_ENCODING_NFS, "nfs"},
 };
 
 /*
@@ -60,6 +62,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;
@@ -228,6 +234,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;
@@ -487,6 +496,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;
@@ -526,6 +536,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;
@@ -560,6 +574,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 a14a370777f..aae6e0aa19d 100644
--- a/source3/modules/wscript_build
+++ b/source3/modules/wscript_build
@@ -259,6 +259,7 @@ vfs_nfs4acl_xattr_source = '''
                            vfs_nfs4acl_xattr.c
                            nfs4acl_xattr_ndr.c
                            nfs4acl_xattr_xdr.c
+                           nfs4acl_xattr_nfs.c
                            nfs4acl_xattr_util.c
                            '''
 
-- 
2.17.2



More information about the samba-technical mailing list