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

Sandeep Nashikkar snashikkar at commvault.com
Fri Jul 20 12:47:16 UTC 2018


Hi All

While experimenting with NFS4ACL_XATTR VFS module I came across failures on windows clients in its current implementation.
I was testing native NFS 4.0 Server export mounted locally and shared through Samba 4.8.0 server with nfs4acl_xattr module.
Looking at XDR backend code and wireshark traces, I could see that current code is not compatible with NFS4 ACL format in RFC 7530.
I have fixed the module with following:

*         Implemented another set of XDR structure and APIs (with nfs40acl prefix) which should work with NFS 4.0 ACL format and convert XDR blob to/from SMB ACL. Enabled by default for now.

*         Did not change any of the existing XDR Backend APIs (with nfs4acl prefix) which probably intend to support both NFS 4.0 and NFS 4.1 ACL format in future using nfs_version config option. Current APIs use iflag in the nfsace4 structure which I did not find even in NFS v4.1 Spec RFC 5661. And that was causing issues in encoding/decoding XDR blobs. So the existing code is broken for my tests and needed lot of fixes if it has to support both specs.

*         Changed XDR attribute name to "system.nfs4_acl" which works with native NFSv4 and nfs-ganesha.

*         All owners with Special IDs along with OWNER@, GROUP@, EVERYONE@ are encoded/decoded now.

Please find below the patch for fixing above issues.
Kindly review the patch and please let me know if there are any suggestions/corrections.
I am not used to submit patches to open source, so let me know if there are any lapses and I would be ready to fix it.

Thanks
Sandeep Nashikkar


-------------- next part --------------
>From 556f44ca183d12a8a5a4211213362247361edff3 Mon Sep 17 00:00:00 2001
From: Sandeep Nashikkar <snashikkar at commvault.com>
Date: Fri, 20 Jul 2018 17:22:43 +0530
Subject: [PATCH] Fix for XDR Backend of NFS4ACL_XATTR module to get it working
with NFS4.0 ACL Spec

Signed-off-by: Sandeep Nashikkar <snashikkar at commvault.com>
---
source3/modules/nfs41acl.x          |  12 +
source3/modules/nfs4acl_xattr_xdr.c | 473 ++++++++++++++++++++++++++++
source3/modules/nfs4acl_xattr_xdr.h |  12 +-
source3/modules/vfs_nfs4acl_xattr.c |   6 +-
4 files changed, 499 insertions(+), 4 deletions(-)

diff --git a/source3/modules/nfs41acl.x b/source3/modules/nfs41acl.x
index 9cfbd9f3074..beea0071fef 100644
--- a/source3/modules/nfs41acl.x
+++ b/source3/modules/nfs41acl.x
@@ -92,3 +92,15 @@ struct nfsacl41 {
         aclflag4        na41_flag;
         nfsace4         na41_aces<>;
};
+
+/* ACL structure definition as per RFC 7530 Section-6.2.1 */
+struct nfsace40 {
+        acetype4        type;
+        aceflag4        flag;
+        acemask4        access_mask;
+        utf8str_mixed   who;
+};
+
+struct nfsacl40 {
+        nfsace40         na40_aces<>;
+};
diff --git a/source3/modules/nfs4acl_xattr_xdr.c b/source3/modules/nfs4acl_xattr_xdr.c
index 399c104faa4..70e562f36cb 100644
--- a/source3/modules/nfs4acl_xattr_xdr.c
+++ b/source3/modules/nfs4acl_xattr_xdr.c
@@ -40,6 +40,21 @@
#include "nfs41acl.h"
#include "nfs4acl_xattr_xdr.h"
+static unsigned nfs40acl_get_naces(nfsacl40 *nacl40)
+{
+             return nacl40->na40_aces.na40_aces_len;
+}
+
+static void nfs40acl_set_naces(nfsacl40 *nacl40, unsigned naces)
+{
+             nacl40->na40_aces.na40_aces_len = naces;
+}
+
+static nfsace40 *nfs40acl_get_ace(nfsacl40 *nacl40, size_t n)
+{
+             return &nacl40->na40_aces.na40_aces_val[n];
+}
+
static unsigned nfs4acl_get_naces(nfsacl41 *nacl)
{
               return nacl->na41_aces.na41_aces_len;
@@ -60,6 +75,61 @@ static void nfs4acl_set_flags(nfsacl41 *nacl, unsigned flags)
               nacl->na41_flag = flags;
}
+static size_t nfs40acl_get_xdrblob_size(nfsacl40 *nacl40)
+{
+             size_t acl_size;
+             size_t aces_size;
+             size_t identifiers_size;
+             int i;
+
+             unsigned naces = nfs40acl_get_naces(nacl40);
+
+             /* ACE Structure minus actual identifier strings */
+             struct nfsace40_size {
+                             acetype4 type;
+                             aceflag4 flag;
+                             acemask4 access_mask;
+                             u_int who_length;
+             };
+
+             /* ACL Size: Size of (ACE Count) +
+              * ACE Count * (Size of nfsace40_size) +
+              * Cumulative Length of Identifiers strings
+              */
+             acl_size = sizeof(u_int);
+
+             if (naces > NFS4ACL_XDR_MAX_ACES) {
+                             DBG_ERR("Too many ACEs: %u", naces);
+                             return 0;
+             }
+
+             aces_size = naces * sizeof(struct nfsace40_size);
+             acl_size += aces_size;
+             DBG_DEBUG("aces_size: %ld\n", aces_size);
+
+             identifiers_size = 0;
+             for (i = 0;  i < naces; i++) {
+                             nfsace40 *nace40 = nfs40acl_get_ace(nacl40, i);
+                             /* UTf-8 identifier strings are aligned */
+                             if (nace40->who.utf8string_len % 4) {
+                                             size_t id_size = nace40->who.utf8string_len;
+                                             id_size += (4 - (nace40->who.utf8string_len % 4));
+                                             identifiers_size += id_size;
+                                             DBG_DEBUG("identifier[%d] size: %ld\n", i, id_size);
+                             } else {
+                                             identifiers_size += (nace40->who.utf8string_len);
+                             }
+             }
+
+             DBG_DEBUG("total identifiers_size: %ld\n", identifiers_size);
+             acl_size += identifiers_size;
+
+             DBG_DEBUG("acl_size: %ld\n", acl_size);
+             return acl_size;
+}
+
+
+
static size_t nfs4acl_get_xdrblob_size(nfsacl41 *nacl)
{
               size_t acl_size;
@@ -82,6 +152,12 @@ static size_t nfs4acl_get_xdrblob_size(nfsacl41 *nacl)
               return acl_size;
}
+static size_t nfs40acl_get_xdrblob_naces(size_t _blobsize)
+{
+             /* Not required */
+             return -1;
+}
+
static size_t nfs4acl_get_xdrblob_naces(size_t _blobsize)
{
               size_t blobsize = _blobsize;
@@ -94,6 +170,31 @@ static size_t nfs4acl_get_xdrblob_naces(size_t _blobsize)
               return (blobsize / sizeof(struct nfsace4));
}
+static nfsacl40 *nfs40acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
+{
+
+             size_t acl_size = sizeof(nfsacl40) + (naces * sizeof(struct nfsace40));
+             nfsacl40 *nacl40 = NULL;
+
+             if (naces > NFS4ACL_XDR_MAX_ACES) {
+                             DBG_ERR("Too many ACEs: %d\n", naces);
+                             return NULL;
+             }
+
+             nacl40 = talloc_zero_size(mem_ctx, acl_size);
+             if (nacl40 == NULL) {
+                             DBG_ERR("talloc_zero_size failed\n");
+                             return NULL;
+             }
+
+             nfs40acl_set_naces(nacl40, naces);
+             nacl40->na40_aces.na40_aces_val =
+                             (nfsace40 *)((char *)nacl40 + sizeof(nfsacl40));
+
+             return nacl40;
+}
+
+
static nfsacl41 *nfs4acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
{
               size_t acl_size = sizeof(nfsacl41) + (naces * sizeof(struct nfsace4));
@@ -139,6 +240,151 @@ static unsigned smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags)
               return nfs4acl_flags;
}
+static bool create_special_id(TALLOC_CTX *mem_ctx, nfsace40 *nace40, char *id)
+{
+             int len = strlen(id);
+             nace40->who.utf8string_val = talloc_memdup(mem_ctx, id, len);
+             nace40->who.utf8string_len = len;
+             if (nace40->who.utf8string_val == NULL) {
+                             DBG_ERR("Error talloc_memdup for %d bytes\n", len);
+                             return false;
+             }
+             return true;
+}
+static bool create_numeric_id(TALLOC_CTX *mem_ctx, nfsace40 *nace40, uid_t id)
+{
+             int id_len = snprintf( NULL, 0, "%ld", id);
+             char* strid = malloc(id_len + 1);
+             if (!strid) {
+                             DBG_ERR("Error allocating %d bytes\n", id_len + 1);
+                             return false;
+             }
+             snprintf(strid, id_len + 1, "%ld", id);
+             nace40->who.utf8string_val = talloc_memdup (mem_ctx, strid, id_len);
+             nace40->who.utf8string_len = id_len;
+             free(strid);
+             if (nace40->who.utf8string_val == NULL) {
+                             DBG_ERR("Error talloc_memdup for %d bytes\n", id_len);
+                             return false;
+             }
+             return true;
+}
+
+static bool smb4acl_to_nfs40acl(vfs_handle_struct *handle,
+                                                    TALLOC_CTX *mem_ctx,
+                                                    struct SMB4ACL_T *smb4acl,
+                                                    nfsacl40 **_nacl40)
+{
+             struct nfs4acl_config *config = NULL;
+             struct SMB4ACE_T *smb4ace = NULL;
+             size_t smb4naces = 0;
+             nfsacl40 *nacl40 = NULL;
+             uint16_t smb4acl_flags = 0;
+             unsigned nacl_flags = 0;
+
+             SMB_VFS_HANDLE_GET_DATA(handle, config,
+                                                             struct nfs4acl_config,
+                                                             return false);
+
+             smb4naces = smb_get_naces(smb4acl);
+             nacl40 = nfs40acl_alloc(mem_ctx, smb4naces);
+             nfs40acl_set_naces(nacl40, 0);
+
+             smb4ace = smb_first_ace4(smb4acl);
+             while (smb4ace != NULL) {
+                             SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
+                             size_t nace_count = nfs40acl_get_naces(nacl40);
+                             nfsace40 *nace40 = nfs40acl_get_ace(nacl40, nace_count);
+
+                             nace40->type = ace4prop->aceType;
+                             nace40->flag = ace4prop->aceFlags;
+                             nace40->access_mask = ace4prop->aceMask;
+
+                             if (ace4prop->flags & SMB_ACE4_ID_SPECIAL) {
+                                             switch (ace4prop->who.special_id) {
+                                             case SMB_ACE4_WHO_OWNER:
+                                                             if (!create_special_id(mem_ctx, nace40, "OWNER@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+                                             case SMB_ACE4_WHO_GROUP:
+                                                             if (!create_special_id(mem_ctx, nace40, "GROUP@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+
+                                             case SMB_ACE4_WHO_EVERYONE:
+                                                             if (!create_special_id(mem_ctx, nace40, "EVERYONE@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+                                             case SMB_ACE4_WHO_INTERACTIVE:
+                                                             if (!create_special_id(mem_ctx, nace40, "INTERACTIVE@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+                                             case SMB_ACE4_WHO_NETWORK:
+                                                             if (!create_special_id(mem_ctx, nace40, "NETWORK@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+                                             case SMB_ACE4_WHO_DIALUP:
+                                                             if (!create_special_id(mem_ctx, nace40, "DIALUP@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+                                             case SMB_ACE4_WHO_BATCH:
+                                                             if (!create_special_id(mem_ctx, nace40, "BATCH@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+                                             case SMB_ACE4_WHO_ANONYMOUS:
+                                                             if (!create_special_id(mem_ctx, nace40, "ANONYMOUS@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+                                             case SMB_ACE4_WHO_AUTHENTICATED:
+                                                             if (!create_special_id(mem_ctx, nace40, "AUTHENTICATED@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+                                             case SMB_ACE4_WHO_SERVICE:
+                                                             if (!create_special_id(mem_ctx, nace40, "SERVICE@")) {
+                                                                             return false;
+                                                             }
+                                                             break;
+
+                                             default:
+                                                             DBG_ERR("Unsupported special id [%d]\n",
+                                                                             ace4prop->who.special_id);
+                                                             continue;
+                                             }
+                                             DBG_DEBUG("nace40->who special [%s]\n", nace40->who.utf8string_val);
+                             } else {
+                                             if (ace4prop->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
+                                                             nace40->flag |= ACE4_IDENTIFIER_GROUP;
+                                                             if (!create_numeric_id(mem_ctx, nace40, ace4prop->who.gid)) {
+                                                                             return false;
+                                                             }
+                                                             DBG_DEBUG("nace40->who gid [%s]\n", nace40->who.utf8string_val);
+                                             } else {
+                                                             if (!create_numeric_id(mem_ctx, nace40, ace4prop->who.uid)) {
+                                                                             return false;
+                                                             }
+                                                             DBG_DEBUG("nace40->who uid [%s]\n", nace40->who.utf8string_val);
+                                             }
+                             }
+
+                             nace_count++;
+                             nfs40acl_set_naces(nacl40, nace_count);
+                             smb4ace = smb_next_ace4(smb4ace);
+             }
+
+             *_nacl40 = nacl40;
+             return true;
+}
+
+
static bool smb4acl_to_nfs4acl(vfs_handle_struct *handle,
                                                      TALLOC_CTX *mem_ctx,
                                                      struct SMB4ACL_T *smb4acl,
@@ -214,6 +460,49 @@ static bool smb4acl_to_nfs4acl(vfs_handle_struct *handle,
               return true;
}
+NTSTATUS nfs40acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
+                                                                  TALLOC_CTX *mem_ctx,
+                                                                  struct SMB4ACL_T *smb4acl,
+                                                                  DATA_BLOB *_blob)
+{
+             nfsacl40 *nacl40 = NULL;
+             XDR xdr = {0};
+             size_t aclblobsize;
+             DATA_BLOB blob;
+             bool ok;
+
+             ok = smb4acl_to_nfs40acl(handle, talloc_tos(), 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) {
+                             return NT_STATUS_INTERNAL_ERROR;
+             }
+
+             blob = data_blob_talloc(mem_ctx, NULL, aclblobsize);
+             if (blob.data == NULL) {
+                             TALLOC_FREE(nacl40);
+                             return NT_STATUS_NO_MEMORY;
+             }
+             DBG_DEBUG("blob 0x%x size %ld\n", blob.data, blob.length);
+
+             xdrmem_create(&xdr, (char *)blob.data, blob.length, XDR_ENCODE);
+
+             ok = xdr_nfsacl40(&xdr, nacl40);
+             TALLOC_FREE(nacl40);
+             if (!ok) {
+                             DBG_ERR("xdr_nfs4acl40 failed\n");
+                             return NT_STATUS_NO_MEMORY;
+             }
+
+             *_blob = blob;
+             return NT_STATUS_OK;
+}
+
+
NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
                                                                    TALLOC_CTX *mem_ctx,
                                                                    struct SMB4ACL_T *smb4acl,
@@ -272,6 +561,44 @@ static uint16_t nfs4acl_to_smb4acl_flags(unsigned nfsacl41_flags)
               return smb4acl_flags;
}
+static NTSTATUS nfs40acl_xdr_blob_to_nfs40acl(struct vfs_handle_struct *handle,
+                                                                                 TALLOC_CTX *mem_ctx,
+                                                                                 DATA_BLOB *blob,
+                                                                                 nfsacl40 **_nacl40)
+{
+             struct nfs4acl_config *config = NULL;
+             nfsacl40* nacl40;
+             size_t naces;
+             XDR xdr = {0};
+             bool ok;
+
+             SMB_VFS_HANDLE_GET_DATA(handle, config,
+                                                             struct nfs4acl_config,
+                                                             return NT_STATUS_INTERNAL_ERROR);
+
+             nacl40 = talloc_zero_size(mem_ctx, sizeof(nfsacl40));
+             if (nacl40 == NULL) {
+                             DBG_ERR("talloc_zero_size failed\n");
+                             return NT_STATUS_NO_MEMORY;
+             }
+
+             xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
+
+             /* XDR allocates the required memory */
+             ok = xdr_nfsacl40(&xdr, nacl40);
+             if (!ok) {
+                             DBG_ERR("xdr_nfsacl40 failed\n");
+                             return NT_STATUS_INTERNAL_ERROR;
+             }
+
+             /* naces is obtained by XDR decode */
+             naces = nacl40->na40_aces.na40_aces_len;
+             DBG_DEBUG("naces = %d \n", naces);
+
+             *_nacl40 = nacl40;
+             return NT_STATUS_OK;
+}
+
static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle,
                                                                                   TALLOC_CTX *mem_ctx,
                                                                                   DATA_BLOB *blob,
@@ -306,6 +633,121 @@ static NTSTATUS nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct *handle,
               return NT_STATUS_OK;
}
+static NTSTATUS nfs40acl_to_smb4acl(struct vfs_handle_struct *handle,
+                                                                TALLOC_CTX *mem_ctx,
+                                                                nfsacl40 *nacl40,
+                                                                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 = nfs40acl_get_naces(nacl40);
+             int i;
+
+             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("flags [%x] nace [%u]\n", smb4acl_flags, naces);
+
+             for (i = 0; i < naces; i++) {
+                             nfsace40 *nace40 = nfs40acl_get_ace(nacl40, i);
+                             SMB_ACE4PROP_T smbace = { 0 };
+
+                             DBG_DEBUG("type [%d] flag [%x] mask [%x] who [%s]\n",
+                                               nace40->type, nace40->flag,
+                                               nace40->access_mask, nace40->who.utf8string_val);
+
+                             smbace.aceType = nace40->type;
+                             smbace.aceFlags = nace40->flag;
+                             smbace.aceMask = nace40->access_mask;
+
+                             if (0 == strncmp(nace40->who.utf8string_val, "OWNER@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("OWNER@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_OWNER;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "GROUP@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("GROUP@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_GROUP;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "EVERYONE@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("EVERYONE@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_EVERYONE;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "INTERACTIVE@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("INTERACTIVE@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_INTERACTIVE;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "NETWORK@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("NETWORK@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_NETWORK;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "DIALUP@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("DIALUP@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_DIALUP;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "BATCH@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("BATCH@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_BATCH;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "ANONYMOUS@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("ANONYMOUS@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_ANONYMOUS;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "AUTHENTICATED@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("AUTHENTICATED@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_AUTHENTICATED;
+                             } else if (0 == strncmp(nace40->who.utf8string_val, "SERVICE@", nace40->who.utf8string_len)) {
+                                             DBG_DEBUG("SERVICE@\n");
+                                             smbace.flags |= SMB_ACE4_ID_SPECIAL;
+                                             smbace.who.special_id = SMB_ACE4_WHO_SERVICE;
+
+                             } else {
+
+                                             if (nace40->flag & ACE4_IDENTIFIER_GROUP) {
+                                                             char *id = calloc(1, nace40->who.utf8string_len + 1);
+                                                             memcpy(id, nace40->who.utf8string_val, nace40->who.utf8string_len);
+                                                             char *endptr = NULL;
+                                                             smbace.who.gid = strtoul(id, &endptr, 10);
+                                                             if (endptr >= nace40->who.utf8string_val && endptr < nace40->who.utf8string_val + nace40->who.utf8string_len) {
+                                                                             DBG_ERR("Error converting gid [%s] to numeric gid, utf8string [%p] endptr: [%p] skipping %d %d\n",
+                                                                                             id, nace40->who.utf8string_val, endptr, endptr - nace40->who.utf8string_val, nace40->who.utf8string_len);
+                                                                             free(id);
+                                                                             continue;
+                                                             } else {
+                                                                             DBG_DEBUG("gid %ld\n", smbace.who.gid);
+                                                                             free(id);
+                                                             }
+                                             } else {
+                                                             char *id = calloc(1, nace40->who.utf8string_len + 1);
+                                                             memcpy(id, nace40->who.utf8string_val, nace40->who.utf8string_len);
+                                                             char *endptr = NULL;
+                                                             smbace.who.uid = strtoul(id, &endptr, 10);
+                                                             if (endptr >= nace40->who.utf8string_val && endptr < nace40->who.utf8string_val + nace40->who.utf8string_len) {
+                                                                             DBG_ERR("Error converting uid [%s] to numeric uid, utf8string [%p] endptr: [%p] skipping\n",
+                                                                                             id, nace40->who.utf8string_val, endptr);
+                                                                             free(id);
+                                                                             continue;
+                                                             } else {
+                                                                             DBG_DEBUG("uid %ld\n", smbace.who.uid);
+                                                                             free(id);
+                                                             }
+                                             }
+                             }
+                             smb_add_ace4(smb4acl, &smbace);
+             }
+
+             *_smb4acl = smb4acl;
+             return NT_STATUS_OK;
+}
+
static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle,
                                                                  TALLOC_CTX *mem_ctx,
                                                                  nfsacl41 *nacl,
@@ -382,6 +824,37 @@ static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle,
               return NT_STATUS_OK;
}
+NTSTATUS nfs40acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
+                                                               TALLOC_CTX *mem_ctx,
+                                                               DATA_BLOB *blob,
+                                                               struct SMB4ACL_T **_smb4acl)
+{
+             struct nfs4acl_config *config = NULL;
+             nfsacl40 *nacl40 = NULL;
+             struct SMB4ACL_T *smb4acl = NULL;
+             NTSTATUS status;
+
+             DBG_DEBUG("entered\n");
+
+             SMB_VFS_HANDLE_GET_DATA(handle, config,
+                                                             struct nfs4acl_config,
+                                                             return NT_STATUS_INTERNAL_ERROR);
+
+             status = nfs40acl_xdr_blob_to_nfs40acl(handle, talloc_tos(), blob, &nacl40);
+             if (!NT_STATUS_IS_OK(status)) {
+                             return status;
+             }
+
+             status = nfs40acl_to_smb4acl(handle, mem_ctx, nacl40, &smb4acl);
+             TALLOC_FREE(nacl40);
+             if (!NT_STATUS_IS_OK(status)) {
+                             return status;
+             }
+
+             *_smb4acl = smb4acl;
+             return NT_STATUS_OK;
+}
+
NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
                                                                 TALLOC_CTX *mem_ctx,
                                                                 DATA_BLOB *blob,
diff --git a/source3/modules/nfs4acl_xattr_xdr.h b/source3/modules/nfs4acl_xattr_xdr.h
index 8a544349cc8..67d60706335 100644
--- a/source3/modules/nfs4acl_xattr_xdr.h
+++ b/source3/modules/nfs4acl_xattr_xdr.h
@@ -19,7 +19,7 @@
#ifndef __NFS4ACL_XATTR_XDR_H__
#define __NFS4ACL_XATTR_XDR_H__
-#define NFS4ACL_XDR_XATTR_NAME "security.nfs4acl_xdr"
+#define NFS4ACL_XDR_XATTR_NAME "system.nfs4_acl"
#define NFS4ACL_XDR_MAX_ACES 8192
 NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
@@ -32,4 +32,14 @@ NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
                                                                    struct SMB4ACL_T *smbacl,
                                                                    DATA_BLOB *blob);
+NTSTATUS nfs40acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
+                                                               TALLOC_CTX *mem_ctx,
+                                                               DATA_BLOB *blob,
+                                                               struct SMB4ACL_T **_smb4acl);
+
+NTSTATUS nfs40acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
+                                                                  TALLOC_CTX *mem_ctx,
+                                                                  struct SMB4ACL_T *smbacl,
+                                                                  DATA_BLOB *blob);
+
#endif /* __NFS4ACL_XATTR_XDR_H__ */
diff --git a/source3/modules/vfs_nfs4acl_xattr.c b/source3/modules/vfs_nfs4acl_xattr.c
index 0e52782075b..1b0e9cfe327 100644
--- a/source3/modules/vfs_nfs4acl_xattr.c
+++ b/source3/modules/vfs_nfs4acl_xattr.c
@@ -226,7 +226,7 @@ static NTSTATUS nfs4acl_blob_to_smb4(struct vfs_handle_struct *handle,
                               status = nfs4acl_ndr_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
                               break;
               case NFS4ACL_ENCODING_XDR:
-                              status = nfs4acl_xdr_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
+                             status = nfs40acl_xdr_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
                               break;
               default:
                               status = NT_STATUS_INTERNAL_ERROR;
@@ -325,7 +325,7 @@ static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle,
                                                                                                    smb4acl, &blob);
                               break;
               case NFS4ACL_ENCODING_XDR:
-                              status = nfs4acl_smb4acl_to_xdr_blob(handle, talloc_tos(),
+                             status = nfs40acl_smb4acl_to_xdr_blob(handle, talloc_tos(),
                                                                                                    smb4acl, &blob);
                               break;
               default:
@@ -535,7 +535,7 @@ static int nfs4acl_connect(struct vfs_handle_struct *handle,
               nfs_version = (unsigned)lp_parm_int(SNUM(handle->conn),
                                                                                   "nfs4acl_xattr",
                                                                                   "version",
-                                                                                  41);
+                                                                                 40);
               switch (nfs_version) {
               case 40:
                               config->nfs_version = ACL4_XATTR_VERSION_40;
--
2.18.0.windows.1

***************************Legal Disclaimer***************************
"This communication may contain confidential and privileged material for the
sole use of the intended recipient. Any unauthorized review, use or distribution
by others is strictly prohibited. If you have received the message by mistake,
please advise the sender by reply email and delete the message. Thank you."
**********************************************************************


More information about the samba-technical mailing list