smbd: Remove NT4 compatability handling in posix -> NT ACL conversion
[metze/samba/wip.git] / source3 / smbd / posix_acls.c
index de27a1ea93114b1523db582d78fef762950c096c..b8e0d4aba42a7497516d0e073e917e46b3cde43a 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,7 +856,7 @@ 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;
 
@@ -894,15 +895,15 @@ static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_AC
        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;
@@ -1057,24 +1058,6 @@ static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
        *pp_list_head = l_head;
 }
 
-/****************************************************************************
- Check if we need to return NT4.x compatible ACL entries.
-****************************************************************************/
-
-bool nt4_compatible_acls(void)
-{
-       int compat = lp_acl_compatibility();
-
-       if (compat == ACL_COMPAT_AUTO) {
-               enum remote_arch_types ra_type = get_remote_arch();
-
-               /* Automatically adapt to client */
-               return (ra_type <= RA_WINNT);
-       } else
-               return (compat == ACL_COMPAT_WINNT);
-}
-
-
 /****************************************************************************
  Map canon_ace perms to permission bits NT.
  The attr element is not used here - we only process deny entries on set,
@@ -1106,10 +1089,7 @@ uint32_t map_canon_ace_perms(int snum,
                 * to be changed in the future.
                 */
 
-               if (nt4_compatible_acls())
-                       nt_mask = UNIX_ACCESS_NONE;
-               else
-                       nt_mask = 0;
+               nt_mask = 0;
        } else {
                if (directory_ace) {
                        nt_mask |= ((perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
@@ -1270,11 +1250,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 +1322,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 +1443,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 +1454,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 +1486,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 +1525,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 +1536,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 +1553,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 +1564,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;
-
-                       DLIST_ADD(*pp_ace, pace);
+       /* 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. */
 
-                       /* 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. */
+
+               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;
 
-                       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;
+               DLIST_ADD(*pp_ace, pace);
 
-                       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;
+       }
 
-                       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,("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;
 }
 
 /****************************************************************************
@@ -1862,26 +1933,6 @@ static bool create_canon_ace_lists(files_struct *fsp,
                        DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));
                        return False;
                }
-
-               if (nt4_compatible_acls()) {
-                       /*
-                        * The security mask may be UNIX_ACCESS_NONE which should map into
-                        * no permissions (we overload the WRITE_OWNER bit for this) or it
-                        * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this
-                        * to be so. Any other bits override the UNIX_ACCESS_NONE bit.
-                        */
-
-                       /*
-                        * Convert GENERIC bits to specific bits.
-                        */
-                       se_map_generic(&psa->access_mask, &file_generic_mapping);
-
-                       psa->access_mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);
-
-                       if(psa->access_mask != UNIX_ACCESS_NONE)
-                               psa->access_mask &= ~UNIX_ACCESS_NONE;
-               }
        }
 
        /*
@@ -2128,7 +2179,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 +2581,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 +2590,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,6 +2679,7 @@ 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;
 
@@ -2667,7 +2719,6 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                                        unix_ug.type = ID_TYPE_UID;
                                        unix_ug.id = *puid;
                                        owner_type = UID_ACE;
-                                       sys_acl_free_qualifier((void *)puid,tagtype);
                                        break;
                                }
                        case SMB_ACL_GROUP_OBJ:
@@ -2688,11 +2739,10 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                                        unix_ug.type = ID_TYPE_GID;
                                        unix_ug.id = *pgid;
                                        owner_type = GID_ACE;
-                                       sys_acl_free_qualifier((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 +2765,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 +2779,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 +2789,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 +2875,7 @@ static bool set_canon_ace_list(files_struct *fsp,
 {
        connection_struct *conn = fsp->conn;
        bool ret = False;
-       SMB_ACL_T the_acl = sys_acl_init(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 +2896,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 +2929,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 +2955,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 +2967,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;
@@ -2953,7 +2994,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,12 +3006,12 @@ 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;
                }
@@ -2985,7 +3026,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,28 +3116,12 @@ static bool set_canon_ace_list(files_struct *fsp,
   fail:
 
        if (the_acl != NULL) {
-               sys_acl_free_acl(the_acl);
+               TALLOC_FREE(the_acl);
        }
 
        return ret;
 }
 
-/****************************************************************************
- Find a particular canon_ace entry.
-****************************************************************************/
-
-static struct canon_ace *canon_ace_entry_for(struct canon_ace *list, SMB_ACL_TAG_T type, struct unixid *id)
-{
-       while (list) {
-               if (list->type == type && ((type != SMB_ACL_USER && type != SMB_ACL_GROUP) ||
-                               (type == SMB_ACL_USER  && id && id->id == list->unix_ug.id) ||
-                               (type == SMB_ACL_GROUP && id && id->id == list->unix_ug.id)))
-                       break;
-               list = list->next;
-       }
-       return list;
-}
-
 /****************************************************************************
  
 ****************************************************************************/
@@ -3108,7 +3133,7 @@ SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl)
        if (!the_acl)
                return NULL;
        if (sys_acl_get_entry(the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) {
-               sys_acl_free_acl(the_acl);
+               TALLOC_FREE(the_acl);
                return NULL;
        }
        return the_acl;
@@ -3174,11 +3199,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 +3333,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;
@@ -3378,55 +3404,6 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
                        canon_ace *ace;
                        enum security_ace_type nt_acl_type;
 
-                       if (nt4_compatible_acls() && dir_ace) {
-                               /*
-                                * NT 4 chokes if an ACL contains an INHERIT_ONLY entry
-                                * but no non-INHERIT_ONLY entry for one SID. So we only
-                                * remove entries from the Access ACL if the
-                                * corresponding Default ACL entries have also been
-                                * removed. ACEs for CREATOR-OWNER and CREATOR-GROUP
-                                * are exceptions. We can do nothing
-                                * intelligent if the Default ACL contains entries that
-                                * are not also contained in the Access ACL, so this
-                                * case will still fail under NT 4.
-                                */
-
-                               ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL);
-                               if (ace && !ace->perms) {
-                                       DLIST_REMOVE(dir_ace, ace);
-                                       TALLOC_FREE(ace);
-
-                                       ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL);
-                                       if (ace && !ace->perms) {
-                                               DLIST_REMOVE(file_ace, ace);
-                                               TALLOC_FREE(ace);
-                                       }
-                               }
-
-                               /*
-                                * WinNT doesn't usually have Creator Group
-                                * in browse lists, so we send this entry to
-                                * WinNT even if it contains no relevant
-                                * permissions. Once we can add
-                                * Creator Group to browse lists we can
-                                * re-enable this.
-                                */
-
-#if 0
-                               ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL);
-                               if (ace && !ace->perms) {
-                                       DLIST_REMOVE(dir_ace, ace);
-                                       TALLOC_FREE(ace);
-                               }
-#endif
-
-                               ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL);
-                               if (ace && !ace->perms) {
-                                       DLIST_REMOVE(file_ace, ace);
-                                       TALLOC_FREE(ace);
-                               }
-                       }
-
                        num_acls = count_canon_ace_list(file_ace);
                        num_def_acls = count_canon_ace_list(dir_ace);
 
@@ -3520,7 +3497,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 +3534,10 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
  done:
 
        if (posix_acl) {
-               sys_acl_free_acl(posix_acl);
+               TALLOC_FREE(posix_acl);
        }
        if (def_acl) {
-               sys_acl_free_acl(def_acl);
+               TALLOC_FREE(def_acl);
        }
        free_canon_ace_list(file_ace);
        free_canon_ace_list(dir_ace);
@@ -3571,11 +3548,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 +3564,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 +3616,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,7 +4267,8 @@ 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;
 
@@ -4298,7 +4294,7 @@ int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode
                        }
                }
        }
-       sys_acl_free_acl(posix_acl);
+       TALLOC_FREE(posix_acl);
        return result;
 }
 
@@ -4354,7 +4350,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 +4376,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 +4388,7 @@ static int copy_access_posix_acl(connection_struct *conn, const char *from, cons
 
  done:
 
-       sys_acl_free_acl(posix_acl);
+       TALLOC_FREE(posix_acl);
        return ret;
 }
 
@@ -4411,7 +4409,9 @@ 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;
 
@@ -4420,7 +4420,7 @@ static bool directory_has_default_posix_acl(connection_struct *conn, const char
        }
 
        if (def_acl) {
-               sys_acl_free_acl(def_acl);
+               TALLOC_FREE(def_acl);
        }
         return has_acl;
 }
@@ -4450,7 +4450,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 +4460,7 @@ int fchmod_acl(files_struct *fsp, mode_t mode)
 
   done:
 
-       sys_acl_free_acl(posix_acl);
+       TALLOC_FREE(posix_acl);
        return ret;
 }
 
@@ -4479,17 +4479,17 @@ static bool unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_
        }
 
        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 +4532,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 = sys_acl_init(num_acls);
+       SMB_ACL_T the_acl = sys_acl_init(mem_ctx);
 
        if (the_acl == NULL) {
                return NULL;
@@ -4546,7 +4549,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,7 +4561,7 @@ 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;
@@ -4579,7 +4582,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 +4591,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 +4601,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 +4614,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
  fail:
 
        if (the_acl != NULL) {
-               sys_acl_free_acl(the_acl);
+               TALLOC_FREE(the_acl);
        }
        return NULL;
 }
@@ -4648,19 +4651,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) ));
-               sys_acl_free_acl(def_acl);
+               TALLOC_FREE(def_acl);
                return False;
        }
 
        DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname ));
-       sys_acl_free_acl(def_acl);
+       TALLOC_FREE(def_acl);
        return True;
 }
 
@@ -4679,7 +4684,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 = sys_acl_init(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 +4695,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 +4730,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) {
@@ -4757,17 +4764,17 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
                }
 
                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 +4801,10 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
  done:
 
        if (file_acl) {
-               sys_acl_free_acl(file_acl);
+               TALLOC_FREE(file_acl);
        }
        if (new_file_acl) {
-               sys_acl_free_acl(new_file_acl);
+               TALLOC_FREE(new_file_acl);
        }
        return ret;
 }
@@ -4817,7 +4824,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 +4835,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) ));
-                       sys_acl_free_acl(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) ));
-                       sys_acl_free_acl(file_acl);
+                       TALLOC_FREE(file_acl);
                        return False;
                }
        }
 
        DEBUG(10,("set_unix_posix_acl: set acl for file %s\n", fname ));
-       sys_acl_free_acl(file_acl);
+       TALLOC_FREE(file_acl);
        return True;
 }
 
@@ -4848,29 +4857,34 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
  check.  Caller is responsible for freeing the returned security
  descriptor via TALLOC_FREE().  This is designed for dealing with 
  user space access checks in smbd outside of the VFS.  For example,
- checking access rights in OpenEventlog().
+ checking access rights in OpenEventlog() or from python.
 
- Assume we are dealing with files (for now)
 ********************************************************************/
 
-struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
+NTSTATUS get_nt_acl_no_snum(TALLOC_CTX *ctx, const char *fname,
+                               uint32 security_info_wanted,
+                               struct security_descriptor **sd)
 {
-       struct security_descriptor *psd, *ret_sd;
+       TALLOC_CTX *frame = talloc_stackframe();
        connection_struct *conn;
-       files_struct finfo;
-       struct fd_handle fh;
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_OK;
 
-       conn = talloc_zero(ctx, connection_struct);
+       if (!posix_locking_init(false)) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       conn = talloc_zero(frame, connection_struct);
        if (conn == NULL) {
+               TALLOC_FREE(frame);
                DEBUG(0, ("talloc failed\n"));
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
 
        if (!(conn->params = talloc(conn, struct share_params))) {
-               DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
-               TALLOC_FREE(conn);
-               return NULL;
+               DEBUG(0, ("talloc failed\n"));
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
        }
 
        conn->params->service = -1;
@@ -4878,39 +4892,21 @@ struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fna
        set_conn_connectpath(conn, "/");
 
        if (!smbd_vfs_init(conn)) {
-               DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
-               conn_free(conn);
-               return NULL;
-        }
-
-       ZERO_STRUCT( finfo );
-       ZERO_STRUCT( fh );
-
-       finfo.fnum = FNUM_FIELD_INVALID;
-       finfo.conn = conn;
-       finfo.fh = &fh;
-       finfo.fh->fd = -1;
-
-       status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL,
-                                           &finfo.fsp_name);
-       if (!NT_STATUS_IS_OK(status)) {
-               conn_free(conn);
-               return NULL;
+               DEBUG(0,("smbd_vfs_init() failed!\n"));
+               TALLOC_FREE(frame);
+               return NT_STATUS_INTERNAL_ERROR;
        }
 
-       if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, SECINFO_DACL, &psd))) {
-               DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
-               TALLOC_FREE(finfo.fsp_name);
-               conn_free(conn);
-               return NULL;
+       status = SMB_VFS_GET_NT_ACL(conn, fname, security_info_wanted, ctx, sd);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("set_nt_acl_no_snum: fset_nt_acl returned %s.\n",
+                       nt_errstr(status)));
        }
 
-       ret_sd = dup_sec_desc( ctx, psd );
-
-       TALLOC_FREE(finfo.fsp_name);
        conn_free(conn);
+       TALLOC_FREE(frame);
 
-       return ret_sd;
+       return status;
 }
 
 /* Stolen shamelessly from pvfs_default_acl() in source4 :-). */
@@ -5022,3 +5018,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;
+}