s3:smbd: Fix typo in got_duplicate_group check
[samba.git] / source3 / smbd / posix_acls.c
index f07f72ebb72ee20d22e8553c0a73a16374a82a69..d46a16dbc13e1a06ae00958a37bb7e1323fdbb76 100644 (file)
@@ -27,6 +27,7 @@
 #include "passdb/lookup_sid.h"
 #include "auth.h"
 #include "../librpc/gen_ndr/idmap.h"
+#include "../librpc/gen_ndr/ndr_smb_acl.h"
 #include "lib/param/loadparm.h"
 
 extern const struct generic_mapping file_generic_mapping;
@@ -855,13 +856,13 @@ static void print_canon_ace_list(const char *name, canon_ace *ace_list)
  Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
 ****************************************************************************/
 
-static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET_T permset)
+static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset)
 {
        mode_t ret = 0;
 
-       ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0);
-       ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0);
-       ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);
+       ret |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRUSR : 0);
+       ret |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWUSR : 0);
+       ret |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);
 
        return ret;
 }
@@ -891,18 +892,18 @@ static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x
 
 static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset)
 {
-       if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) ==  -1)
+       if (sys_acl_clear_perms(*p_permset) ==  -1)
                return -1;
        if (mode & S_IRUSR) {
-               if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1)
+               if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1)
                        return -1;
        }
        if (mode & S_IWUSR) {
-               if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1)
+               if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1)
                        return -1;
        }
        if (mode & S_IXUSR) {
-               if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1)
+               if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1)
                        return -1;
        }
        return 0;
@@ -919,7 +920,7 @@ void create_file_sids(const SMB_STRUCT_STAT *psbuf, struct dom_sid *powner_sid,
 }
 
 /****************************************************************************
- Merge aces with a common sid - if both are allow or deny, OR the permissions together and
+ Merge aces with a common UID or GID - if both are allow or deny, OR the permissions together and
  delete the second one. If the first is deny, mask the permissions off and delete the allow
  if the permissions become zero, delete the deny if the permissions are non zero.
 ****************************************************************************/
@@ -955,11 +956,11 @@ static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
                         */
 
                        if (!dir_acl) {
-                               can_merge = (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+                               can_merge = (curr_ace->unix_ug.id == curr_ace_outer->unix_ug.id &&
                                             curr_ace->owner_type == curr_ace_outer->owner_type &&
                                             (curr_ace->attr == curr_ace_outer->attr));
                        } else {
-                               can_merge = (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+                               can_merge = (curr_ace->unix_ug.id == curr_ace_outer->unix_ug.id &&
                                             curr_ace->owner_type == curr_ace_outer->owner_type &&
                                             (curr_ace->type == curr_ace_outer->type) &&
                                             (curr_ace->attr == curr_ace_outer->attr));
@@ -1009,7 +1010,7 @@ static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
                         * we've put on the ACL, we know the deny must be the first one.
                         */
 
-                       if (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+                       if (curr_ace->unix_ug.id == curr_ace_outer->unix_ug.id &&
                            (curr_ace->owner_type == curr_ace_outer->owner_type) &&
                            (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
 
@@ -1270,11 +1271,11 @@ static void apply_default_perms(const struct share_params *params,
        /* Get the initial bits to apply. */
 
        if (is_directory) {
-               and_bits = lp_dir_security_mask(params->service);
-               or_bits = lp_force_dir_security_mode(params->service);
+               and_bits = lp_dir_mask(params->service);
+               or_bits = lp_force_dir_mode(params->service);
        } else {
-               and_bits = lp_security_mask(params->service);
-               or_bits = lp_force_security_mode(params->service);
+               and_bits = lp_create_mask(params->service);
+               or_bits = lp_force_create_mode(params->service);
        }
 
        /* Now bounce them into the S_USR space. */     
@@ -1342,33 +1343,119 @@ static bool uid_entry_in_group(connection_struct *conn, canon_ace *uid_ace, cano
 }
 
 /****************************************************************************
- A well formed POSIX file or default ACL has at least 3 entries, a 
+ A well formed POSIX file or default ACL has at least 3 entries, a
  SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ.
  In addition, the owner must always have at least read access.
  When using this call on get_acl, the pst struct is valid and contains
- the mode of the file. When using this call on set_acl, the pst struct has
+ the mode of the file.
+****************************************************************************/
+
+static bool ensure_canon_entry_valid_on_get(connection_struct *conn,
+                                       canon_ace **pp_ace,
+                                       const struct dom_sid *pfile_owner_sid,
+                                       const struct dom_sid *pfile_grp_sid,
+                                       const SMB_STRUCT_STAT *pst)
+{
+       canon_ace *pace;
+       bool got_user = false;
+       bool got_group = false;
+       bool got_other = false;
+
+       for (pace = *pp_ace; pace; pace = pace->next) {
+               if (pace->type == SMB_ACL_USER_OBJ) {
+                       got_user = true;
+               } else if (pace->type == SMB_ACL_GROUP_OBJ) {
+                       got_group = true;
+               } else if (pace->type == SMB_ACL_OTHER) {
+                       got_other = true;
+               }
+       }
+
+       if (!got_user) {
+               if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
+                       DEBUG(0,("malloc fail.\n"));
+                       return false;
+               }
+
+               ZERO_STRUCTP(pace);
+               pace->type = SMB_ACL_USER_OBJ;
+               pace->owner_type = UID_ACE;
+               pace->unix_ug.type = ID_TYPE_UID;
+               pace->unix_ug.id = pst->st_ex_uid;
+               pace->trustee = *pfile_owner_sid;
+               pace->attr = ALLOW_ACE;
+               pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRUSR, S_IWUSR, S_IXUSR);
+               DLIST_ADD(*pp_ace, pace);
+       }
+
+       if (!got_group) {
+               if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
+                       DEBUG(0,("malloc fail.\n"));
+                       return false;
+               }
+
+               ZERO_STRUCTP(pace);
+               pace->type = SMB_ACL_GROUP_OBJ;
+               pace->owner_type = GID_ACE;
+               pace->unix_ug.type = ID_TYPE_GID;
+               pace->unix_ug.id = pst->st_ex_gid;
+               pace->trustee = *pfile_grp_sid;
+               pace->attr = ALLOW_ACE;
+               pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRGRP, S_IWGRP, S_IXGRP);
+               DLIST_ADD(*pp_ace, pace);
+       }
+
+       if (!got_other) {
+               if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
+                       DEBUG(0,("malloc fail.\n"));
+                       return false;
+               }
+
+               ZERO_STRUCTP(pace);
+               pace->type = SMB_ACL_OTHER;
+               pace->owner_type = WORLD_ACE;
+               pace->unix_ug.type = ID_TYPE_NOT_SPECIFIED;
+               pace->unix_ug.id = -1;
+               pace->trustee = global_sid_World;
+               pace->attr = ALLOW_ACE;
+               pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IROTH, S_IWOTH, S_IXOTH);
+               DLIST_ADD(*pp_ace, pace);
+       }
+
+       return true;
+}
+
+/****************************************************************************
+ A well formed POSIX file or default ACL has at least 3 entries, a
+ SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ.
+ In addition, the owner must always have at least read access.
+ When using this call on set_acl, the pst struct has
  been modified to have a mode containing the default for this file or directory
  type.
 ****************************************************************************/
 
-static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace,
-                                    const struct share_params *params,
-                                    const bool is_directory,
-                                                       const struct dom_sid *pfile_owner_sid,
-                                                       const struct dom_sid *pfile_grp_sid,
-                                                       const SMB_STRUCT_STAT *pst,
-                                                       bool setting_acl)
+static bool ensure_canon_entry_valid_on_set(connection_struct *conn,
+                                       canon_ace **pp_ace,
+                                       bool is_default_acl,
+                                       const struct share_params *params,
+                                       const bool is_directory,
+                                       const struct dom_sid *pfile_owner_sid,
+                                       const struct dom_sid *pfile_grp_sid,
+                                       const SMB_STRUCT_STAT *pst)
 {
        canon_ace *pace;
        canon_ace *pace_user = NULL;
        canon_ace *pace_group = NULL;
        canon_ace *pace_other = NULL;
+       bool got_duplicate_user = false;
+       bool got_duplicate_group = false;
 
        for (pace = *pp_ace; pace; pace = pace->next) {
                if (pace->type == SMB_ACL_USER_OBJ) {
 
-                       if (setting_acl)
+                       if (!is_default_acl) {
                                apply_default_perms(params, is_directory, pace, S_IRUSR);
+                       }
                        pace_user = pace;
 
                } else if (pace->type == SMB_ACL_GROUP_OBJ) {
@@ -1377,8 +1464,9 @@ static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace
                         * Ensure create mask/force create mode is respected on set.
                         */
 
-                       if (setting_acl)
+                       if (!is_default_acl) {
                                apply_default_perms(params, is_directory, pace, S_IRGRP);
+                       }
                        pace_group = pace;
 
                } else if (pace->type == SMB_ACL_OTHER) {
@@ -1387,16 +1475,29 @@ static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace
                         * Ensure create mask/force create mode is respected on set.
                         */
 
-                       if (setting_acl)
+                       if (!is_default_acl) {
                                apply_default_perms(params, is_directory, pace, S_IROTH);
+                       }
                        pace_other = pace;
+
+               } else if (pace->type == SMB_ACL_USER || pace->type == SMB_ACL_GROUP) {
+
+                       /*
+                        * Ensure create mask/force create mode is respected on set.
+                        */
+
+                       if (!is_default_acl) {
+                               apply_default_perms(params, is_directory, pace, S_IRGRP);
+                       }
                }
        }
 
        if (!pace_user) {
+               canon_ace *pace_iter;
+
                if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
-                       DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
-                       return False;
+                       DEBUG(0,("talloc fail.\n"));
+                       return false;
                }
 
                ZERO_STRUCTP(pace);
@@ -1406,40 +1507,37 @@ static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace
                pace->unix_ug.id = pst->st_ex_uid;
                pace->trustee = *pfile_owner_sid;
                pace->attr = ALLOW_ACE;
-               /* Start with existing permissions, principle of least
+               /* Start with existing user permissions, principle of least
                   surprises for the user. */
-               pace->perms = pst->st_ex_mode;
+               pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRUSR, S_IWUSR, S_IXUSR);
 
-               if (setting_acl) {
-                       /* See if the owning user is in any of the other groups in
-                          the ACE, or if there's a matching user entry (by uid
-                          or in the case of ID_TYPE_BOTH by SID).
-                          If so, OR in the permissions from that entry. */
+               /* See if the owning user is in any of the other groups in
+                  the ACE, or if there's a matching user entry (by uid
+                  or in the case of ID_TYPE_BOTH by SID).
+                  If so, OR in the permissions from that entry. */
 
-                       canon_ace *pace_iter;
 
-                       for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {
-                               if (pace_iter->type == SMB_ACL_USER &&
-                                               pace_iter->unix_ug.id == pace->unix_ug.id) {
+               for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {
+                       if (pace_iter->type == SMB_ACL_USER &&
+                                       pace_iter->unix_ug.id == pace->unix_ug.id) {
+                               pace->perms |= pace_iter->perms;
+                       } else if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) {
+                               if (dom_sid_equal(&pace->trustee, &pace_iter->trustee)) {
+                                       pace->perms |= pace_iter->perms;
+                               } else if (uid_entry_in_group(conn, pace, pace_iter)) {
                                        pace->perms |= pace_iter->perms;
-                               } else if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) {
-                                       if (dom_sid_equal(&pace->trustee, &pace_iter->trustee)) {
-                                               pace->perms |= pace_iter->perms;
-                                       } else if (uid_entry_in_group(conn, pace, pace_iter)) {
-                                               pace->perms |= pace_iter->perms;
-                                       }
                                }
                        }
+               }
 
-                       if (pace->perms == 0) {
-                               /* If we only got an "everyone" perm, just use that. */
-                               if (pace_other)
-                                       pace->perms = pace_other->perms;
-                       }
+               if (pace->perms == 0) {
+                       /* If we only got an "everyone" perm, just use that. */
+                       if (pace_other)
+                               pace->perms = pace_other->perms;
+               }
 
+               if (!is_default_acl) {
                        apply_default_perms(params, is_directory, pace, S_IRUSR);
-               } else {
-                       pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRUSR, S_IWUSR, S_IXUSR);
                }
 
                DLIST_ADD(*pp_ace, pace);
@@ -1448,8 +1546,8 @@ static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace
 
        if (!pace_group) {
                if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
-                       DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
-                       return False;
+                       DEBUG(0,("talloc fail.\n"));
+                       return false;
                }
 
                ZERO_STRUCTP(pace);
@@ -1459,15 +1557,15 @@ static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace
                pace->unix_ug.id = pst->st_ex_gid;
                pace->trustee = *pfile_grp_sid;
                pace->attr = ALLOW_ACE;
-               if (setting_acl) {
-                       /* If we only got an "everyone" perm, just use that. */
-                       if (pace_other)
-                               pace->perms = pace_other->perms;
-                       else
-                               pace->perms = 0;
-                       apply_default_perms(params, is_directory, pace, S_IRGRP);
+
+               /* If we only got an "everyone" perm, just use that. */
+               if (pace_other) {
+                       pace->perms = pace_other->perms;
                } else {
-                       pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRGRP, S_IWGRP, S_IXGRP);
+                       pace->perms = 0;
+               }
+               if (!is_default_acl) {
+                       apply_default_perms(params, is_directory, pace, S_IRGRP);
                }
 
                DLIST_ADD(*pp_ace, pace);
@@ -1476,8 +1574,8 @@ static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace
 
        if (!pace_other) {
                if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
-                       DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
-                       return False;
+                       DEBUG(0,("talloc fail.\n"));
+                       return false;
                }
 
                ZERO_STRUCTP(pace);
@@ -1487,124 +1585,118 @@ static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace
                pace->unix_ug.id = -1;
                pace->trustee = global_sid_World;
                pace->attr = ALLOW_ACE;
-               if (setting_acl) {
-                       pace->perms = 0;
+               pace->perms = 0;
+               if (!is_default_acl) {
                        apply_default_perms(params, is_directory, pace, S_IROTH);
-               } else
-                       pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IROTH, S_IWOTH, S_IXOTH);
+               }
 
                DLIST_ADD(*pp_ace, pace);
                pace_other = pace;
        }
 
-       if (setting_acl) {
-               /* Ensure when setting a POSIX ACL, that the uid for a
-                  SMB_ACL_USER_OBJ ACE (the owner ACE entry) has a duplicate
-                  permission entry as an SMB_ACL_USER, and a gid for a
-                  SMB_ACL_GROUP_OBJ ACE (the primary group ACE entry) also has
-                  a duplicate permission entry as an SMB_ACL_GROUP. If not,
-                  then if the ownership or group ownership of this file or
-                  directory gets changed, the user or group can lose their
-                  access. */
-               bool got_duplicate_user = false;
-               bool got_duplicate_group = false;
-
-               for (pace = *pp_ace; pace; pace = pace->next) {
-                       if (pace->type == SMB_ACL_USER &&
-                                       pace->unix_ug.id == pace_user->unix_ug.id) {
-                               /* Already got one. */
-                               got_duplicate_user = true;
-                       } else if (pace->type == SMB_ACL_GROUP &&
-                                       pace->unix_ug.id == pace_user->unix_ug.id) {
-                               /* Already got one. */
-                               got_duplicate_group = true;
-                       } else if ((pace->type == SMB_ACL_GROUP)
-                                  && (dom_sid_equal(&pace->trustee, &pace_user->trustee))) {
-                               /* If the SID owning the file appears
-                                * in a group entry, then we have
-                                * enough duplication, they will still
-                                * have access */
-                               got_duplicate_user = true;
-                       }
-               }
-
-               /* If the SID is equal for the user and group that we need
-                  to add the duplicate for, add only the group */
-               if (!got_duplicate_user && !got_duplicate_group
-                               && dom_sid_equal(&pace_group->trustee,
-                                               &pace_user->trustee)) {
-                       /* Add a duplicate SMB_ACL_GROUP entry, this
-                        * will cover the owning SID as well, as it
-                        * will always be mapped to both a uid and
-                        * gid. */
-
-                       if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
-                               DEBUG(0,("ensure_canon_entry_valid: talloc fail.\n"));
-                               return false;
-                       }
-
-                       ZERO_STRUCTP(pace);
-                       pace->type = SMB_ACL_GROUP;;
-                       pace->owner_type = GID_ACE;
-                       pace->unix_ug.type = ID_TYPE_GID;
-                       pace->unix_ug.id = pace_group->unix_ug.id;
-                       pace->trustee = pace_group->trustee;
-                       pace->attr = pace_group->attr;
-                       pace->perms = pace_group->perms;
+       /* Ensure when setting a POSIX ACL, that the uid for a
+          SMB_ACL_USER_OBJ ACE (the owner ACE entry) has a duplicate
+          permission entry as an SMB_ACL_USER, and a gid for a
+          SMB_ACL_GROUP_OBJ ACE (the primary group ACE entry) also has
+          a duplicate permission entry as an SMB_ACL_GROUP. If not,
+          then if the ownership or group ownership of this file or
+          directory gets changed, the user or group can lose their
+          access. */
 
-                       DLIST_ADD(*pp_ace, pace);
-
-                       /* We're done here, make sure the
-                          statements below are not executed. */
+       for (pace = *pp_ace; pace; pace = pace->next) {
+               if (pace->type == SMB_ACL_USER &&
+                               pace->unix_ug.id == pace_user->unix_ug.id) {
+                       /* Already got one. */
                        got_duplicate_user = true;
+               } else if (pace->type == SMB_ACL_GROUP &&
+                               pace->unix_ug.id == pace_group->unix_ug.id) {
+                       /* Already got one. */
                        got_duplicate_group = true;
+               } else if ((pace->type == SMB_ACL_GROUP)
+                          && (dom_sid_equal(&pace->trustee, &pace_user->trustee))) {
+                       /* If the SID owning the file appears
+                        * in a group entry, then we have
+                        * enough duplication, they will still
+                        * have access */
+                       got_duplicate_user = true;
                }
+       }
 
-               if (!got_duplicate_user) {
-                       /* Add a duplicate SMB_ACL_USER entry. */
-                       if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
-                               DEBUG(0,("ensure_canon_entry_valid: talloc fail.\n"));
-                               return false;
-                       }
+       /* If the SID is equal for the user and group that we need
+          to add the duplicate for, add only the group */
+       if (!got_duplicate_user && !got_duplicate_group
+                       && dom_sid_equal(&pace_group->trustee,
+                                       &pace_user->trustee)) {
+               /* Add a duplicate SMB_ACL_GROUP entry, this
+                * will cover the owning SID as well, as it
+                * will always be mapped to both a uid and
+                * gid. */
 
-                       ZERO_STRUCTP(pace);
-                       pace->type = SMB_ACL_USER;;
-                       pace->owner_type = UID_ACE;
-                       pace->unix_ug.type = ID_TYPE_UID;
-                       pace->unix_ug.id = pace_user->unix_ug.id;
-                       pace->trustee = pace_user->trustee;
-                       pace->attr = pace_user->attr;
-                       pace->perms = pace_user->perms;
+               if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
+                       DEBUG(0,("talloc fail.\n"));
+                       return false;
+               }
 
-                       DLIST_ADD(*pp_ace, pace);
+               ZERO_STRUCTP(pace);
+               pace->type = SMB_ACL_GROUP;;
+               pace->owner_type = GID_ACE;
+               pace->unix_ug.type = ID_TYPE_GID;
+               pace->unix_ug.id = pace_group->unix_ug.id;
+               pace->trustee = pace_group->trustee;
+               pace->attr = pace_group->attr;
+               pace->perms = pace_group->perms;
 
-                       got_duplicate_user = true;
+               DLIST_ADD(*pp_ace, pace);
+
+               /* We're done here, make sure the
+                  statements below are not executed. */
+               got_duplicate_user = true;
+               got_duplicate_group = true;
+       }
+
+       if (!got_duplicate_user) {
+               /* Add a duplicate SMB_ACL_USER entry. */
+               if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
+                       DEBUG(0,("talloc fail.\n"));
+                       return false;
                }
 
-               if (!got_duplicate_group) {
-                       /* Add a duplicate SMB_ACL_GROUP entry. */
-                       if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
-                               DEBUG(0,("ensure_canon_entry_valid: talloc fail.\n"));
-                               return false;
-                       }
+               ZERO_STRUCTP(pace);
+               pace->type = SMB_ACL_USER;;
+               pace->owner_type = UID_ACE;
+               pace->unix_ug.type = ID_TYPE_UID;
+               pace->unix_ug.id = pace_user->unix_ug.id;
+               pace->trustee = pace_user->trustee;
+               pace->attr = pace_user->attr;
+               pace->perms = pace_user->perms;
 
-                       ZERO_STRUCTP(pace);
-                       pace->type = SMB_ACL_GROUP;;
-                       pace->owner_type = GID_ACE;
-                       pace->unix_ug.type = ID_TYPE_GID;
-                       pace->unix_ug.id = pace_group->unix_ug.id;
-                       pace->trustee = pace_group->trustee;
-                       pace->attr = pace_group->attr;
-                       pace->perms = pace_group->perms;
+               DLIST_ADD(*pp_ace, pace);
 
-                       DLIST_ADD(*pp_ace, pace);
+               got_duplicate_user = true;
+       }
 
-                       got_duplicate_group = true;
+       if (!got_duplicate_group) {
+               /* Add a duplicate SMB_ACL_GROUP entry. */
+               if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
+                       DEBUG(0,("talloc fail.\n"));
+                       return false;
                }
 
+               ZERO_STRUCTP(pace);
+               pace->type = SMB_ACL_GROUP;;
+               pace->owner_type = GID_ACE;
+               pace->unix_ug.type = ID_TYPE_GID;
+               pace->unix_ug.id = pace_group->unix_ug.id;
+               pace->trustee = pace_group->trustee;
+               pace->attr = pace_group->attr;
+               pace->perms = pace_group->perms;
+
+               DLIST_ADD(*pp_ace, pace);
+
+               got_duplicate_group = true;
        }
 
-       return True;
+       return true;
 }
 
 /****************************************************************************
@@ -2128,7 +2220,7 @@ static bool create_canon_ace_lists(files_struct *fsp,
                 * the file ACL. If we don't have them, check if any SMB_ACL_USER/SMB_ACL_GROUP
                 * entries can be converted to *_OBJ. Don't do this for the default
                 * ACL, we will create them separately for this if needed inside
-                * ensure_canon_entry_valid().
+                * ensure_canon_entry_valid_on_set().
                 */
                if (file_ace) {
                        check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid);
@@ -2530,8 +2622,8 @@ static bool unpack_canon_ace(files_struct *fsp,
 
        print_canon_ace_list( "file ace - before valid", file_ace);
 
-       if (!ensure_canon_entry_valid(fsp->conn, &file_ace, fsp->conn->params,
-                       fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) {
+       if (!ensure_canon_entry_valid_on_set(fsp->conn, &file_ace, false, fsp->conn->params,
+                       fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst)) {
                free_canon_ace_list(file_ace);
                free_canon_ace_list(dir_ace);
                return False;
@@ -2539,8 +2631,8 @@ static bool unpack_canon_ace(files_struct *fsp,
 
        print_canon_ace_list( "dir ace - before valid", dir_ace);
 
-       if (dir_ace && !ensure_canon_entry_valid(fsp->conn, &dir_ace, fsp->conn->params,
-                       fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) {
+       if (dir_ace && !ensure_canon_entry_valid_on_set(fsp->conn, &dir_ace, true, fsp->conn->params,
+                       fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst)) {
                free_canon_ace_list(file_ace);
                free_canon_ace_list(dir_ace);
                return False;
@@ -2628,10 +2720,11 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
        canon_ace *ace = NULL;
        canon_ace *next_ace = NULL;
        int entry_id = SMB_ACL_FIRST_ENTRY;
+       bool is_default_acl = (the_acl_type == SMB_ACL_TYPE_DEFAULT);
        SMB_ACL_ENTRY_T entry;
        size_t ace_count;
 
-       while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
+       while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
                SMB_ACL_TAG_T tagtype;
                SMB_ACL_PERMSET_T permset;
                struct dom_sid sid;
@@ -2641,10 +2734,10 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                entry_id = SMB_ACL_NEXT_ENTRY;
 
                /* Is this a MASK entry ? */
-               if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
+               if (sys_acl_get_tag_type(entry, &tagtype) == -1)
                        continue;
 
-               if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
+               if (sys_acl_get_permset(entry, &permset) == -1)
                        continue;
 
                /* Decide which SID to use based on the ACL type. */
@@ -2658,7 +2751,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                                break;
                        case SMB_ACL_USER:
                                {
-                                       uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+                                       uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
                                        if (puid == NULL) {
                                                DEBUG(0,("canonicalise_acl: Failed to get uid.\n"));
                                                continue;
@@ -2667,7 +2760,6 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                                        unix_ug.type = ID_TYPE_UID;
                                        unix_ug.id = *puid;
                                        owner_type = UID_ACE;
-                                       SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
                                        break;
                                }
                        case SMB_ACL_GROUP_OBJ:
@@ -2679,7 +2771,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                                break;
                        case SMB_ACL_GROUP:
                                {
-                                       gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+                                       gid_t *pgid = (gid_t *)sys_acl_get_qualifier(entry);
                                        if (pgid == NULL) {
                                                DEBUG(0,("canonicalise_acl: Failed to get gid.\n"));
                                                continue;
@@ -2688,11 +2780,10 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                                        unix_ug.type = ID_TYPE_GID;
                                        unix_ug.id = *pgid;
                                        owner_type = GID_ACE;
-                                       SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
                                        break;
                                }
                        case SMB_ACL_MASK:
-                               acl_mask = convert_permset_to_mode_t(conn, permset);
+                               acl_mask = convert_permset_to_mode_t(permset);
                                continue; /* Don't count the mask as an entry. */
                        case SMB_ACL_OTHER:
                                /* Use the Everyone SID */
@@ -2715,12 +2806,12 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
 
                ZERO_STRUCTP(ace);
                ace->type = tagtype;
-               ace->perms = convert_permset_to_mode_t(conn, permset);
+               ace->perms = convert_permset_to_mode_t(permset);
                ace->attr = ALLOW_ACE;
                ace->trustee = sid;
                ace->unix_ug = unix_ug;
                ace->owner_type = owner_type;
-               ace->ace_flags = get_pai_flags(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT));
+               ace->ace_flags = get_pai_flags(pal, ace, is_default_acl);
 
                DLIST_ADD(l_head, ace);
        }
@@ -2729,9 +2820,9 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
         * This next call will ensure we have at least a user/group/world set.
         */
 
-       if (!ensure_canon_entry_valid(conn, &l_head, conn->params,
-                                     S_ISDIR(psbuf->st_ex_mode), powner, pgroup,
-                                     psbuf, False))
+       if (!ensure_canon_entry_valid_on_get(conn, &l_head,
+                                     powner, pgroup,
+                                     psbuf))
                goto fail;
 
        /*
@@ -2739,7 +2830,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
         * acl_mask. Ensure all DENY Entries are at the start of the list.
         */
 
-       DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" ));
+       DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", is_default_acl ?  "Default" : "Access"));
 
        for ( ace_count = 0, ace = l_head; ace; ace = next_ace, ace_count++) {
                next_ace = ace->next;
@@ -2825,7 +2916,7 @@ static bool set_canon_ace_list(files_struct *fsp,
 {
        connection_struct *conn = fsp->conn;
        bool ret = False;
-       SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1);
+       SMB_ACL_T the_acl = sys_acl_init(talloc_tos());
        canon_ace *p_ace;
        int i;
        SMB_ACL_ENTRY_T mask_entry;
@@ -2846,17 +2937,8 @@ static bool set_canon_ace_list(files_struct *fsp,
 #endif
 
        if (the_acl == NULL) {
-
-               if (!no_acl_syscall_error(errno)) {
-                       /*
-                        * Only print this error message if we have some kind of ACL
-                        * support that's not working. Otherwise we would always get this.
-                        */
-                       DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n",
-                               default_ace ? "default" : "file", strerror(errno) ));
-               }
-               *pacl_set_support = False;
-               goto fail;
+               DEBUG(0, ("sys_acl_init failed to allocate an ACL\n"));
+               return false;
        }
 
        if( DEBUGLVL( 10 )) {
@@ -2888,7 +2970,7 @@ static bool set_canon_ace_list(files_struct *fsp,
                 * Get the entry for this ACE.
                 */
 
-               if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
+               if (sys_acl_create_entry(&the_acl, &the_entry) == -1) {
                        DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n",
                                i, strerror(errno) ));
                        goto fail;
@@ -2914,7 +2996,7 @@ static bool set_canon_ace_list(files_struct *fsp,
                 * First tell the entry what type of ACE this is.
                 */
 
-               if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) {
+               if (sys_acl_set_tag_type(the_entry, p_ace->type) == -1) {
                        DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n",
                                i, strerror(errno) ));
                        goto fail;
@@ -2926,7 +3008,7 @@ static bool set_canon_ace_list(files_struct *fsp,
                 */
 
                if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) {
-                       if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.id) == -1) {
+                       if (sys_acl_set_qualifier(the_entry,(void *)&p_ace->unix_ug.id) == -1) {
                                DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n",
                                        i, strerror(errno) ));
                                goto fail;
@@ -2937,7 +3019,7 @@ static bool set_canon_ace_list(files_struct *fsp,
                 * Convert the mode_t perms in the canon_ace to a POSIX permset.
                 */
 
-               if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
+               if (sys_acl_get_permset(the_entry, &the_permset) == -1) {
                        DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n",
                                i, strerror(errno) ));
                        goto fail;
@@ -2953,7 +3035,7 @@ static bool set_canon_ace_list(files_struct *fsp,
                 * ..and apply them to the entry.
                 */
 
-               if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
+               if (sys_acl_set_permset(the_entry, the_permset) == -1) {
                        DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n",
                                i, strerror(errno) ));
                        goto fail;
@@ -2965,17 +3047,17 @@ static bool set_canon_ace_list(files_struct *fsp,
        }
 
        if (needs_mask && !got_mask_entry) {
-               if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) {
+               if (sys_acl_create_entry(&the_acl, &mask_entry) == -1) {
                        DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) ));
                        goto fail;
                }
 
-               if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) {
+               if (sys_acl_set_tag_type(mask_entry, SMB_ACL_MASK) == -1) {
                        DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) ));
                        goto fail;
                }
 
-               if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) {
+               if (sys_acl_get_permset(mask_entry, &mask_permset) == -1) {
                        DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) ));
                        goto fail;
                }
@@ -2985,7 +3067,7 @@ static bool set_canon_ace_list(files_struct *fsp,
                        goto fail;
                }
 
-               if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) {
+               if (sys_acl_set_permset(mask_entry, mask_permset) == -1) {
                        DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) ));
                        goto fail;
                }
@@ -3075,7 +3157,7 @@ static bool set_canon_ace_list(files_struct *fsp,
   fail:
 
        if (the_acl != NULL) {
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
+               TALLOC_FREE(the_acl);
        }
 
        return ret;
@@ -3107,8 +3189,8 @@ SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl)
 
        if (!the_acl)
                return NULL;
-       if (SMB_VFS_SYS_ACL_GET_ENTRY(conn, the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) {
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
+       if (sys_acl_get_entry(the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) {
+               TALLOC_FREE(the_acl);
                return NULL;
        }
        return the_acl;
@@ -3174,11 +3256,11 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
        /* Get the initial bits to apply. */
 
        if (fsp->is_directory) {
-               and_bits = lp_dir_security_mask(snum);
-               or_bits = lp_force_dir_security_mode(snum);
+               and_bits = lp_dir_mask(snum);
+               or_bits = lp_force_dir_mode(snum);
        } else {
-               and_bits = lp_security_mask(snum);
-               or_bits = lp_force_security_mode(snum);
+               and_bits = lp_create_mask(snum);
+               or_bits = lp_force_create_mode(snum);
        }
 
        *posix_perms = (((*posix_perms) & and_bits)|or_bits);
@@ -3308,6 +3390,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
                                      SMB_ACL_T posix_acl,
                                      SMB_ACL_T def_acl,
                                      uint32_t security_info,
+                                     TALLOC_CTX *mem_ctx,
                                      struct security_descriptor **ppdesc)
 {
        struct dom_sid owner_sid;
@@ -3520,7 +3603,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
                }
        } /* security_info & SECINFO_DACL */
 
-       psd = make_standard_sec_desc( talloc_tos(),
+       psd = make_standard_sec_desc(mem_ctx,
                        (security_info & SECINFO_OWNER) ? &owner_sid : NULL,
                        (security_info & SECINFO_GROUP) ? &group_sid : NULL,
                        psa,
@@ -3557,10 +3640,10 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
  done:
 
        if (posix_acl) {
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
+               TALLOC_FREE(posix_acl);
        }
        if (def_acl) {
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+               TALLOC_FREE(def_acl);
        }
        free_canon_ace_list(file_ace);
        free_canon_ace_list(dir_ace);
@@ -3571,11 +3654,14 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
 }
 
 NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
+                          TALLOC_CTX *mem_ctx,
                           struct security_descriptor **ppdesc)
 {
        SMB_STRUCT_STAT sbuf;
        SMB_ACL_T posix_acl = NULL;
        struct pai_val *pal;
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status;
 
        *ppdesc = NULL;
 
@@ -3584,33 +3670,42 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
 
        /* can it happen that fsp_name == NULL ? */
        if (fsp->is_directory ||  fsp->fh->fd == -1) {
-               return posix_get_nt_acl(fsp->conn, fsp->fsp_name->base_name,
-                                       security_info, ppdesc);
+               status = posix_get_nt_acl(fsp->conn, fsp->fsp_name->base_name,
+                                         security_info, mem_ctx, ppdesc);
+               TALLOC_FREE(frame);
+               return status;
        }
 
        /* Get the stat struct for the owner info. */
        if(SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
+               TALLOC_FREE(frame);
                return map_nt_error_from_unix(errno);
        }
 
        /* Get the ACL from the fd. */
-       posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
+       posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, frame);
 
        pal = fload_inherited_info(fsp);
 
-       return posix_get_nt_acl_common(fsp->conn, fsp->fsp_name->base_name,
-                                      &sbuf, pal, posix_acl, NULL,
-                                      security_info, ppdesc);
+       status = posix_get_nt_acl_common(fsp->conn, fsp->fsp_name->base_name,
+                                        &sbuf, pal, posix_acl, NULL,
+                                        security_info, mem_ctx, ppdesc);
+       TALLOC_FREE(frame);
+       return status;
 }
 
 NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
-                         uint32_t security_info, struct security_descriptor **ppdesc)
+                         uint32_t security_info,
+                         TALLOC_CTX *mem_ctx,
+                         struct security_descriptor **ppdesc)
 {
        SMB_ACL_T posix_acl = NULL;
        SMB_ACL_T def_acl = NULL;
        struct pai_val *pal;
        struct smb_filename smb_fname;
        int ret;
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status;
 
        *ppdesc = NULL;
 
@@ -3627,23 +3722,29 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
        }
 
        if (ret == -1) {
+               TALLOC_FREE(frame);
                return map_nt_error_from_unix(errno);
        }
 
        /* Get the ACL from the path. */
-       posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_ACCESS);
+       posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name,
+                                            SMB_ACL_TYPE_ACCESS, frame);
 
        /* If it's a directory get the default POSIX ACL. */
        if(S_ISDIR(smb_fname.st.st_ex_mode)) {
-               def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_DEFAULT);
+               def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name,
+                                                  SMB_ACL_TYPE_DEFAULT, frame);
                def_acl = free_empty_sys_acl(conn, def_acl);
        }
 
        pal = load_inherited_info(conn, name);
 
-       return posix_get_nt_acl_common(conn, name, &smb_fname.st, pal,
-                                      posix_acl, def_acl, security_info,
-                                      ppdesc);
+       status = posix_get_nt_acl_common(conn, name, &smb_fname.st, pal,
+                                        posix_acl, def_acl, security_info,
+                                        mem_ctx,
+                                        ppdesc);
+       TALLOC_FREE(frame);
+       return status;
 }
 
 /****************************************************************************
@@ -4272,33 +4373,34 @@ int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode
        SMB_ACL_T posix_acl;
        int result = -1;
 
-       posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
+       posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+                                            SMB_ACL_TYPE_ACCESS, talloc_tos());
        if (posix_acl == (SMB_ACL_T)NULL)
                return -1;
 
-       while (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
+       while (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) {
                SMB_ACL_TAG_T tagtype;
                SMB_ACL_PERMSET_T permset;
 
                entry_id = SMB_ACL_NEXT_ENTRY;
 
-               if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1)
+               if (sys_acl_get_tag_type(entry, &tagtype) ==-1)
                        break;
 
                if (tagtype == SMB_ACL_GROUP_OBJ) {
-                       if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
+                       if (sys_acl_get_permset(entry, &permset) == -1) {
                                break;
                        } else {
                                *mode &= ~(S_IRGRP|S_IWGRP|S_IXGRP);
-                               *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRGRP : 0);
-                               *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWGRP : 0);
-                               *mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0);
+                               *mode |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRGRP : 0);
+                               *mode |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWGRP : 0);
+                               *mode |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0);
                                result = 0;
                                break;
                        }
                }
        }
-       SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
+       TALLOC_FREE(posix_acl);
        return result;
 }
 
@@ -4313,17 +4415,17 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo
        SMB_ACL_ENTRY_T entry;
        int num_entries = 0;
 
-       while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
+       while ( sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) {
                SMB_ACL_TAG_T tagtype;
                SMB_ACL_PERMSET_T permset;
                mode_t perms;
 
                entry_id = SMB_ACL_NEXT_ENTRY;
 
-               if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
+               if (sys_acl_get_tag_type(entry, &tagtype) == -1)
                        return -1;
 
-               if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
+               if (sys_acl_get_permset(entry, &permset) == -1)
                        return -1;
 
                num_entries++;
@@ -4354,7 +4456,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo
                if (map_acl_perms_to_permset(conn, perms, &permset) == -1)
                        return -1;
 
-               if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) == -1)
+               if (sys_acl_set_permset(entry, permset) == -1)
                        return -1;
        }
 
@@ -4380,7 +4482,9 @@ static int copy_access_posix_acl(connection_struct *conn, const char *from, cons
        SMB_ACL_T posix_acl = NULL;
        int ret = -1;
 
-       if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL)
+       if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from,
+                                                 SMB_ACL_TYPE_ACCESS,
+                                                 talloc_tos())) == NULL)
                return -1;
 
        if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
@@ -4390,7 +4494,7 @@ static int copy_access_posix_acl(connection_struct *conn, const char *from, cons
 
  done:
 
-       SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
+       TALLOC_FREE(posix_acl);
        return ret;
 }
 
@@ -4411,16 +4515,18 @@ int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
 
 static bool directory_has_default_posix_acl(connection_struct *conn, const char *fname)
 {
-       SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT);
+       SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+                                                    SMB_ACL_TYPE_DEFAULT,
+                                                    talloc_tos());
        bool has_acl = False;
        SMB_ACL_ENTRY_T entry;
 
-       if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
+       if (def_acl != NULL && (sys_acl_get_entry(def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
                has_acl = True;
        }
 
        if (def_acl) {
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+               TALLOC_FREE(def_acl);
        }
         return has_acl;
 }
@@ -4450,7 +4556,7 @@ int fchmod_acl(files_struct *fsp, mode_t mode)
        SMB_ACL_T posix_acl = NULL;
        int ret = -1;
 
-       if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp)) == NULL)
+       if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, talloc_tos())) == NULL)
                return -1;
 
        if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
@@ -4460,7 +4566,7 @@ int fchmod_acl(files_struct *fsp, mode_t mode)
 
   done:
 
-       SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
+       TALLOC_FREE(posix_acl);
        return ret;
 }
 
@@ -4474,22 +4580,22 @@ static bool unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_
                return False;
        }
 
-       if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) ==  -1) {
+       if (sys_acl_clear_perms(*p_permset) ==  -1) {
                return False;
        }
 
        if (wire_perm & SMB_POSIX_ACL_READ) {
-               if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) {
+               if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1) {
                        return False;
                }
        }
        if (wire_perm & SMB_POSIX_ACL_WRITE) {
-               if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) {
+               if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1) {
                        return False;
                }
        }
        if (wire_perm & SMB_POSIX_ACL_EXECUTE) {
-               if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) {
+               if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1) {
                        return False;
                }
        }
@@ -4532,10 +4638,13 @@ static bool unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt)
  FIXME ! How does the share mask/mode fit into this.... ?
 ****************************************************************************/
 
-static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_acls, const char *pdata)
+static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn,
+                                           uint16 num_acls,
+                                           const char *pdata,
+                                           TALLOC_CTX *mem_ctx)
 {
        unsigned int i;
-       SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, num_acls);
+       SMB_ACL_T the_acl = sys_acl_init(mem_ctx);
 
        if (the_acl == NULL) {
                return NULL;
@@ -4546,7 +4655,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
                SMB_ACL_PERMSET_T the_permset;
                SMB_ACL_TAG_T tag_type;
 
-               if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
+               if (sys_acl_create_entry(&the_acl, &the_entry) == -1) {
                        DEBUG(0,("create_posix_acl_from_wire: Failed to create entry %u. (%s)\n",
                                i, strerror(errno) ));
                        goto fail;
@@ -4558,14 +4667,14 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
                        goto fail;
                }
 
-               if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, tag_type) == -1) {
+               if (sys_acl_set_tag_type(the_entry, tag_type) == -1) {
                        DEBUG(0,("create_posix_acl_from_wire: Failed to set tagtype on entry %u. (%s)\n",
                                i, strerror(errno) ));
                        goto fail;
                }
 
                /* Get the permset pointer from the new ACL entry. */
-               if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
+               if (sys_acl_get_permset(the_entry, &the_permset) == -1) {
                        DEBUG(0,("create_posix_acl_from_wire: Failed to get permset on entry %u. (%s)\n",
                                 i, strerror(errno) ));
                         goto fail;
@@ -4579,7 +4688,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
                }
 
                /* Now apply to the new ACL entry. */
-               if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
+               if (sys_acl_set_permset(the_entry, the_permset) == -1) {
                        DEBUG(0,("create_posix_acl_from_wire: Failed to add permset on entry %u. (%s)\n",
                                i, strerror(errno) ));
                        goto fail;
@@ -4588,7 +4697,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
                if (tag_type == SMB_ACL_USER) {
                        uint32 uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
                        uid_t uid = (uid_t)uidval;
-                       if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&uid) == -1) {
+                       if (sys_acl_set_qualifier(the_entry,(void *)&uid) == -1) {
                                DEBUG(0,("create_posix_acl_from_wire: Failed to set uid %u on entry %u. (%s)\n",
                                        (unsigned int)uid, i, strerror(errno) ));
                                goto fail;
@@ -4598,7 +4707,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
                if (tag_type == SMB_ACL_GROUP) {
                        uint32 gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
                        gid_t gid = (uid_t)gidval;
-                       if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&gid) == -1) {
+                       if (sys_acl_set_qualifier(the_entry,(void *)&gid) == -1) {
                                DEBUG(0,("create_posix_acl_from_wire: Failed to set gid %u on entry %u. (%s)\n",
                                        (unsigned int)gid, i, strerror(errno) ));
                                goto fail;
@@ -4611,7 +4720,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
  fail:
 
        if (the_acl != NULL) {
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
+               TALLOC_FREE(the_acl);
        }
        return NULL;
 }
@@ -4648,19 +4757,21 @@ bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, cons
                return True;
        }
 
-       if ((def_acl = create_posix_acl_from_wire(conn, num_def_acls, pdata)) == NULL) {
+       if ((def_acl = create_posix_acl_from_wire(conn, num_def_acls,
+                                                 pdata,
+                                                 talloc_tos())) == NULL) {
                return False;
        }
 
        if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, def_acl) == -1) {
                DEBUG(5,("set_unix_posix_default_acl: acl_set_file failed on directory %s (%s)\n",
                        fname, strerror(errno) ));
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+               TALLOC_FREE(def_acl);
                return False;
        }
 
        DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname ));
-       SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+       TALLOC_FREE(def_acl);
        return True;
 }
 
@@ -4679,7 +4790,7 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
        SMB_ACL_ENTRY_T entry;
        bool ret = False;
        /* Create a new ACL with only 3 entries, u/g/w. */
-       SMB_ACL_T new_file_acl = SMB_VFS_SYS_ACL_INIT(conn, 3);
+       SMB_ACL_T new_file_acl = sys_acl_init(talloc_tos());
        SMB_ACL_ENTRY_T user_ent = NULL;
        SMB_ACL_ENTRY_T group_ent = NULL;
        SMB_ACL_ENTRY_T other_ent = NULL;
@@ -4690,34 +4801,34 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
        }
 
        /* Now create the u/g/w entries. */
-       if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &user_ent) == -1) {
+       if (sys_acl_create_entry(&new_file_acl, &user_ent) == -1) {
                DEBUG(5,("remove_posix_acl: Failed to create user entry for file %s. (%s)\n",
                        fname, strerror(errno) ));
                goto done;
        }
-       if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, user_ent, SMB_ACL_USER_OBJ) == -1) {
+       if (sys_acl_set_tag_type(user_ent, SMB_ACL_USER_OBJ) == -1) {
                DEBUG(5,("remove_posix_acl: Failed to set user entry for file %s. (%s)\n",
                        fname, strerror(errno) ));
                goto done;
        }
 
-       if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &group_ent) == -1) {
+       if (sys_acl_create_entry(&new_file_acl, &group_ent) == -1) {
                DEBUG(5,("remove_posix_acl: Failed to create group entry for file %s. (%s)\n",
                        fname, strerror(errno) ));
                goto done;
        }
-       if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, group_ent, SMB_ACL_GROUP_OBJ) == -1) {
+       if (sys_acl_set_tag_type(group_ent, SMB_ACL_GROUP_OBJ) == -1) {
                DEBUG(5,("remove_posix_acl: Failed to set group entry for file %s. (%s)\n",
                        fname, strerror(errno) ));
                goto done;
        }
 
-       if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &other_ent) == -1) {
+       if (sys_acl_create_entry(&new_file_acl, &other_ent) == -1) {
                DEBUG(5,("remove_posix_acl: Failed to create other entry for file %s. (%s)\n",
                        fname, strerror(errno) ));
                goto done;
        }
-       if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, other_ent, SMB_ACL_OTHER) == -1) {
+       if (sys_acl_set_tag_type(other_ent, SMB_ACL_OTHER) == -1) {
                DEBUG(5,("remove_posix_acl: Failed to set other entry for file %s. (%s)\n",
                        fname, strerror(errno) ));
                goto done;
@@ -4725,9 +4836,11 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
 
        /* Get the current file ACL. */
        if (fsp && fsp->fh->fd != -1) {
-               file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
+               file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, talloc_tos());
        } else {
-               file_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_ACCESS);
+               file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+                                                   SMB_ACL_TYPE_ACCESS,
+                                                   talloc_tos());
        }
 
        if (file_acl == NULL) {
@@ -4738,36 +4851,36 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
                goto done;
        }
 
-       while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, file_acl, entry_id, &entry) == 1) {
+       while ( sys_acl_get_entry(file_acl, entry_id, &entry) == 1) {
                SMB_ACL_TAG_T tagtype;
                SMB_ACL_PERMSET_T permset;
 
                entry_id = SMB_ACL_NEXT_ENTRY;
 
-               if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
+               if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
                        DEBUG(5,("remove_posix_acl: failed to get tagtype from ACL on file %s (%s).\n",
                                fname, strerror(errno) ));
                        goto done;
                }
 
-               if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
+               if (sys_acl_get_permset(entry, &permset) == -1) {
                        DEBUG(5,("remove_posix_acl: failed to get permset from ACL on file %s (%s).\n",
                                fname, strerror(errno) ));
                        goto done;
                }
 
                if (tagtype == SMB_ACL_USER_OBJ) {
-                       if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, user_ent, permset) == -1) {
+                       if (sys_acl_set_permset(user_ent, permset) == -1) {
                                DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
                                        fname, strerror(errno) ));
                        }
                } else if (tagtype == SMB_ACL_GROUP_OBJ) {
-                       if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, group_ent, permset) == -1) {
+                       if (sys_acl_set_permset(group_ent, permset) == -1) {
                                DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
                                        fname, strerror(errno) ));
                        }
                } else if (tagtype == SMB_ACL_OTHER) {
-                       if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, other_ent, permset) == -1) {
+                       if (sys_acl_set_permset(other_ent, permset) == -1) {
                                DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
                                        fname, strerror(errno) ));
                        }
@@ -4794,10 +4907,10 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
  done:
 
        if (file_acl) {
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+               TALLOC_FREE(file_acl);
        }
        if (new_file_acl) {
-               SMB_VFS_SYS_ACL_FREE_ACL(conn, new_file_acl);
+               TALLOC_FREE(new_file_acl);
        }
        return ret;
 }
@@ -4817,7 +4930,9 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
                return remove_posix_acl(conn, fsp, fname);
        }
 
-       if ((file_acl = create_posix_acl_from_wire(conn, num_acls, pdata)) == NULL) {
+       if ((file_acl = create_posix_acl_from_wire(conn, num_acls,
+                                                  pdata,
+                                                  talloc_tos())) == NULL) {
                return False;
        }
 
@@ -4826,20 +4941,20 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
                if (SMB_VFS_SYS_ACL_SET_FD(fsp, file_acl) == -1) {
                        DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
                                fname, strerror(errno) ));
-                       SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+                       TALLOC_FREE(file_acl);
                        return False;
                }
        } else {
                if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, file_acl) == -1) {
                        DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
                                fname, strerror(errno) ));
-                       SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+                       TALLOC_FREE(file_acl);
                        return False;
                }
        }
 
        DEBUG(10,("set_unix_posix_acl: set acl for file %s\n", fname ));
-       SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+       TALLOC_FREE(file_acl);
        return True;
 }
 
@@ -4853,15 +4968,16 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
  Assume we are dealing with files (for now)
 ********************************************************************/
 
-struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
+struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname, uint32 security_info_wanted)
 {
-       struct security_descriptor *psd, *ret_sd;
+       struct security_descriptor *ret_sd;
        connection_struct *conn;
        files_struct finfo;
        struct fd_handle fh;
        NTSTATUS status;
+       TALLOC_CTX *frame = talloc_stackframe();
 
-       conn = talloc_zero(ctx, connection_struct);
+       conn = talloc_zero(frame, connection_struct);
        if (conn == NULL) {
                DEBUG(0, ("talloc failed\n"));
                return NULL;
@@ -4869,7 +4985,7 @@ struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fna
 
        if (!(conn->params = talloc(conn, struct share_params))) {
                DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
-               TALLOC_FREE(conn);
+               TALLOC_FREE(frame);
                return NULL;
        }
 
@@ -4880,6 +4996,7 @@ struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fna
        if (!smbd_vfs_init(conn)) {
                DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
                conn_free(conn);
+               TALLOC_FREE(frame);
                return NULL;
         }
 
@@ -4891,24 +5008,27 @@ struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fna
        finfo.fh = &fh;
        finfo.fh->fd = -1;
 
-       status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL,
+       status = create_synthetic_smb_fname(frame, fname, NULL, NULL,
                                            &finfo.fsp_name);
        if (!NT_STATUS_IS_OK(status)) {
                conn_free(conn);
+               TALLOC_FREE(frame);
                return NULL;
        }
 
-       if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, SECINFO_DACL, &psd))) {
+       if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo,
+                                                 security_info_wanted,
+                                                 ctx, &ret_sd))) {
                DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
                TALLOC_FREE(finfo.fsp_name);
                conn_free(conn);
+               TALLOC_FREE(frame);
                return NULL;
        }
 
-       ret_sd = dup_sec_desc( ctx, psd );
-
        TALLOC_FREE(finfo.fsp_name);
        conn_free(conn);
+       TALLOC_FREE(frame);
 
        return ret_sd;
 }
@@ -5022,3 +5142,117 @@ NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
        }
        return NT_STATUS_OK;
 }
+
+int posix_sys_acl_blob_get_file(vfs_handle_struct *handle,
+                               const char *path_p,
+                               TALLOC_CTX *mem_ctx,
+                               char **blob_description,
+                               DATA_BLOB *blob)
+{
+       int ret;
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct smb_acl_wrapper acl_wrapper = {};
+       struct smb_filename *smb_fname = NULL;
+       NTSTATUS status = create_synthetic_smb_fname_split(frame, path_p,
+                                                          NULL,
+                                                          &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       acl_wrapper.access_acl
+               = smb_vfs_call_sys_acl_get_file(handle,
+                                               path_p,
+                                               SMB_ACL_TYPE_ACCESS,
+                                               frame);
+
+       ret = smb_vfs_call_stat(handle, smb_fname);
+       if (ret == -1) {
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+               acl_wrapper.default_acl
+                       = smb_vfs_call_sys_acl_get_file(handle,
+                                                       path_p,
+                                                       SMB_ACL_TYPE_DEFAULT,
+                                                       frame);
+       }
+
+       acl_wrapper.owner = smb_fname->st.st_ex_uid;
+       acl_wrapper.group = smb_fname->st.st_ex_gid;
+       acl_wrapper.mode = smb_fname->st.st_ex_mode;
+
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(blob, mem_ctx,
+                                                         &acl_wrapper,
+                                                         (ndr_push_flags_fn_t)ndr_push_smb_acl_wrapper))) {
+               errno = EINVAL;
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       *blob_description = talloc_strdup(mem_ctx, "posix_acl");
+       if (!*blob_description) {
+               errno = EINVAL;
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       TALLOC_FREE(frame);
+       return 0;
+}
+
+int posix_sys_acl_blob_get_fd(vfs_handle_struct *handle,
+                             files_struct *fsp,
+                             TALLOC_CTX *mem_ctx,
+                             char **blob_description,
+                             DATA_BLOB *blob)
+{
+       SMB_STRUCT_STAT sbuf;
+       TALLOC_CTX *frame;
+       struct smb_acl_wrapper acl_wrapper;
+       int ret;
+
+       /* This ensures that we also consider the default ACL */
+       if (fsp->is_directory ||  fsp->fh->fd == -1) {
+               return posix_sys_acl_blob_get_file(handle, fsp->fsp_name->base_name,
+                                                  mem_ctx, blob_description, blob);
+       }
+       frame = talloc_stackframe();
+
+       acl_wrapper.default_acl = NULL;
+
+       acl_wrapper.access_acl = smb_vfs_call_sys_acl_get_file(handle, fsp->fsp_name->base_name,
+                                                              SMB_ACL_TYPE_ACCESS, frame);
+
+       ret = smb_vfs_call_fstat(handle, fsp, &sbuf);
+       if (ret == -1) {
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       acl_wrapper.owner = sbuf.st_ex_uid;
+       acl_wrapper.group = sbuf.st_ex_gid;
+       acl_wrapper.mode = sbuf.st_ex_mode;
+
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(blob, mem_ctx,
+                                                         &acl_wrapper,
+                                                         (ndr_push_flags_fn_t)ndr_push_smb_acl_wrapper))) {
+               errno = EINVAL;
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       *blob_description = talloc_strdup(mem_ctx, "posix_acl");
+       if (!*blob_description) {
+               errno = EINVAL;
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       TALLOC_FREE(frame);
+       return 0;
+}