notifyd: Use messaging_register for MSG_SMB_NOTIFY_GET_DB
[vlendec/samba-autobuild/.git] / source3 / smbd / posix_acls.c
index 05cd2a740d04c5b4d3a455e69089b5a0d4c188af..e4403458495493c7e9a419d6bf5053e5abc0df25 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;
@@ -129,7 +130,7 @@ struct pai_val {
 };
 
 /************************************************************************
- Return a uint32 of the pai_entry principal.
+ Return a uint32_t of the pai_entry principal.
 ************************************************************************/
 
 static uint32_t get_pai_entry_val(struct pai_entry *paie)
@@ -149,7 +150,7 @@ static uint32_t get_pai_entry_val(struct pai_entry *paie)
 }
 
 /************************************************************************
- Return a uint32 of the entry principal.
+ Return a uint32_t of the entry principal.
 ************************************************************************/
 
 static uint32_t get_entry_val(canon_ace *ace_entry)
@@ -274,7 +275,7 @@ static void store_inheritance_attributes(files_struct *fsp,
                ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
                                pai_buf, store_size, 0);
        } else {
-               ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name,
+               ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name,
                                       SAMBA_POSIX_INHERITANCE_EA_NAME,
                                       pai_buf, store_size, 0);
        }
@@ -337,8 +338,8 @@ static uint16_t get_pai_flags(struct pai_val *pal, canon_ace *ace_entry, bool de
 
 static bool check_pai_ok_v1(const char *pai_buf, size_t pai_buf_data_size)
 {
-       uint16 num_entries;
-       uint16 num_def_entries;
+       uint16_t num_entries;
+       uint16_t num_def_entries;
 
        if (pai_buf_data_size < PAI_V1_ENTRIES_BASE) {
                /* Corrupted - too small. */
@@ -369,8 +370,8 @@ static bool check_pai_ok_v1(const char *pai_buf, size_t pai_buf_data_size)
 
 static bool check_pai_ok_v2(const char *pai_buf, size_t pai_buf_data_size)
 {
-       uint16 num_entries;
-       uint16 num_def_entries;
+       uint16_t num_entries;
+       uint16_t num_def_entries;
 
        if (pai_buf_data_size < PAI_V2_ENTRIES_BASE) {
                /* Corrupted - too small. */
@@ -436,7 +437,7 @@ static const char *create_pai_v1_entries(struct pai_val *paiv,
                                const char *entry_offset,
                                bool def_entry)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < paiv->num_entries; i++) {
                struct pai_entry *paie = talloc(talloc_tos(), struct pai_entry);
@@ -628,7 +629,7 @@ static struct pai_val *fload_inherited_info(files_struct *fsp)
                                        pai_buf, pai_buf_size);
                } else {
                        ret = SMB_VFS_GETXATTR(fsp->conn,
-                                              fsp->fsp_name->base_name,
+                                              fsp->fsp_name,
                                               SAMBA_POSIX_INHERITANCE_EA_NAME,
                                               pai_buf, pai_buf_size);
                }
@@ -680,7 +681,7 @@ static struct pai_val *fload_inherited_info(files_struct *fsp)
 ************************************************************************/
 
 static struct pai_val *load_inherited_info(const struct connection_struct *conn,
-                                          const char *fname)
+                                          const struct smb_filename *smb_fname)
 {
        char *pai_buf;
        size_t pai_buf_size = 1024;
@@ -696,7 +697,7 @@ static struct pai_val *load_inherited_info(const struct connection_struct *conn,
        }
 
        do {
-               ret = SMB_VFS_GETXATTR(conn, fname,
+               ret = SMB_VFS_GETXATTR(conn, smb_fname,
                                       SAMBA_POSIX_INHERITANCE_EA_NAME,
                                       pai_buf, pai_buf_size);
 
@@ -715,7 +716,8 @@ static struct pai_val *load_inherited_info(const struct connection_struct *conn,
                }
        } while (ret == -1);
 
-       DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fname));
+       DEBUG(10,("load_inherited_info: ret = %lu for file %s\n",
+                       (unsigned long)ret, smb_fname->base_name));
 
        if (ret == -1) {
                /* No attribute or not supported. */
@@ -735,7 +737,7 @@ static struct pai_val *load_inherited_info(const struct connection_struct *conn,
        if (paiv) {
                DEBUG(10,("load_inherited_info: ACL type 0x%x for file %s\n",
                        (unsigned int)paiv->sd_type,
-                       fname));
+                       smb_fname->base_name));
        }
 
        TALLOC_FREE(pai_buf);
@@ -801,11 +803,9 @@ static void print_canon_ace(canon_ace *pace, int num)
        dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
        dbgtext( "SID = %s ", sid_string_dbg(&pace->trustee));
        if (pace->owner_type == UID_ACE) {
-               const char *u_name = uidtoname(pace->unix_ug.id);
-               dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.id, u_name );
+               dbgtext( "uid %u ", (unsigned int)pace->unix_ug.id);
        } else if (pace->owner_type == GID_ACE) {
-               char *g_name = gidtoname(pace->unix_ug.id);
-               dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.id, g_name );
+               dbgtext( "gid %u ", (unsigned int)pace->unix_ug.id);
        } else
                dbgtext( "other ");
        switch (pace->type) {
@@ -912,7 +912,9 @@ static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_AC
  Function to create owner and group SIDs from a SMB_STRUCT_STAT.
 ****************************************************************************/
 
-void create_file_sids(const SMB_STRUCT_STAT *psbuf, struct dom_sid *powner_sid, struct dom_sid *pgroup_sid)
+static void create_file_sids(const SMB_STRUCT_STAT *psbuf,
+                            struct dom_sid *powner_sid,
+                            struct dom_sid *pgroup_sid)
 {
        uid_to_sid( powner_sid, psbuf->st_ex_uid );
        gid_to_sid( pgroup_sid, psbuf->st_ex_gid );
@@ -1057,24 +1059,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 +1090,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 );
@@ -1140,7 +1121,7 @@ uint32_t map_canon_ace_perms(int snum,
 #define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA)
 #define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
 
-static mode_t map_nt_perms( uint32 *mask, int type)
+static mode_t map_nt_perms( uint32_t *mask, int type)
 {
        mode_t mode = 0;
 
@@ -1183,12 +1164,9 @@ static mode_t map_nt_perms( uint32 *mask, int type)
 
 NTSTATUS unpack_nt_owners(struct connection_struct *conn,
                        uid_t *puser, gid_t *pgrp,
-                       uint32 security_info_sent, const struct
+                       uint32_t security_info_sent, const struct
                        security_descriptor *psd)
 {
-       struct dom_sid owner_sid;
-       struct dom_sid grp_sid;
-
        *puser = (uid_t)-1;
        *pgrp = (gid_t)-1;
 
@@ -1201,9 +1179,6 @@ NTSTATUS unpack_nt_owners(struct connection_struct *conn,
         * Validate the owner and group SID's.
         */
 
-       memset(&owner_sid, '\0', sizeof(owner_sid));
-       memset(&grp_sid, '\0', sizeof(grp_sid));
-
        DEBUG(5,("unpack_nt_owners: validating owner_sids.\n"));
 
        /*
@@ -1212,8 +1187,7 @@ NTSTATUS unpack_nt_owners(struct connection_struct *conn,
         */
 
        if (security_info_sent & SECINFO_OWNER) {
-               sid_copy(&owner_sid, psd->owner_sid);
-               if (!sid_to_uid(&owner_sid, puser)) {
+               if (!sid_to_uid(psd->owner_sid, puser)) {
                        if (lp_force_unknown_acl_user(SNUM(conn))) {
                                /* this allows take ownership to work
                                 * reasonably */
@@ -1221,7 +1195,7 @@ NTSTATUS unpack_nt_owners(struct connection_struct *conn,
                        } else {
                                DEBUG(3,("unpack_nt_owners: unable to validate"
                                         " owner sid for %s\n",
-                                        sid_string_dbg(&owner_sid)));
+                                        sid_string_dbg(psd->owner_sid)));
                                return NT_STATUS_INVALID_OWNER;
                        }
                }
@@ -1235,8 +1209,7 @@ NTSTATUS unpack_nt_owners(struct connection_struct *conn,
         */
 
        if (security_info_sent & SECINFO_GROUP) {
-               sid_copy(&grp_sid, psd->group_sid);
-               if (!sid_to_gid( &grp_sid, pgrp)) {
+               if (!sid_to_gid(psd->group_sid, pgrp)) {
                        if (lp_force_unknown_acl_user(SNUM(conn))) {
                                /* this allows take group ownership to work
                                 * reasonably */
@@ -1256,48 +1229,19 @@ NTSTATUS unpack_nt_owners(struct connection_struct *conn,
        return NT_STATUS_OK;
 }
 
-/****************************************************************************
- Ensure the enforced permissions for this share apply.
-****************************************************************************/
 
-static void apply_default_perms(const struct share_params *params,
-                               const bool is_directory, canon_ace *pace,
-                               mode_t type)
+static void trim_ace_perms(canon_ace *pace)
 {
-       mode_t and_bits = (mode_t)0;
-       mode_t or_bits = (mode_t)0;
-
-       /* Get the initial bits to apply. */
+       pace->perms = pace->perms & (S_IXUSR|S_IWUSR|S_IRUSR);
+}
 
+static void ensure_minimal_owner_ace_perms(const bool is_directory,
+                                          canon_ace *pace)
+{
+       pace->perms |= S_IRUSR;
        if (is_directory) {
-               and_bits = lp_dir_mask(params->service);
-               or_bits = lp_force_dir_mode(params->service);
-       } else {
-               and_bits = lp_create_mask(params->service);
-               or_bits = lp_force_create_mode(params->service);
+               pace->perms |= (S_IWUSR|S_IXUSR);
        }
-
-       /* Now bounce them into the S_USR space. */     
-       switch(type) {
-       case S_IRUSR:
-               /* Ensure owner has read access. */
-               pace->perms |= S_IRUSR;
-               if (is_directory)
-                       pace->perms |= (S_IWUSR|S_IXUSR);
-               and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR);
-               or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR);
-               break;
-       case S_IRGRP:
-               and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP);
-               or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP);
-               break;
-       case S_IROTH:
-               and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH);
-               or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH);
-               break;
-       }
-
-       pace->perms = ((pace->perms & and_bits)|or_bits);
 }
 
 /****************************************************************************
@@ -1450,44 +1394,14 @@ static bool ensure_canon_entry_valid_on_set(connection_struct *conn,
        bool got_duplicate_group = false;
 
        for (pace = *pp_ace; pace; pace = pace->next) {
+               trim_ace_perms(pace);
                if (pace->type == SMB_ACL_USER_OBJ) {
-
-                       if (!is_default_acl) {
-                               apply_default_perms(params, is_directory, pace, S_IRUSR);
-                       }
+                       ensure_minimal_owner_ace_perms(is_directory, pace);
                        pace_user = pace;
-
                } else if (pace->type == SMB_ACL_GROUP_OBJ) {
-
-                       /*
-                        * Ensure create mask/force create mode is respected on set.
-                        */
-
-                       if (!is_default_acl) {
-                               apply_default_perms(params, is_directory, pace, S_IRGRP);
-                       }
                        pace_group = pace;
-
                } else if (pace->type == SMB_ACL_OTHER) {
-
-                       /*
-                        * Ensure create mask/force create mode is respected on set.
-                        */
-
-                       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);
-                       }
                }
        }
 
@@ -1535,9 +1449,11 @@ static bool ensure_canon_entry_valid_on_set(connection_struct *conn,
                                pace->perms = pace_other->perms;
                }
 
-               if (!is_default_acl) {
-                       apply_default_perms(params, is_directory, pace, S_IRUSR);
-               }
+               /*
+                * Ensure we have default parameters for the
+                * user (owner) even on default ACLs.
+                */
+               ensure_minimal_owner_ace_perms(is_directory, pace);
 
                DLIST_ADD(*pp_ace, pace);
                pace_user = pace;
@@ -1563,9 +1479,6 @@ static bool ensure_canon_entry_valid_on_set(connection_struct *conn,
                } else {
                        pace->perms = 0;
                }
-               if (!is_default_acl) {
-                       apply_default_perms(params, is_directory, pace, S_IRGRP);
-               }
 
                DLIST_ADD(*pp_ace, pace);
                pace_group = pace;
@@ -1585,9 +1498,6 @@ static bool ensure_canon_entry_valid_on_set(connection_struct *conn,
                pace->trustee = global_sid_World;
                pace->attr = ALLOW_ACE;
                pace->perms = 0;
-               if (!is_default_acl) {
-                       apply_default_perms(params, is_directory, pace, S_IROTH);
-               }
 
                DLIST_ADD(*pp_ace, pace);
                pace_other = pace;
@@ -1608,7 +1518,7 @@ static bool ensure_canon_entry_valid_on_set(connection_struct *conn,
                        /* Already got one. */
                        got_duplicate_user = true;
                } else if (pace->type == SMB_ACL_GROUP &&
-                               pace->unix_ug.id == pace_user->unix_ug.id) {
+                               pace->unix_ug.id == pace_group->unix_ug.id) {
                        /* Already got one. */
                        got_duplicate_group = true;
                } else if ((pace->type == SMB_ACL_GROUP)
@@ -1779,7 +1689,7 @@ static bool add_current_ace_to_acl(files_struct *fsp, struct security_ace *psa,
                    (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) {
 
                        canon_ace *current_dir_ace = current_ace;
-                       DLIST_ADD_END(*dir_ace, current_ace, canon_ace *);
+                       DLIST_ADD_END(*dir_ace, current_ace);
 
                        /*
                         * Note if this was an allow ace. We can't process
@@ -1881,7 +1791,7 @@ static bool add_current_ace_to_acl(files_struct *fsp, struct security_ace *psa,
         */
 
        if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
-               DLIST_ADD_END(*file_ace, current_ace, canon_ace *);
+               DLIST_ADD_END(*file_ace, current_ace);
 
                /*
                 * Note if this was an allow ace. We can't process
@@ -1891,7 +1801,7 @@ static bool add_current_ace_to_acl(files_struct *fsp, struct security_ace *psa,
                if (current_ace->attr == ALLOW_ACE)
                        *got_file_allow = True;
 
-               if ((current_ace->attr == DENY_ACE) && got_file_allow) {
+               if ((current_ace->attr == DENY_ACE) && *got_file_allow) {
                        DEBUG(0,("add_current_ace_to_acl: malformed "
                                 "ACL in file ACL ! Deny entry after "
                                 "Allow entry. Failing to set on file "
@@ -1937,7 +1847,7 @@ static bool create_canon_ace_lists(files_struct *fsp,
        canon_ace *current_ace = NULL;
        bool got_dir_allow = False;
        bool got_file_allow = False;
-       int i, j;
+       uint32_t i, j;
 
        *ppfile_ace = NULL;
        *ppdir_ace = NULL;
@@ -1953,26 +1863,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;
-               }
        }
 
        /*
@@ -2084,47 +1974,50 @@ static bool create_canon_ace_lists(files_struct *fsp,
                        }
 
                        if (unixid.type == ID_TYPE_BOTH) {
-                               /* If it's the owning user, this is a
-                                * user_obj, not a user.  This way, we
-                                * get a valid ACL for groups that own
-                                * files, without putting user ACL
-                                * entries in for groups otherwise */
-                               if (unixid.id == pst->st_ex_uid) {
-                                       current_ace->owner_type = UID_ACE;
-                                       current_ace->unix_ug.type = ID_TYPE_UID;
-                                       current_ace->unix_ug.id = unixid.id;
-                                       current_ace->type = SMB_ACL_USER_OBJ;
-
-                                       /* Add the user object to the posix ACL,
-                                          and proceed to the group mapping
-                                          below. This handles the talloc_free
-                                          of current_ace if not added for some
-                                          reason */
-                                       if (!add_current_ace_to_acl(fsp,
-                                                       psa,
-                                                       &file_ace,
-                                                       &dir_ace,
-                                                       &got_file_allow,
-                                                       &got_dir_allow,
-                                                       &all_aces_are_inherit_only,
-                                                       current_ace)) {
-                                               free_canon_ace_list(file_ace);
-                                               free_canon_ace_list(dir_ace);
-                                               return false;
-                                       }
-
-                                       if ((current_ace = talloc(talloc_tos(),
-                                                       canon_ace)) == NULL) {
-                                               free_canon_ace_list(file_ace);
-                                               free_canon_ace_list(dir_ace);
-                                               DEBUG(0,("create_canon_ace_lists: "
-                                                       "malloc fail.\n"));
-                                               return False;
-                                       }
+                               /*
+                                * We must add both a user and group
+                                * entry POSIX_ACL.
+                                * This is due to the fact that in POSIX
+                                * user entries are more specific than
+                                * groups.
+                                */
+                               current_ace->owner_type = UID_ACE;
+                               current_ace->unix_ug.type = ID_TYPE_UID;
+                               current_ace->unix_ug.id = unixid.id;
+                               current_ace->type =
+                                       (unixid.id == pst->st_ex_uid) ?
+                                               SMB_ACL_USER_OBJ :
+                                               SMB_ACL_USER;
+
+                               /* Add the user object to the posix ACL,
+                                  and proceed to the group mapping
+                                  below. This handles the talloc_free
+                                  of current_ace if not added for some
+                                  reason */
+                               if (!add_current_ace_to_acl(fsp,
+                                               psa,
+                                               &file_ace,
+                                               &dir_ace,
+                                               &got_file_allow,
+                                               &got_dir_allow,
+                                               &all_aces_are_inherit_only,
+                                               current_ace)) {
+                                       free_canon_ace_list(file_ace);
+                                       free_canon_ace_list(dir_ace);
+                                       return false;
+                               }
 
-                                       ZERO_STRUCTP(current_ace);
+                               if ((current_ace = talloc(talloc_tos(),
+                                               canon_ace)) == NULL) {
+                                       free_canon_ace_list(file_ace);
+                                       free_canon_ace_list(dir_ace);
+                                       DEBUG(0,("create_canon_ace_lists: "
+                                               "malloc fail.\n"));
+                                       return False;
                                }
 
+                               ZERO_STRUCTP(current_ace);
+
                                sid_copy(&current_ace->trustee, &psa->trustee);
 
                                current_ace->unix_ug.type = ID_TYPE_GID;
@@ -2427,7 +2320,7 @@ static void process_deny_list(connection_struct *conn, canon_ace **pp_ace_list )
 
                        curr_ace->attr = ALLOW_ACE;
                        curr_ace->perms = (mode_t)0;
-                       DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
+                       DLIST_DEMOTE(ace_list, curr_ace);
                        continue;
                }
 
@@ -2452,7 +2345,7 @@ static void process_deny_list(connection_struct *conn, canon_ace **pp_ace_list )
 
                curr_ace->attr = ALLOW_ACE;
                curr_ace->perms = (new_perms & ~curr_ace->perms);
-               DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
+               DLIST_DEMOTE(ace_list, curr_ace);
        }
 
        /* Pass 3 above - deal with deny group entries. */
@@ -2499,7 +2392,7 @@ static void process_deny_list(connection_struct *conn, canon_ace **pp_ace_list )
                        curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;
                else
                        curr_ace->perms = (mode_t)0;
-               DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
+               DLIST_DEMOTE(ace_list, curr_ace);
        }
 
        /* Doing this fourth pass allows Windows semantics to be layered
@@ -2555,7 +2448,7 @@ static bool unpack_canon_ace(files_struct *fsp,
                                struct dom_sid *pfile_grp_sid,
                                canon_ace **ppfile_ace,
                                canon_ace **ppdir_ace,
-                               uint32 security_info_sent,
+                               uint32_t security_info_sent,
                                const struct security_descriptor *psd)
 {
        canon_ace *file_ace = NULL;
@@ -2580,9 +2473,10 @@ static bool unpack_canon_ace(files_struct *fsp,
         * Now go through the DACL and create the canon_ace lists.
         */
 
-       if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid,
-                                                               &file_ace, &dir_ace, psd->dacl))
+       if (!create_canon_ace_lists(fsp, pst, pfile_owner_sid, pfile_grp_sid,
+                                   &file_ace, &dir_ace, psd->dacl)) {
                return False;
+       }
 
        if ((file_ace == NULL) && (dir_ace == NULL)) {
                /* W2K traverse DACL set - ignore. */
@@ -2697,7 +2591,7 @@ static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head)
        }
 
        if (other_ace) {
-               DLIST_DEMOTE(l_head, other_ace, canon_ace *);
+               DLIST_DEMOTE(l_head, other_ace);
        }
 
        /* We have probably changed the head of the list. */
@@ -2732,7 +2626,6 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
 
                entry_id = SMB_ACL_NEXT_ENTRY;
 
-               /* Is this a MASK entry ? */
                if (sys_acl_get_tag_type(entry, &tagtype) == -1)
                        continue;
 
@@ -2803,13 +2696,14 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                if ((ace = talloc(talloc_tos(), canon_ace)) == NULL)
                        goto fail;
 
-               ZERO_STRUCTP(ace);
-               ace->type = tagtype;
-               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 = (canon_ace) {
+                       .type = tagtype,
+                       .perms = convert_permset_to_mode_t(permset),
+                       .attr = ALLOW_ACE,
+                       .trustee = sid,
+                       .unix_ug = unix_ug,
+                       .owner_type = owner_type
+               };
                ace->ace_flags = get_pai_flags(pal, ace, is_default_acl);
 
                DLIST_ADD(l_head, ace);
@@ -2865,7 +2759,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
 
 bool current_user_in_group(connection_struct *conn, gid_t gid)
 {
-       int i;
+       uint32_t i;
        const struct security_unix_token *utok = get_current_utok(conn);
 
        for (i = 0; i < utok->ngroups; i++) {
@@ -3077,7 +2971,7 @@ static bool set_canon_ace_list(files_struct *fsp,
         */
 
        if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
-               if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name->base_name,
+               if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name,
                                             the_acl_type, the_acl) == -1) {
                        /*
                         * Some systems allow all the above calls and only fail with no ACL support
@@ -3097,7 +2991,7 @@ static bool set_canon_ace_list(files_struct *fsp,
 
                                become_root();
                                sret = SMB_VFS_SYS_ACL_SET_FILE(conn,
-                                   fsp->fsp_name->base_name, the_acl_type,
+                                   fsp->fsp_name, the_acl_type,
                                    the_acl);
                                unbecome_root();
                                if (sret == 0) {
@@ -3162,22 +3056,6 @@ static bool set_canon_ace_list(files_struct *fsp,
        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;
-}
-
 /****************************************************************************
  
 ****************************************************************************/
@@ -3203,16 +3081,13 @@ SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl)
 
 static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms)
 {
-       int snum = SNUM(fsp->conn);
        size_t ace_count = count_canon_ace_list(file_ace_list);
        canon_ace *ace_p;
        canon_ace *owner_ace = NULL;
        canon_ace *group_ace = NULL;
        canon_ace *other_ace = NULL;
-       mode_t and_bits;
-       mode_t or_bits;
 
-       if (ace_count != 3) {
+       if (ace_count > 5) {
                DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE "
                         "entries for file %s to convert to posix perms.\n",
                         fsp_str_dbg(fsp)));
@@ -3234,6 +3109,43 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
                return False;
        }
 
+       /*
+        * Ensure all ACE entries are owner, group or other.
+        * We can't set if there are any other SIDs.
+        */
+       for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
+               if (ace_p == owner_ace || ace_p == group_ace ||
+                               ace_p == other_ace) {
+                       continue;
+               }
+               if (ace_p->owner_type == UID_ACE) {
+                       if (ace_p->unix_ug.id != owner_ace->unix_ug.id) {
+                               DEBUG(3,("Invalid uid %u in ACE for file %s.\n",
+                                       (unsigned int)ace_p->unix_ug.id,
+                                       fsp_str_dbg(fsp)));
+                               return false;
+                       }
+               } else if (ace_p->owner_type == GID_ACE) {
+                       if (ace_p->unix_ug.id != group_ace->unix_ug.id) {
+                               DEBUG(3,("Invalid gid %u in ACE for file %s.\n",
+                                       (unsigned int)ace_p->unix_ug.id,
+                                       fsp_str_dbg(fsp)));
+                               return false;
+                       }
+               } else {
+                       /*
+                        * There should be no duplicate WORLD_ACE entries.
+                        */
+
+                       DEBUG(3,("Invalid type %u, uid %u in "
+                               "ACE for file %s.\n",
+                               (unsigned int)ace_p->owner_type,
+                               (unsigned int)ace_p->unix_ug.id,
+                               fsp_str_dbg(fsp)));
+                       return false;
+               }
+       }
+
        *posix_perms = (mode_t)0;
 
        *posix_perms |= owner_ace->perms;
@@ -3250,20 +3162,6 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
        if (fsp->is_directory)
                *posix_perms |= (S_IWUSR|S_IXUSR);
 
-       /* If requested apply the masks. */
-
-       /* Get the initial bits to apply. */
-
-       if (fsp->is_directory) {
-               and_bits = lp_dir_mask(snum);
-               or_bits = lp_force_dir_mode(snum);
-       } else {
-               and_bits = lp_create_mask(snum);
-               or_bits = lp_force_create_mode(snum);
-       }
-
-       *posix_perms = (((*posix_perms) & and_bits)|or_bits);
-
        DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o "
                  "to perm=0%o for file %s.\n", (int)owner_ace->perms,
                  (int)group_ace->perms, (int)other_ace->perms,
@@ -3285,8 +3183,8 @@ static size_t merge_default_aces( struct security_ace *nt_ace_list, size_t num_a
 
        for (i = 0; i < num_aces; i++) {
                for (j = i+1; j < num_aces; j++) {
-                       uint32 i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
-                       uint32 j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
+                       uint32_t i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
+                       uint32_t j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
                        bool i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
                        bool j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
 
@@ -3354,7 +3252,7 @@ static void add_or_replace_ace(struct security_ace *nt_ace_list, size_t *num_ace
                                const struct dom_sid *sid, enum security_ace_type type,
                                uint32_t mask, uint8_t flags)
 {
-       int i;
+       size_t i;
 
        /* first search for a duplicate */
        for (i = 0; i < *num_aces; i++) {
@@ -3365,7 +3263,7 @@ static void add_or_replace_ace(struct security_ace *nt_ace_list, size_t *num_ace
        if (i < *num_aces) { /* found */
                nt_ace_list[i].type = type;
                nt_ace_list[i].access_mask = mask;
-               DEBUG(10, ("Replacing ACE %d with SID %s and flags %02x\n",
+               DEBUG(10, ("Replacing ACE %zu with SID %s and flags %02x\n",
                           i, sid_string_dbg(sid), flags));
                return;
        }
@@ -3405,7 +3303,6 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
        size_t num_profile_acls = 0;
        struct dom_sid orig_owner_sid;
        struct security_descriptor *psd = NULL;
-       int i;
 
        /*
         * Get the owner, group and world SIDs.
@@ -3421,7 +3318,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
                num_profile_acls = 3;
        }
 
-       if ((security_info & SECINFO_DACL) && !(security_info & SECINFO_PROTECTED_DACL)) {
+       if (security_info & SECINFO_DACL) {
 
                /*
                 * In the optimum case Creator Owner and Creator Group would be used for
@@ -3429,7 +3326,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
                 * would lead to usability problems under Windows: The Creator entries
                 * are only available in browse lists of directories and not for files;
                 * additionally the identity of the owning group couldn't be determined.
-                * We therefore use those identities only for Default ACLs. 
+                * We therefore use those identities only for Default ACLs.
                 */
 
                /* Create the canon_ace lists. */
@@ -3438,7 +3335,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
                                            SMB_ACL_TYPE_ACCESS);
 
                /* We must have *some* ACLS. */
-       
+
                if (count_canon_ace_list(file_ace) == 0) {
                        DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", name));
                        goto done;
@@ -3460,66 +3357,18 @@ 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);
 
-                       /* Allocate the ace list. */
-                       if ((nt_ace_list = talloc_array(talloc_tos(), struct security_ace,num_acls + num_profile_acls + num_def_acls)) == NULL) {
+                       nt_ace_list = talloc_zero_array(
+                               talloc_tos(), struct security_ace,
+                               num_acls + num_profile_acls + num_def_acls);
+
+                       if (nt_ace_list == NULL) {
                                DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n"));
                                goto done;
                        }
 
-                       memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(struct security_ace) );
-
                        /*
                         * Create the NT ACE list from the canonical ace lists.
                         */
@@ -3581,6 +3430,8 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
                        num_aces = merge_default_aces(nt_ace_list, num_aces);
 
                        if (lp_profile_acls(SNUM(conn))) {
+                               size_t i;
+
                                for (i = 0; i < num_aces; i++) {
                                        if (dom_sid_equal(&nt_ace_list[i].trustee, &owner_sid)) {
                                                add_or_replace_ace(nt_ace_list, &num_aces,
@@ -3669,7 +3520,7 @@ 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) {
-               status = posix_get_nt_acl(fsp->conn, fsp->fsp_name->base_name,
+               status = posix_get_nt_acl(fsp->conn, fsp->fsp_name,
                                          security_info, mem_ctx, ppdesc);
                TALLOC_FREE(frame);
                return status;
@@ -3693,32 +3544,39 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
        return status;
 }
 
-NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
-                         uint32_t security_info,
-                         TALLOC_CTX *mem_ctx,
-                         struct security_descriptor **ppdesc)
+NTSTATUS posix_get_nt_acl(struct connection_struct *conn,
+                       const struct smb_filename *smb_fname_in,
+                       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;
+       struct smb_filename *smb_fname = NULL;
        int ret;
        TALLOC_CTX *frame = talloc_stackframe();
        NTSTATUS status;
 
        *ppdesc = NULL;
 
-       DEBUG(10,("posix_get_nt_acl: called for file %s\n", name ));
+       DEBUG(10,("posix_get_nt_acl: called for file %s\n",
+               smb_fname_in->base_name ));
 
-       ZERO_STRUCT(smb_fname);
-       smb_fname.base_name = discard_const_p(char, name);
+       smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
+       if (smb_fname == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
 
        /* Get the stat struct for the owner info. */
-       if (lp_posix_pathnames()) {
-               ret = SMB_VFS_LSTAT(conn, &smb_fname);
-       } else {
-               ret = SMB_VFS_STAT(conn, &smb_fname);
-       }
+       /*
+        * We can directly use SMB_VFS_STAT here, as if this was a
+        * POSIX call on a symlink, we've already refused it.
+        * For a Windows acl mapped call on a symlink, we want to follow
+        * it.
+        */
+       ret = SMB_VFS_STAT(conn, smb_fname);
 
        if (ret == -1) {
                TALLOC_FREE(frame);
@@ -3726,22 +3584,27 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
        }
 
        /* Get the ACL from the path. */
-       posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name,
+       posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
                                             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,
+       if(S_ISDIR(smb_fname->st.st_ex_mode)) {
+               def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
                                                   SMB_ACL_TYPE_DEFAULT, frame);
                def_acl = free_empty_sys_acl(conn, def_acl);
        }
 
-       pal = load_inherited_info(conn, name);
+       pal = load_inherited_info(conn, smb_fname);
 
-       status = posix_get_nt_acl_common(conn, name, &smb_fname.st, pal,
-                                        posix_acl, def_acl, security_info,
-                                        mem_ctx,
-                                        ppdesc);
+       status = posix_get_nt_acl_common(conn,
+                                       smb_fname->base_name,
+                                       &smb_fname->st,
+                                       pal,
+                                       posix_acl,
+                                       def_acl,
+                                       security_info,
+                                       mem_ctx,
+                                       ppdesc);
        TALLOC_FREE(frame);
        return status;
 }
@@ -3819,207 +3682,6 @@ NTSTATUS try_chown(files_struct *fsp, uid_t uid, gid_t gid)
        return status;
 }
 
-#if 0
-/* Disable this - prevents ACL inheritance from the ACL editor. JRA. */
-
-/****************************************************************************
- Take care of parent ACL inheritance.
-****************************************************************************/
-
-NTSTATUS append_parent_acl(files_struct *fsp,
-                               const struct security_descriptor *pcsd,
-                               struct security_descriptor **pp_new_sd)
-{
-       struct smb_filename *smb_dname = NULL;
-       struct security_descriptor *parent_sd = NULL;
-       files_struct *parent_fsp = NULL;
-       TALLOC_CTX *mem_ctx = talloc_tos();
-       char *parent_name = NULL;
-       struct security_ace *new_ace = NULL;
-       unsigned int num_aces = pcsd->dacl->num_aces;
-       NTSTATUS status;
-       int info;
-       unsigned int i, j;
-       struct security_descriptor *psd = dup_sec_desc(talloc_tos(), pcsd);
-       bool is_dacl_protected = (pcsd->type & SEC_DESC_DACL_PROTECTED);
-
-       if (psd == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (!parent_dirname(mem_ctx, fsp->fsp_name->base_name, &parent_name,
-                           NULL)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       status = create_synthetic_smb_fname(mem_ctx, parent_name, NULL, NULL,
-                                           &smb_dname);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto fail;
-       }
-
-       status = SMB_VFS_CREATE_FILE(
-               fsp->conn,                              /* conn */
-               NULL,                                   /* req */
-               0,                                      /* root_dir_fid */
-               smb_dname,                              /* fname */
-               FILE_READ_ATTRIBUTES,                   /* access_mask */
-               FILE_SHARE_NONE,                        /* share_access */
-               FILE_OPEN,                              /* create_disposition*/
-               FILE_DIRECTORY_FILE,                    /* create_options */
-               0,                                      /* file_attributes */
-               INTERNAL_OPEN_ONLY,                     /* oplock_request */
-               0,                                      /* allocation_size */
-               NULL,                                   /* sd */
-               NULL,                                   /* ea_list */
-               &parent_fsp,                            /* result */
-               &info);                                 /* pinfo */
-
-       if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(smb_dname);
-               return status;
-       }
-
-       status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, smb_dname->base_name,
-                                   SECINFO_DACL, &parent_sd );
-
-       close_file(NULL, parent_fsp, NORMAL_CLOSE);
-       TALLOC_FREE(smb_dname);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       /*
-        * Make room for potentially all the ACLs from
-        * the parent. We used to add the ugw triple here,
-        * as we knew we were dealing with POSIX ACLs.
-        * We no longer need to do so as we can guarentee
-        * that a default ACL from the parent directory will
-        * be well formed for POSIX ACLs if it came from a
-        * POSIX ACL source, and if we're not writing to a
-        * POSIX ACL sink then we don't care if it's not well
-        * formed. JRA.
-        */
-
-       num_aces += parent_sd->dacl->num_aces;
-
-       if((new_ace = talloc_zero_array(mem_ctx, struct security_ace,
-                                       num_aces)) == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* Start by copying in all the given ACE entries. */
-       for (i = 0; i < psd->dacl->num_aces; i++) {
-               sec_ace_copy(&new_ace[i], &psd->dacl->aces[i]);
-       }
-
-       /*
-        * Note that we're ignoring "inherit permissions" here
-        * as that really only applies to newly created files. JRA.
-        */
-
-       /* Finally append any inherited ACEs. */
-       for (j = 0; j < parent_sd->dacl->num_aces; j++) {
-               struct security_ace *se = &parent_sd->dacl->aces[j];
-
-               if (fsp->is_directory) {
-                       if (!(se->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
-                               /* Doesn't apply to a directory - ignore. */
-                               DEBUG(10,("append_parent_acl: directory %s "
-                                       "ignoring non container "
-                                       "inherit flags %u on ACE with sid %s "
-                                       "from parent %s\n",
-                                       fsp_str_dbg(fsp),
-                                       (unsigned int)se->flags,
-                                       sid_string_dbg(&se->trustee),
-                                       parent_name));
-                               continue;
-                       }
-               } else {
-                       if (!(se->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
-                               /* Doesn't apply to a file - ignore. */
-                               DEBUG(10,("append_parent_acl: file %s "
-                                       "ignoring non object "
-                                       "inherit flags %u on ACE with sid %s "
-                                       "from parent %s\n",
-                                       fsp_str_dbg(fsp),
-                                       (unsigned int)se->flags,
-                                       sid_string_dbg(&se->trustee),
-                                       parent_name));
-                               continue;
-                       }
-               }
-
-               if (is_dacl_protected) {
-                       /* If the DACL is protected it means we must
-                        * not overwrite an existing ACE entry with the
-                        * same SID. This is order N^2. Ouch :-(. JRA. */
-                       unsigned int k;
-                       for (k = 0; k < psd->dacl->num_aces; k++) {
-                               if (dom_sid_equal(&psd->dacl->aces[k].trustee,
-                                               &se->trustee)) {
-                                       break;
-                               }
-                       }
-                       if (k < psd->dacl->num_aces) {
-                               /* SID matched. Ignore. */
-                               DEBUG(10,("append_parent_acl: path %s "
-                                       "ignoring ACE with protected sid %s "
-                                       "from parent %s\n",
-                                       fsp_str_dbg(fsp),
-                                       sid_string_dbg(&se->trustee),
-                                       parent_name));
-                               continue;
-                       }
-               }
-
-               sec_ace_copy(&new_ace[i], se);
-               if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
-                       new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT);
-               }
-               new_ace[i].flags |= SEC_ACE_FLAG_INHERITED_ACE;
-
-               if (fsp->is_directory) {
-                       /*
-                        * Strip off any inherit only. It's applied.
-                        */
-                       new_ace[i].flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY);
-                       if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
-                               /* No further inheritance. */
-                               new_ace[i].flags &=
-                                       ~(SEC_ACE_FLAG_CONTAINER_INHERIT|
-                                       SEC_ACE_FLAG_OBJECT_INHERIT);
-                       }
-               } else {
-                       /*
-                        * Strip off any container or inherit
-                        * flags, they can't apply to objects.
-                        */
-                       new_ace[i].flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|
-                                               SEC_ACE_FLAG_INHERIT_ONLY|
-                                               SEC_ACE_FLAG_NO_PROPAGATE_INHERIT);
-               }
-               i++;
-
-               DEBUG(10,("append_parent_acl: path %s "
-                       "inheriting ACE with sid %s "
-                       "from parent %s\n",
-                       fsp_str_dbg(fsp),
-                       sid_string_dbg(&se->trustee),
-                       parent_name));
-       }
-
-       psd->dacl->aces = new_ace;
-       psd->dacl->num_aces = i;
-       psd->type &= ~(SEC_DESC_DACL_AUTO_INHERITED|
-                         SEC_DESC_DACL_AUTO_INHERIT_REQ);
-
-       *pp_new_sd = psd;
-       return status;
-}
-#endif
-
 /****************************************************************************
  Reply to set a security descriptor on an fsp. security_info_sent is the
  description of the following NT ACL.
@@ -4028,7 +3690,7 @@ NTSTATUS append_parent_acl(files_struct *fsp,
  it, even though it's a const pointer.
 ****************************************************************************/
 
-NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd_orig)
+NTSTATUS set_nt_acl(files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd_orig)
 {
        connection_struct *conn = fsp->conn;
        uid_t user = (uid_t)-1;
@@ -4053,12 +3715,22 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct s
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
        }
 
-       if (!psd_orig) {
+       if (psd_orig == NULL) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       psd = dup_sec_desc(talloc_tos(), psd_orig);
-       if (!psd) {
+       /*
+        * MS NFS mode, here's the deal: the client merely wants to
+        * modify the mode, but roundtripping get_acl/set/acl would
+        * add additional POSIX ACEs.  So in case we get a request
+        * containing a MS NFS mode SID, we do nothing here.
+        */
+       if (security_descriptor_with_ms_nfs(psd_orig)) {
+               return NT_STATUS_OK;
+       }
+
+       psd = security_descriptor_copy(talloc_tos(), psd_orig);
+       if (psd == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -4086,6 +3758,14 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct s
                security_info_sent &= ~SECINFO_GROUP;
        }
 
+       /* If UNIX owner is inherited and Windows isn't, then
+        * setting the UNIX owner based on Windows owner conflicts
+        * with the inheritance rule
+        */
+       if (lp_inherit_owner(SNUM(conn)) == INHERIT_OWNER_UNIX_ONLY) {
+               security_info_sent &= ~SECINFO_OWNER;
+       }
+
        status = unpack_nt_owners( conn, &user, &grp, security_info_sent, psd);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -4248,7 +3928,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct s
                                become_root();
                        }
                        sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn,
-                           fsp->fsp_name->base_name);
+                           fsp->fsp_name);
                        if (set_acl_as_root) {
                                unbecome_root();
                        }
@@ -4264,7 +3944,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct s
                                        sret =
                                            SMB_VFS_SYS_ACL_DELETE_DEF_FILE(
                                                    conn,
-                                                   fsp->fsp_name->base_name);
+                                                   fsp->fsp_name);
                                        unbecome_root();
                                }
 
@@ -4316,7 +3996,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct s
                        if (set_acl_as_root) {
                                become_root();
                        }
-                       sret = SMB_VFS_CHMOD(conn, fsp->fsp_name->base_name,
+                       sret = SMB_VFS_CHMOD(conn, fsp->fsp_name,
                                             posix_perms);
                        if (set_acl_as_root) {
                                unbecome_root();
@@ -4331,7 +4011,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct s
 
                                        become_root();
                                        sret = SMB_VFS_CHMOD(conn,
-                                           fsp->fsp_name->base_name,
+                                           fsp->fsp_name,
                                            posix_perms);
                                        unbecome_root();
                                }
@@ -4365,14 +4045,16 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct s
  the mask bits, not the real group bits, for a file with an ACL.
 ****************************************************************************/
 
-int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode )
+int get_acl_group_bits( connection_struct *conn,
+                       const struct smb_filename *smb_fname,
+                       mode_t *mode )
 {
        int entry_id = SMB_ACL_FIRST_ENTRY;
        SMB_ACL_ENTRY_T entry;
        SMB_ACL_T posix_acl;
        int result = -1;
 
-       posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+       posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
                                             SMB_ACL_TYPE_ACCESS, talloc_tos());
        if (posix_acl == (SMB_ACL_T)NULL)
                return -1;
@@ -4476,12 +4158,15 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo
  resulting ACL on TO.  Note that name is in UNIX character set.
 ****************************************************************************/
 
-static int copy_access_posix_acl(connection_struct *conn, const char *from, const char *to, mode_t mode)
+static int copy_access_posix_acl(connection_struct *conn,
+                               const struct smb_filename *smb_fname_from,
+                               const struct smb_filename *smb_fname_to,
+                               mode_t mode)
 {
        SMB_ACL_T posix_acl = NULL;
        int ret = -1;
 
-       if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from,
+       if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname_from,
                                                  SMB_ACL_TYPE_ACCESS,
                                                  talloc_tos())) == NULL)
                return -1;
@@ -4489,7 +4174,8 @@ static int copy_access_posix_acl(connection_struct *conn, const char *from, cons
        if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
                goto done;
 
-       ret = SMB_VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl);
+       ret = SMB_VFS_SYS_ACL_SET_FILE(conn, smb_fname_to,
+                       SMB_ACL_TYPE_ACCESS, posix_acl);
 
  done:
 
@@ -4503,18 +4189,21 @@ static int copy_access_posix_acl(connection_struct *conn, const char *from, cons
  Note that name is in UNIX character set.
 ****************************************************************************/
 
-int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
+int chmod_acl(connection_struct *conn,
+                       const struct smb_filename *smb_fname,
+                       mode_t mode)
 {
-       return copy_access_posix_acl(conn, name, name, mode);
+       return copy_access_posix_acl(conn, smb_fname, smb_fname, mode);
 }
 
 /****************************************************************************
  Check for an existing default POSIX ACL on a directory.
 ****************************************************************************/
 
-static bool directory_has_default_posix_acl(connection_struct *conn, const char *fname)
+static bool directory_has_default_posix_acl(connection_struct *conn,
+                       const struct smb_filename *smb_fname)
 {
-       SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+       SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
                                                     SMB_ACL_TYPE_DEFAULT,
                                                     talloc_tos());
        bool has_acl = False;
@@ -4535,13 +4224,25 @@ static bool directory_has_default_posix_acl(connection_struct *conn, const char
  inherit this Access ACL to file name.
 ****************************************************************************/
 
-int inherit_access_posix_acl(connection_struct *conn, const char *inherit_from_dir,
-                      const char *name, mode_t mode)
+int inherit_access_posix_acl(connection_struct *conn,
+                       const char *inherit_from_dir,
+                       const struct smb_filename *smb_fname,
+                       mode_t mode)
 {
-       if (directory_has_default_posix_acl(conn, inherit_from_dir))
+       struct smb_filename *inherit_from_fname =
+                       synthetic_smb_fname(talloc_tos(),
+                               smb_fname->base_name,
+                               NULL,
+                               NULL,
+                               smb_fname->flags);
+       if (inherit_from_fname == NULL) {
+               return-1;
+       }
+
+       if (directory_has_default_posix_acl(conn, inherit_from_fname))
                return 0;
 
-       return copy_access_posix_acl(conn, inherit_from_dir, name, mode);
+       return copy_access_posix_acl(conn, inherit_from_fname, smb_fname, mode);
 }
 
 /****************************************************************************
@@ -4638,7 +4339,7 @@ static bool unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt)
 ****************************************************************************/
 
 static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn,
-                                           uint16 num_acls,
+                                           uint16_t num_acls,
                                            const char *pdata,
                                            TALLOC_CTX *mem_ctx)
 {
@@ -4694,7 +4395,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn,
                }
 
                if (tag_type == SMB_ACL_USER) {
-                       uint32 uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
+                       uint32_t uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
                        uid_t uid = (uid_t)uidval;
                        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",
@@ -4704,7 +4405,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn,
                }
 
                if (tag_type == SMB_ACL_GROUP) {
-                       uint32 gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
+                       uint32_t gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
                        gid_t gid = (uid_t)gidval;
                        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",
@@ -4731,14 +4432,18 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn,
  on the directory.
 ****************************************************************************/
 
-bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf,
-                               uint16 num_def_acls, const char *pdata)
+bool set_unix_posix_default_acl(connection_struct *conn,
+                               const struct smb_filename *smb_fname,
+                               uint16_t num_def_acls,
+                               const char *pdata)
 {
        SMB_ACL_T def_acl = NULL;
 
-       if (!S_ISDIR(psbuf->st_ex_mode)) {
+       if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
                if (num_def_acls) {
-                       DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname ));
+                       DEBUG(5,("set_unix_posix_default_acl: Can't "
+                               "set default ACL on non-directory file %s\n",
+                               smb_fname->base_name ));
                        errno = EISDIR;
                        return False;
                } else {
@@ -4748,9 +4453,9 @@ bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, cons
 
        if (!num_def_acls) {
                /* Remove the default ACL. */
-               if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fname) == -1) {
+               if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, smb_fname) == -1) {
                        DEBUG(5,("set_unix_posix_default_acl: acl_delete_def_file failed on directory %s (%s)\n",
-                               fname, strerror(errno) ));
+                               smb_fname->base_name, strerror(errno) ));
                        return False;
                }
                return True;
@@ -4762,14 +4467,16 @@ bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, cons
                return False;
        }
 
-       if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, def_acl) == -1) {
+       if (SMB_VFS_SYS_ACL_SET_FILE(conn, smb_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_fname->base_name, strerror(errno) ));
                TALLOC_FREE(def_acl);
                return False;
        }
 
-       DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname ));
+       DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n",
+               smb_fname->base_name ));
        TALLOC_FREE(def_acl);
        return True;
 }
@@ -4782,12 +4489,15 @@ bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, cons
  FIXME ! How does the share mask/mode fit into this.... ?
 ****************************************************************************/
 
-static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname)
+static bool remove_posix_acl(connection_struct *conn,
+                       files_struct *fsp,
+                       const struct smb_filename *smb_fname)
 {
        SMB_ACL_T file_acl = NULL;
        int entry_id = SMB_ACL_FIRST_ENTRY;
        SMB_ACL_ENTRY_T entry;
        bool ret = False;
+       const char *fname = smb_fname->base_name;
        /* Create a new ACL with only 3 entries, u/g/w. */
        SMB_ACL_T new_file_acl = sys_acl_init(talloc_tos());
        SMB_ACL_ENTRY_T user_ent = NULL;
@@ -4837,7 +4547,7 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
        if (fsp && fsp->fh->fd != -1) {
                file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, talloc_tos());
        } else {
-               file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+               file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
                                                    SMB_ACL_TYPE_ACCESS,
                                                    talloc_tos());
        }
@@ -4894,7 +4604,10 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
                        goto done;
                }
        } else {
-               if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, new_file_acl) == -1) {
+               if (SMB_VFS_SYS_ACL_SET_FILE(conn,
+                                       smb_fname,
+                                       SMB_ACL_TYPE_ACCESS,
+                                       new_file_acl) == -1) {
                        DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
                                fname, strerror(errno) ));
                        goto done;
@@ -4920,13 +4633,17 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
  except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER.
 ****************************************************************************/
 
-bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname, uint16 num_acls, const char *pdata)
+bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp,
+                       const struct smb_filename *smb_fname,
+                       uint16_t num_acls,
+                       const char *pdata)
 {
        SMB_ACL_T file_acl = NULL;
+       const char *fname = smb_fname->base_name;
 
        if (!num_acls) {
                /* Remove the ACL from the file. */
-               return remove_posix_acl(conn, fsp, fname);
+               return remove_posix_acl(conn, fsp, smb_fname);
        }
 
        if ((file_acl = create_posix_acl_from_wire(conn, num_acls,
@@ -4944,7 +4661,8 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
                        return False;
                }
        } else {
-               if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, file_acl) == -1) {
+               if (SMB_VFS_SYS_ACL_SET_FILE(conn, smb_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) ));
                        TALLOC_FREE(file_acl);
@@ -4962,182 +4680,180 @@ 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, uint32 security_info_wanted)
+NTSTATUS get_nt_acl_no_snum(TALLOC_CTX *ctx, const char *fname,
+                               uint32_t security_info_wanted,
+                               struct security_descriptor **sd)
 {
-       struct security_descriptor *ret_sd;
-       connection_struct *conn;
-       files_struct finfo;
-       struct fd_handle fh;
-       NTSTATUS status;
        TALLOC_CTX *frame = talloc_stackframe();
+       connection_struct *conn;
+       NTSTATUS status = NT_STATUS_OK;
+       struct smb_filename *smb_fname = synthetic_smb_fname(talloc_tos(),
+                                               fname,
+                                               NULL,
+                                               NULL,
+                                               0);
+
+       if (smb_fname == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       conn = talloc_zero(frame, connection_struct);
-       if (conn == NULL) {
-               DEBUG(0, ("talloc failed\n"));
-               return NULL;
+       if (!posix_locking_init(false)) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
        }
 
-       if (!(conn->params = talloc(conn, struct share_params))) {
-               DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
+       status = create_conn_struct(ctx,
+                               server_event_context(),
+                               server_messaging_context(),
+                               &conn,
+                               -1,
+                               "/",
+                               NULL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("create_conn_struct returned %s.\n",
+                       nt_errstr(status)));
                TALLOC_FREE(frame);
-               return NULL;
+               return status;
+       }
+
+       status = SMB_VFS_GET_NT_ACL(conn,
+                               smb_fname,
+                               security_info_wanted,
+                               ctx,
+                               sd);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("get_nt_acl_no_snum: SMB_VFS_GET_NT_ACL returned %s.\n",
+                         nt_errstr(status)));
        }
 
-       conn->params->service = -1;
+       conn_free(conn);
+       TALLOC_FREE(frame);
 
-       set_conn_connectpath(conn, "/");
+       return status;
+}
 
-       if (!smbd_vfs_init(conn)) {
-               DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
-               conn_free(conn);
+int posix_sys_acl_blob_get_file(vfs_handle_struct *handle,
+                               const struct smb_filename *smb_fname_in,
+                               TALLOC_CTX *mem_ctx,
+                               char **blob_description,
+                               DATA_BLOB *blob)
+{
+       int ret;
+       TALLOC_CTX *frame = talloc_stackframe();
+       /* Initialise this to zero, in a portable way */
+       struct smb_acl_wrapper acl_wrapper = {
+               NULL
+       };
+       struct smb_filename *smb_fname = cp_smb_filename_nostream(frame,
+                                               smb_fname_in);
+       if (smb_fname == NULL) {
                TALLOC_FREE(frame);
-               return NULL;
-        }
+               errno = ENOMEM;
+               return -1;
+       }
 
-       ZERO_STRUCT( finfo );
-       ZERO_STRUCT( fh );
+       acl_wrapper.access_acl
+               = smb_vfs_call_sys_acl_get_file(handle,
+                                               smb_fname,
+                                               SMB_ACL_TYPE_ACCESS,
+                                               frame);
 
-       finfo.fnum = FNUM_FIELD_INVALID;
-       finfo.conn = conn;
-       finfo.fh = &fh;
-       finfo.fh->fd = -1;
+       ret = smb_vfs_call_stat(handle, smb_fname);
+       if (ret == -1) {
+               TALLOC_FREE(frame);
+               return -1;
+       }
 
-       status = create_synthetic_smb_fname(frame, fname, NULL, NULL,
-                                           &finfo.fsp_name);
-       if (!NT_STATUS_IS_OK(status)) {
-               conn_free(conn);
+       if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+               acl_wrapper.default_acl
+                       = smb_vfs_call_sys_acl_get_file(handle,
+                                                       smb_fname,
+                                                       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 NULL;
+               return -1;
        }
 
-       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);
+       *blob_description = talloc_strdup(mem_ctx, "posix_acl");
+       if (!*blob_description) {
+               errno = EINVAL;
                TALLOC_FREE(frame);
-               return NULL;
+               return -1;
        }
 
-       TALLOC_FREE(finfo.fsp_name);
-       conn_free(conn);
        TALLOC_FREE(frame);
-
-       return ret_sd;
+       return 0;
 }
 
-/* Stolen shamelessly from pvfs_default_acl() in source4 :-). */
-
-NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
-                                       const char *name,
-                                       SMB_STRUCT_STAT *psbuf,
-                                       struct security_descriptor **ppdesc)
+int posix_sys_acl_blob_get_fd(vfs_handle_struct *handle,
+                             files_struct *fsp,
+                             TALLOC_CTX *mem_ctx,
+                             char **blob_description,
+                             DATA_BLOB *blob)
 {
-       struct dom_sid owner_sid, group_sid;
-       size_t size = 0;
-       struct security_ace aces[4];
-       uint32_t access_mask = 0;
-       mode_t mode = psbuf->st_ex_mode;
-       struct security_acl *new_dacl = NULL;
-       int idx = 0;
+       SMB_STRUCT_STAT sbuf;
+       TALLOC_CTX *frame;
+       struct smb_acl_wrapper acl_wrapper;
+       int ret;
 
-       DEBUG(10,("make_default_filesystem_acl: file %s mode = 0%o\n",
-               name, (int)mode ));
+       /* 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,
+                                               mem_ctx,
+                                               blob_description,
+                                               blob);
+       }
+       frame = talloc_stackframe();
 
-       uid_to_sid(&owner_sid, psbuf->st_ex_uid);
-       gid_to_sid(&group_sid, psbuf->st_ex_gid);
+       acl_wrapper.default_acl = NULL;
 
-       /*
-        We provide up to 4 ACEs
-               - Owner
-               - Group
-               - Everyone
-               - NT System
-       */
+       acl_wrapper.access_acl = smb_vfs_call_sys_acl_get_file(handle,
+                                       fsp->fsp_name,
+                                       SMB_ACL_TYPE_ACCESS,
+                                       frame);
 
-       if (mode & S_IRUSR) {
-               if (mode & S_IWUSR) {
-                       access_mask |= SEC_RIGHTS_FILE_ALL;
-               } else {
-                       access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
-               }
+       ret = smb_vfs_call_fstat(handle, fsp, &sbuf);
+       if (ret == -1) {
+               TALLOC_FREE(frame);
+               return -1;
        }
-       if (mode & S_IWUSR) {
-               access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
-       }
-
-       init_sec_ace(&aces[idx],
-                       &owner_sid,
-                       SEC_ACE_TYPE_ACCESS_ALLOWED,
-                       access_mask,
-                       0);
-       idx++;
-
-       access_mask = 0;
-       if (mode & S_IRGRP) {
-               access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
-       }
-       if (mode & S_IWGRP) {
-               /* note that delete is not granted - this matches posix behaviour */
-               access_mask |= SEC_RIGHTS_FILE_WRITE;
-       }
-       if (access_mask) {
-               init_sec_ace(&aces[idx],
-                       &group_sid,
-                       SEC_ACE_TYPE_ACCESS_ALLOWED,
-                       access_mask,
-                       0);
-               idx++;
-       }
-
-       access_mask = 0;
-       if (mode & S_IROTH) {
-               access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
-       }
-       if (mode & S_IWOTH) {
-               access_mask |= SEC_RIGHTS_FILE_WRITE;
-       }
-       if (access_mask) {
-               init_sec_ace(&aces[idx],
-                       &global_sid_World,
-                       SEC_ACE_TYPE_ACCESS_ALLOWED,
-                       access_mask,
-                       0);
-               idx++;
-       }
-
-       init_sec_ace(&aces[idx],
-                       &global_sid_System,
-                       SEC_ACE_TYPE_ACCESS_ALLOWED,
-                       SEC_RIGHTS_FILE_ALL,
-                       0);
-       idx++;
-
-       new_dacl = make_sec_acl(ctx,
-                       NT4_ACL_REVISION,
-                       idx,
-                       aces);
-
-       if (!new_dacl) {
-               return NT_STATUS_NO_MEMORY;
+
+       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;
        }
 
-       *ppdesc = make_sec_desc(ctx,
-                       SECURITY_DESCRIPTOR_REVISION_1,
-                       SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
-                       &owner_sid,
-                       &group_sid,
-                       NULL,
-                       new_dacl,
-                       &size);
-       if (!*ppdesc) {
-               return NT_STATUS_NO_MEMORY;
+       *blob_description = talloc_strdup(mem_ctx, "posix_acl");
+       if (!*blob_description) {
+               errno = EINVAL;
+               TALLOC_FREE(frame);
+               return -1;
        }
-       return NT_STATUS_OK;
+
+       TALLOC_FREE(frame);
+       return 0;
 }