vfs_acl_common: simplify ACL logic, cleanup and talloc hierarchy
[gd/samba-autobuild/.git] / source3 / modules / vfs_acl_common.c
index 30574e0e06fcb9e146039be7287a7350721b00de..66c58e73ad50d351066a5548256aab3a117ce51b 100644 (file)
@@ -24,6 +24,7 @@
 #include "../libcli/security/security.h"
 #include "../librpc/gen_ndr/ndr_security.h"
 #include "../lib/util/bitmap.h"
+#include "passdb/lookup_sid.h"
 
 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
                        DATA_BLOB *pblob,
@@ -33,7 +34,7 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
                        vfs_handle_struct *handle,
                        files_struct *fsp,
-                       const char *name,
+                       const struct smb_filename *smb_fname,
                        DATA_BLOB *pblob);
 
 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
@@ -358,6 +359,114 @@ static NTSTATUS add_directory_inheritable_components(vfs_handle_struct *handle,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
+                                           const char *name,
+                                           SMB_STRUCT_STAT *psbuf,
+                                           struct security_descriptor **ppdesc)
+{
+       struct dom_sid owner_sid, group_sid;
+       size_t size = 0;
+       struct security_ace aces[4];
+       uint32_t access_mask = 0;
+       mode_t mode = psbuf->st_ex_mode;
+       struct security_acl *new_dacl = NULL;
+       int idx = 0;
+
+       DEBUG(10,("make_default_filesystem_acl: file %s mode = 0%o\n",
+               name, (int)mode ));
+
+       uid_to_sid(&owner_sid, psbuf->st_ex_uid);
+       gid_to_sid(&group_sid, psbuf->st_ex_gid);
+
+       /*
+        We provide up to 4 ACEs
+               - Owner
+               - Group
+               - Everyone
+               - NT System
+       */
+
+       if (mode & S_IRUSR) {
+               if (mode & S_IWUSR) {
+                       access_mask |= SEC_RIGHTS_FILE_ALL;
+               } else {
+                       access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+               }
+       }
+       if (mode & S_IWUSR) {
+               access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
+       }
+
+       init_sec_ace(&aces[idx],
+                       &owner_sid,
+                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                       access_mask,
+                       0);
+       idx++;
+
+       access_mask = 0;
+       if (mode & S_IRGRP) {
+               access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+       }
+       if (mode & S_IWGRP) {
+               /* note that delete is not granted - this matches posix behaviour */
+               access_mask |= SEC_RIGHTS_FILE_WRITE;
+       }
+       if (access_mask) {
+               init_sec_ace(&aces[idx],
+                       &group_sid,
+                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                       access_mask,
+                       0);
+               idx++;
+       }
+
+       access_mask = 0;
+       if (mode & S_IROTH) {
+               access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+       }
+       if (mode & S_IWOTH) {
+               access_mask |= SEC_RIGHTS_FILE_WRITE;
+       }
+       if (access_mask) {
+               init_sec_ace(&aces[idx],
+                       &global_sid_World,
+                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                       access_mask,
+                       0);
+               idx++;
+       }
+
+       init_sec_ace(&aces[idx],
+                       &global_sid_System,
+                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                       SEC_RIGHTS_FILE_ALL,
+                       0);
+       idx++;
+
+       new_dacl = make_sec_acl(ctx,
+                       NT4_ACL_REVISION,
+                       idx,
+                       aces);
+
+       if (!new_dacl) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *ppdesc = make_sec_desc(ctx,
+                       SECURITY_DESCRIPTOR_REVISION_1,
+                       SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
+                       &owner_sid,
+                       &group_sid,
+                       NULL,
+                       new_dacl,
+                       &size);
+       if (!*ppdesc) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
+}
+
 /*******************************************************************
  Pull a DATA_BLOB from an xattr given a pathname.
  If the hash doesn't match, or doesn't exist - return the underlying
@@ -366,7 +475,7 @@ static NTSTATUS add_directory_inheritable_components(vfs_handle_struct *handle,
 
 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                                    files_struct *fsp,
-                                   const struct smb_filename *smb_fname,
+                                   const struct smb_filename *smb_fname_in,
                                    uint32_t security_info,
                                    TALLOC_CTX *mem_ctx,
                                    struct security_descriptor **ppdesc)
@@ -380,45 +489,42 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
        uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
        uint8_t sys_acl_hash_tmp[XATTR_SD_HASH_SIZE];
        struct security_descriptor *psd = NULL;
-       struct security_descriptor *pdesc_next = NULL;
-       const char *name = NULL;
+       struct security_descriptor *psd_blob = NULL;
+       struct security_descriptor *psd_fs = NULL;
+       const struct smb_filename *smb_fname = NULL;
        bool ignore_file_system_acl = lp_parm_bool(SNUM(handle->conn),
                                                ACL_MODULE_NAME,
                                                "ignore system acls",
                                                false);
-       TALLOC_CTX *frame = talloc_stackframe();
+       char *sys_acl_blob_description = NULL;
+       DATA_BLOB sys_acl_blob = { 0 };
+       bool psd_is_from_fs = false;
 
-       if (fsp && smb_fname == NULL) {
-               name = fsp->fsp_name->base_name;
+       if (fsp && smb_fname_in == NULL) {
+               smb_fname = fsp->fsp_name;
        } else {
-               name = smb_fname->base_name;
+               smb_fname = smb_fname_in;
        }
 
-       DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
+       DEBUG(10, ("get_nt_acl_internal: name=%s\n", smb_fname->base_name));
 
-       status = get_acl_blob(frame, handle, fsp, name, &blob);
+       status = get_acl_blob(mem_ctx, handle, fsp, smb_fname, &blob);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
                        nt_errstr(status)));
-               psd = NULL;
                goto out;
        } else {
-               status = parse_acl_blob(&blob, mem_ctx, &psd,
+               status = parse_acl_blob(&blob, mem_ctx, &psd_blob,
                                        &hash_type, &xattr_version, &hash[0], &sys_acl_hash[0]);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(10, ("parse_acl_blob returned %s\n",
                                   nt_errstr(status)));
-                       psd = NULL;
+                       TALLOC_FREE(blob.data);
                        goto out;
                }
        }
 
-       /* Ensure we don't leak psd if we don't choose it.
-        *
-        * We don't allocate it onto frame as it is preferred not to
-        * steal from a talloc pool.
-        */
-       talloc_steal(frame, psd);
+       TALLOC_FREE(blob.data);
 
        /* determine which type of xattr we got */
        switch (xattr_version) {
@@ -428,10 +534,14 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                 * require confirmation of the hash.  In particular,
                 * the NTVFS file server uses version 1, but
                 * 'samba-tool ntacl' can set these as well */
+               psd = psd_blob;
+               psd_blob = NULL;
                goto out;
        case 3:
        case 4:
                if (ignore_file_system_acl) {
+                       psd = psd_blob;
+                       psd_blob = NULL;
                        goto out;
                }
 
@@ -440,9 +550,8 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
                           "mismatch (%u) for file %s\n",
                           (unsigned int)hash_type,
-                          name));
-               TALLOC_FREE(psd);
-               psd = NULL;
+                          smb_fname->base_name));
+               TALLOC_FREE(psd_blob);
                goto out;
        }
 
@@ -451,9 +560,8 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                DEBUG(10, ("get_nt_acl_internal: ACL blob hash type "
                           "(%u) unexpected for file %s\n",
                           (unsigned int)hash_type,
-                          name));
-               TALLOC_FREE(psd);
-               psd = NULL;
+                          smb_fname->base_name));
+               TALLOC_FREE(psd_blob);
                goto out;
        }
 
@@ -462,22 +570,20 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
        case 4:
        {
                int ret;
-               char *sys_acl_blob_description;
-               DATA_BLOB sys_acl_blob;
                if (fsp) {
                        /* Get the full underlying sd, then hash. */
                        ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle,
                                                               fsp,
-                                                              frame,
+                                                              mem_ctx,
                                                               &sys_acl_blob_description,
                                                               &sys_acl_blob);
                } else {
                        /* Get the full underlying sd, then hash. */
                        ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle,
-                                                                name,
-                                                                frame,
-                                                                &sys_acl_blob_description,
-                                                                &sys_acl_blob);
+                                                smb_fname->base_name,
+                                                mem_ctx,
+                                                &sys_acl_blob_description,
+                                                &sys_acl_blob);
                }
 
                /* If we fail to get the ACL blob (for some reason) then this
@@ -485,16 +591,20 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                if (ret == 0) {
                        status = hash_blob_sha256(sys_acl_blob, sys_acl_hash_tmp);
                        if (!NT_STATUS_IS_OK(status)) {
-                               TALLOC_FREE(frame);
-                               return status;
+                               goto fail;
                        }
 
+                       TALLOC_FREE(sys_acl_blob_description);
+                       TALLOC_FREE(sys_acl_blob.data);
+
                        if (memcmp(&sys_acl_hash[0], &sys_acl_hash_tmp[0], 
                                   XATTR_SD_HASH_SIZE) == 0) {
                                /* Hash matches, return blob sd. */
                                DEBUG(10, ("get_nt_acl_internal: blob hash "
                                           "matches for file %s\n",
-                                          name ));
+                                          smb_fname->base_name ));
+                               psd = psd_blob;
+                               psd_blob = NULL;
                                goto out;
                        }
                }
@@ -509,35 +619,29 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                                                          fsp,
                                                          HASH_SECURITY_INFO,
                                                          mem_ctx,
-                                                         &pdesc_next);
+                                                         &psd_fs);
                } else {
                        status = SMB_VFS_NEXT_GET_NT_ACL(handle,
                                                         smb_fname,
                                                         HASH_SECURITY_INFO,
                                                         mem_ctx,
-                                                        &pdesc_next);
+                                                        &psd_fs);
                }
 
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
                                   "returned %s\n",
-                                  name,
+                                  smb_fname->base_name,
                                   nt_errstr(status)));
-                       TALLOC_FREE(frame);
-                       return status;
+                       goto fail;
                }
 
-               /* Ensure we don't leak psd_next if we don't choose it.
-                *
-                * We don't allocate it onto frame as it is preferred not to
-                * steal from a talloc pool.
-                */
-               talloc_steal(frame, pdesc_next);
-
-               status = hash_sd_sha256(pdesc_next, hash_tmp);
+               status = hash_sd_sha256(psd_fs, hash_tmp);
                if (!NT_STATUS_IS_OK(status)) {
-                       TALLOC_FREE(psd);
-                       psd = pdesc_next;
+                       TALLOC_FREE(psd_blob);
+                       psd = psd_fs;
+                       psd_fs = NULL;
+                       psd_is_from_fs = true;
                        goto out;
                }
 
@@ -545,7 +649,9 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                        /* Hash matches, return blob sd. */
                        DEBUG(10, ("get_nt_acl_internal: blob hash "
                                   "matches for file %s\n",
-                                  name ));
+                                  smb_fname->base_name ));
+                       psd = psd_blob;
+                       psd_blob = NULL;
                        goto out;
                }
 
@@ -553,19 +659,21 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                DEBUG(10, ("get_nt_acl_internal: blob hash "
                           "does not match for file %s - returning "
                           "file system SD mapping.\n",
-                          name ));
+                          smb_fname->base_name ));
 
                if (DEBUGLEVEL >= 10) {
                        DEBUG(10,("get_nt_acl_internal: acl for blob hash for %s is:\n",
-                                 name ));
-                       NDR_PRINT_DEBUG(security_descriptor, pdesc_next);
+                                 smb_fname->base_name ));
+                       NDR_PRINT_DEBUG(security_descriptor, psd_fs);
                }
 
-               TALLOC_FREE(psd);
-               psd = pdesc_next;
+               TALLOC_FREE(psd_blob);
+               psd = psd_fs;
+               psd_fs = NULL;
+               psd_is_from_fs = true;
        }
-  out:
 
+out:
        if (psd == NULL) {
                /* Get the full underlying sd, as we failed to get the
                 * blob for the hash, or the revision/hash type wasn't
@@ -575,38 +683,27 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                                                          fsp,
                                                          security_info,
                                                          mem_ctx,
-                                                         &pdesc_next);
+                                                         &psd);
                } else {
                        status = SMB_VFS_NEXT_GET_NT_ACL(handle,
                                                         smb_fname,
                                                         security_info,
                                                         mem_ctx,
-                                                        &pdesc_next);
+                                                        &psd);
                }
 
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
                                   "returned %s\n",
-                                  name,
+                                  smb_fname->base_name,
                                   nt_errstr(status)));
-                       TALLOC_FREE(frame);
-                       return status;
+                       goto fail;
                }
 
-               /* Ensure we don't leak psd_next if we don't choose it.
-                *
-                * We don't allocate it onto frame as it is preferred not to
-                * steal from a talloc pool.
-                */
-               talloc_steal(frame, pdesc_next);
-               psd = pdesc_next;
+               psd_is_from_fs = true;
        }
 
-       if (psd != pdesc_next) {
-               /* We're returning the blob, throw
-                * away the filesystem SD. */
-               TALLOC_FREE(pdesc_next);
-       } else {
+       if (psd_is_from_fs) {
                SMB_STRUCT_STAT sbuf;
                SMB_STRUCT_STAT *psbuf = &sbuf;
                bool is_directory = false;
@@ -618,8 +715,7 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                if (fsp) {
                        status = vfs_stat_fsp(fsp);
                        if (!NT_STATUS_IS_OK(status)) {
-                               TALLOC_FREE(frame);
-                               return status;
+                               goto fail;
                        }
                        psbuf = &fsp->fsp_name->st;
                } else {
@@ -641,24 +737,23 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                         * is fully plumbed through the VFS.
                         */
                        int ret = vfs_stat_smb_basename(handle->conn,
-                                               name,
+                                               smb_fname,
                                                &sbuf);
                        if (ret == -1) {
-                               TALLOC_FREE(frame);
-                               return map_nt_error_from_unix(errno);
+                               status = map_nt_error_from_unix(errno);
+                               goto fail;
                        }
                }
                is_directory = S_ISDIR(psbuf->st_ex_mode);
 
                if (ignore_file_system_acl) {
-                       TALLOC_FREE(pdesc_next);
+                       TALLOC_FREE(psd);
                        status = make_default_filesystem_acl(mem_ctx,
-                                               name,
+                                               smb_fname->base_name,
                                                psbuf,
                                                &psd);
                        if (!NT_STATUS_IS_OK(status)) {
-                               TALLOC_FREE(frame);
-                               return status;
+                               goto fail;
                        }
                } else {
                        if (is_directory &&
@@ -666,12 +761,11 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                                                        true)) {
                                status = add_directory_inheritable_components(
                                                        handle,
-                                                       name,
+                                                       smb_fname->base_name,
                                                        psbuf,
                                                        psd);
                                if (!NT_STATUS_IS_OK(status)) {
-                                       TALLOC_FREE(frame);
-                                       return status;
+                                       goto fail;
                                }
                        }
                        /* The underlying POSIX module always sets
@@ -697,19 +791,23 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                psd->sacl = NULL;
        }
 
-       TALLOC_FREE(blob.data);
-
        if (DEBUGLEVEL >= 10) {
                DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
-                       name ));
+                       smb_fname->base_name ));
                NDR_PRINT_DEBUG(security_descriptor, psd);
        }
 
-       /* The VFS API is that the ACL is expected to be on mem_ctx */
-       *ppdesc = talloc_move(mem_ctx, &psd);
+       *ppdesc = psd;
 
-       TALLOC_FREE(frame);
        return NT_STATUS_OK;
+
+fail:
+       TALLOC_FREE(psd);
+       TALLOC_FREE(psd_blob);
+       TALLOC_FREE(psd_fs);
+       TALLOC_FREE(sys_acl_blob_description);
+       TALLOC_FREE(sys_acl_blob.data);
+       return status;
 }
 
 /*********************************************************************
@@ -744,6 +842,81 @@ static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
                                ppdesc);
 }
 
+/*********************************************************************
+ Set the underlying ACL (e.g. POSIX ACLS, POSIX owner, etc)
+*********************************************************************/
+static NTSTATUS set_underlying_acl(vfs_handle_struct *handle, files_struct *fsp,
+                                  struct security_descriptor *psd,
+                                  uint32_t security_info_sent,
+                                  bool chown_needed)
+{
+       NTSTATUS status =
+           SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               return status;
+       }
+
+       /* We got access denied here. If we're already root,
+          or we didn't need to do a chown, or the fsp isn't
+          open with WRITE_OWNER access, just return. */
+       if (get_current_uid(handle->conn) == 0 || chown_needed == false ||
+           !(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       DEBUG(10, ("fset_nt_acl_common: overriding chown on file %s "
+                  "for sid %s\n",
+                  fsp_str_dbg(fsp), sid_string_tos(psd->owner_sid)));
+
+       /* Ok, we failed to chown and we have
+          SEC_STD_WRITE_OWNER access - override. */
+       become_root();
+       status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
+       unbecome_root();
+
+       return status;
+}
+
+/*********************************************************************
+ Store a v3 security descriptor
+*********************************************************************/
+static NTSTATUS store_v3_blob(vfs_handle_struct *handle, files_struct *fsp,
+                             struct security_descriptor *psd,
+                             struct security_descriptor *pdesc_next,
+                             uint8_t hash[XATTR_SD_HASH_SIZE])
+{
+       NTSTATUS status;
+       DATA_BLOB blob;
+
+       if (DEBUGLEVEL >= 10) {
+               DEBUG(10, ("fset_nt_acl_xattr: storing xattr sd for file %s\n",
+                          fsp_str_dbg(fsp)));
+               NDR_PRINT_DEBUG(
+                   security_descriptor,
+                   discard_const_p(struct security_descriptor, psd));
+
+               if (pdesc_next != NULL) {
+                       DEBUG(10, ("fset_nt_acl_xattr: storing has in xattr sd "
+                                  "based on \n"));
+                       NDR_PRINT_DEBUG(
+                           security_descriptor,
+                           discard_const_p(struct security_descriptor,
+                                           pdesc_next));
+               } else {
+                       DEBUG(10,
+                             ("fset_nt_acl_xattr: ignoring underlying sd\n"));
+               }
+       }
+       status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("fset_nt_acl_xattr: create_acl_blob failed\n"));
+               return status;
+       }
+
+       status = store_acl_blob_fsp(handle, fsp, &blob);
+       return status;
+}
+
 /*********************************************************************
  Store a security descriptor given an fsp.
 *********************************************************************/
@@ -761,6 +934,8 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
        bool chown_needed = false;
        char *sys_acl_description;
        TALLOC_CTX *frame = talloc_stackframe();
+       bool ignore_file_system_acl = lp_parm_bool(
+           SNUM(handle->conn), ACL_MODULE_NAME, "ignore system acls", false);
 
        if (DEBUGLEVEL >= 10) {
                DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
@@ -816,38 +991,29 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
                psd->type |= SEC_DESC_SACL_PRESENT;
        }
 
-       status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
-       if (!NT_STATUS_IS_OK(status)) {
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
-                       TALLOC_FREE(frame);
-                       return status;
-               }
-               /* We got access denied here. If we're already root,
-                  or we didn't need to do a chown, or the fsp isn't
-                  open with WRITE_OWNER access, just return. */
-               if (get_current_uid(handle->conn) == 0 ||
-                               chown_needed == false ||
-                               !(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
-                       TALLOC_FREE(frame);
-                       return NT_STATUS_ACCESS_DENIED;
+       if (ignore_file_system_acl) {
+               if (chown_needed) {
+                       /* send only ownership stuff to lower layer */
+                       security_info_sent &= (SECINFO_OWNER | SECINFO_GROUP);
+                       status = set_underlying_acl(handle, fsp, psd,
+                                                   security_info_sent, true);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(frame);
+                               return status;
+                       }
                }
+               ZERO_ARRAY(hash);
+               status = store_v3_blob(handle, fsp, psd, NULL, hash);
 
-               DEBUG(10,("fset_nt_acl_common: overriding chown on file %s "
-                       "for sid %s\n",
-                       fsp_str_dbg(fsp),
-                       sid_string_tos(psd->owner_sid)
-                       ));
-
-               /* Ok, we failed to chown and we have
-                  SEC_STD_WRITE_OWNER access - override. */
-               become_root();
-               status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp,
-                               security_info_sent, psd);
-               unbecome_root();
-               if (!NT_STATUS_IS_OK(status)) {
-                       TALLOC_FREE(frame);
-                       return status;
-               }
+               TALLOC_FREE(frame);
+               return status;
+       }
+
+       status = set_underlying_acl(handle, fsp, psd, security_info_sent,
+                                   chown_needed);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return status;
        }
 
        /* Get the full underlying sd, then hash. */
@@ -878,24 +1044,7 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
        /* If we fail to get the ACL blob (for some reason) then this
         * is not fatal, we just work based on the NT ACL only */
        if (ret != 0) {
-               if (DEBUGLEVEL >= 10) {
-                       DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
-                                 fsp_str_dbg(fsp)));
-                       NDR_PRINT_DEBUG(security_descriptor,
-                                       discard_const_p(struct security_descriptor, psd));
-
-                       DEBUG(10,("fset_nt_acl_xattr: storing has in xattr sd based on \n"));
-                       NDR_PRINT_DEBUG(security_descriptor,
-                                       discard_const_p(struct security_descriptor, pdesc_next));
-               }
-               status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(10, ("fset_nt_acl_xattr: create_acl_blob failed\n"));
-                       TALLOC_FREE(frame);
-                       return status;
-               }
-
-               status = store_acl_blob_fsp(handle, fsp, &blob);
+               status = store_v3_blob(handle, fsp, psd, pdesc_next, hash);
 
                TALLOC_FREE(frame);
                return status;
@@ -1007,7 +1156,7 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
 
        become_root();
        if (is_directory) {
-               ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
+               ret = SMB_VFS_NEXT_RMDIR(handle, &local_fname);
        } else {
                ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
        }
@@ -1031,12 +1180,12 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
 }
 
 static int rmdir_acl_common(struct vfs_handle_struct *handle,
-                               const char *path)
+                               const struct smb_filename *smb_fname)
 {
        int ret;
 
        /* Try the normal rmdir first. */
-       ret = SMB_VFS_NEXT_RMDIR(handle, path);
+       ret = SMB_VFS_NEXT_RMDIR(handle, smb_fname);
        if (ret == 0) {
                return 0;
        }
@@ -1044,12 +1193,12 @@ static int rmdir_acl_common(struct vfs_handle_struct *handle,
                /* Failed due to access denied,
                   see if we need to root override. */
                return acl_common_remove_object(handle,
-                                               path,
+                                               smb_fname->base_name,
                                                true);
        }
 
        DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
-               path,
+               smb_fname->base_name,
                strerror(errno) ));
        return -1;
 }
@@ -1084,11 +1233,12 @@ static int unlink_acl_common(struct vfs_handle_struct *handle,
 }
 
 static int chmod_acl_module_common(struct vfs_handle_struct *handle,
-                       const char *path, mode_t mode)
+                       const struct smb_filename *smb_fname,
+                       mode_t mode)
 {
-       if (lp_posix_pathnames()) {
+       if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
                /* Only allow this on POSIX pathnames. */
-               return SMB_VFS_NEXT_CHMOD(handle, path, mode);
+               return SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
        }
        return 0;
 }
@@ -1104,11 +1254,12 @@ static int fchmod_acl_module_common(struct vfs_handle_struct *handle,
 }
 
 static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
-                       const char *name, mode_t mode)
+                       const struct smb_filename *smb_fname,
+                       mode_t mode)
 {
-       if (lp_posix_pathnames()) {
+       if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
                /* Only allow this on POSIX pathnames. */
-               return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode);
+               return SMB_VFS_NEXT_CHMOD_ACL(handle, smb_fname, mode);
        }
        return 0;
 }