empty access mask is only denied on SMB2
[kai/samba.git] / source4 / ntvfs / posix / pvfs_acl.c
index e38f2c9ecb2180851db736f4451a0c8db83788da..d479f1e2ee0e452ec48243d3a6db4ec7d9e14a68 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "auth/auth.h"
-#include "system/filesys.h"
 #include "vfs_posix.h"
-#include "librpc/gen_ndr/ndr_xattr.h"
+#include "librpc/gen_ndr/xattr.h"
+#include "libcli/security/security.h"
+#include "param/param.h"
+
+
+/* the list of currently registered ACL backends */
+static struct pvfs_acl_backend {
+       const struct pvfs_acl_ops *ops;
+} *backends = NULL;
+static int num_backends;
+
+/*
+  register a pvfs acl backend. 
+
+  The 'name' can be later used by other backends to find the operations
+  structure for this backend.  
+*/
+NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
+{
+       struct pvfs_acl_ops *new_ops;
+
+       if (pvfs_acl_backend_byname(ops->name) != NULL) {
+               DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));
+               return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
+
+       backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);
+       NT_STATUS_HAVE_NO_MEMORY(backends);
+
+       new_ops = talloc_memdup(backends, ops, sizeof(*ops));
+       new_ops->name = talloc_strdup(new_ops, ops->name);
+
+       backends[num_backends].ops = new_ops;
+
+       num_backends++;
+
+       DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
+
+       return NT_STATUS_OK;
+}
+
+
+/*
+  return the operations structure for a named backend
+*/
+const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
+{
+       int i;
+
+       for (i=0;i<num_backends;i++) {
+               if (strcmp(backends[i].ops->name, name) == 0) {
+                       return backends[i].ops;
+               }
+       }
+
+       return NULL;
+}
+
+NTSTATUS pvfs_acl_init(struct loadparm_context *lp_ctx)
+{
+       static bool initialized = false;
+       extern NTSTATUS pvfs_acl_nfs4_init(void);
+       extern NTSTATUS pvfs_acl_xattr_init(void);
+       init_module_fn static_init[] = { STATIC_pvfs_acl_MODULES };
+       init_module_fn *shared_init;
+
+       if (initialized) return NT_STATUS_OK;
+       initialized = true;
+
+       shared_init = load_samba_modules(NULL, lp_ctx, "pvfs_acl");
+
+       run_init_functions(static_init);
+       run_init_functions(shared_init);
+
+       talloc_free(shared_init);
+
+       return NT_STATUS_OK;
+}
 
 
 /*
@@ -52,6 +127,8 @@ static void pvfs_translate_generic_bits(struct security_acl *acl)
 {
        unsigned i;
 
+       if (!acl) return;
+
        for (i=0;i<acl->num_aces;i++) {
                struct security_ace *ace = &acl->aces[i];
                ace->access_mask = pvfs_translate_mask(ace->access_mask);
@@ -63,29 +140,50 @@ static void pvfs_translate_generic_bits(struct security_acl *acl)
   setup a default ACL for a file
 */
 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
-                                struct smbsrv_request *req,
+                                struct ntvfs_request *req,
                                 struct pvfs_filename *name, int fd, 
-                                struct xattr_NTACL *acl)
+                                struct security_descriptor **psd)
 {
        struct security_descriptor *sd;
        NTSTATUS status;
        struct security_ace ace;
        mode_t mode;
+       struct id_mapping *ids;
+       struct composite_context *ctx;
 
-       sd = security_descriptor_initialise(req);
-       if (sd == NULL) {
+       *psd = security_descriptor_initialise(req);
+       if (*psd == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
+       sd = *psd;
 
-       status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-       status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
+       ids = talloc_zero_array(sd, struct id_mapping, 2);
+       NT_STATUS_HAVE_NO_MEMORY(ids);
 
+       ids[0].unixid = talloc(ids, struct unixid);
+       NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
+
+       ids[0].unixid->id = name->st.st_uid;
+       ids[0].unixid->type = ID_TYPE_UID;
+       ids[0].sid = NULL;
+
+       ids[1].unixid = talloc(ids, struct unixid);
+       NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
+
+       ids[1].unixid->id = name->st.st_gid;
+       ids[1].unixid->type = ID_TYPE_GID;
+       ids[1].sid = NULL;
+
+       ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
+       NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+       status = wbc_xids_to_sids_recv(ctx, &ids);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       sd->owner_sid = talloc_steal(sd, ids[0].sid);
+       sd->group_sid = talloc_steal(sd, ids[1].sid);
+
+       talloc_free(ids);
        sd->type |= SEC_DESC_DACL_PRESENT;
 
        mode = name->st.st_mode;
@@ -152,9 +250,6 @@ static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
        ace.access_mask = SEC_RIGHTS_FILE_ALL;
        security_descriptor_dacl_add(sd, &ace);
        
-       acl->version = 1;
-       acl->info.sd = sd;
-
        return NT_STATUS_OK;
 }
                                 
@@ -183,83 +278,111 @@ static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_
   answer a setfileinfo for an ACL
 */
 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, 
-                     struct smbsrv_request *req,
+                     struct ntvfs_request *req,
                      struct pvfs_filename *name, int fd, 
                      uint32_t access_mask,
                      union smb_setfileinfo *info)
 {
-       struct xattr_NTACL *acl;
        uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
        struct security_descriptor *new_sd, *sd, orig_sd;
-       NTSTATUS status;
-       uid_t uid = -1;
-       gid_t gid = -1;
+       NTSTATUS status = NT_STATUS_NOT_FOUND;
+       uid_t old_uid = -1;
+       gid_t old_gid = -1;
+       uid_t new_uid = -1;
+       gid_t new_gid = -1;
+       struct id_mapping *ids;
+       struct composite_context *ctx;
 
-       acl = talloc_p(req, struct xattr_NTACL);
-       if (acl == NULL) {
-               return NT_STATUS_NO_MEMORY;
+       if (pvfs->acl_ops != NULL) {
+               status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
        }
-
-       status = pvfs_acl_load(pvfs, name, fd, acl);
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
-               status = pvfs_default_acl(pvfs, req, name, fd, acl);
+               status = pvfs_default_acl(pvfs, req, name, fd, &sd);
        }
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       switch (acl->version) {
-       case 1:
-               sd = acl->info.sd;
-               break;
-       default:
-               return NT_STATUS_INVALID_ACL;
-       }
+       ids = talloc(req, struct id_mapping);
+       NT_STATUS_HAVE_NO_MEMORY(ids);
+       ids->unixid = NULL;
+       ids->sid = NULL;
+       ids->status = NT_STATUS_NONE_MAPPED;
 
        new_sd = info->set_secdesc.in.sd;
        orig_sd = *sd;
 
-       uid = name->st.st_uid;
-       gid = name->st.st_gid;
+       old_uid = name->st.st_uid;
+       old_gid = name->st.st_gid;
 
        /* only set the elements that have been specified */
-       if ((secinfo_flags & SECINFO_OWNER) && 
-           !dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
+       if (secinfo_flags & SECINFO_OWNER) {
                if (!(access_mask & SEC_STD_WRITE_OWNER)) {
                        return NT_STATUS_ACCESS_DENIED;
                }
-               sd->owner_sid = new_sd->owner_sid;
-               status = sidmap_sid_to_unixuid(pvfs->sidmap, sd->owner_sid, &uid);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
+               if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
+                       ids->sid = new_sd->owner_sid;
+                       ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
+                       NT_STATUS_HAVE_NO_MEMORY(ctx);
+                       status = wbc_sids_to_xids_recv(ctx, &ids);
+                       NT_STATUS_NOT_OK_RETURN(status);
+
+                       if (ids->unixid->type == ID_TYPE_BOTH ||
+                           ids->unixid->type == ID_TYPE_UID) {
+                               new_uid = ids->unixid->id;
+                       }
                }
+               sd->owner_sid = new_sd->owner_sid;
        }
-       if ((secinfo_flags & SECINFO_GROUP) &&
-           !dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
-               sd->group_sid = new_sd->group_sid;
-               status = sidmap_sid_to_unixgid(pvfs->sidmap, sd->owner_sid, &gid);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
+       if (secinfo_flags & SECINFO_GROUP) {
+               if (!(access_mask & SEC_STD_WRITE_OWNER)) {
+                       return NT_STATUS_ACCESS_DENIED;
                }
+               if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
+                       ids->sid = new_sd->group_sid;
+                       ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
+                       NT_STATUS_HAVE_NO_MEMORY(ctx);
+                       status = wbc_sids_to_xids_recv(ctx, &ids);
+                       NT_STATUS_NOT_OK_RETURN(status);
+
+                       if (ids->unixid->type == ID_TYPE_BOTH ||
+                           ids->unixid->type == ID_TYPE_GID) {
+                               new_gid = ids->unixid->id;
+                       }
+
+               }
+               sd->group_sid = new_sd->group_sid;
        }
        if (secinfo_flags & SECINFO_DACL) {
+               if (!(access_mask & SEC_STD_WRITE_DAC)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
                sd->dacl = new_sd->dacl;
                pvfs_translate_generic_bits(sd->dacl);
        }
        if (secinfo_flags & SECINFO_SACL) {
-               sd->sacl = new_sd->sacl;
                if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
                        return NT_STATUS_ACCESS_DENIED;
                }
+               sd->sacl = new_sd->sacl;
                pvfs_translate_generic_bits(sd->sacl);
        }
 
-       if (uid != -1 || gid != -1) {
+       if (new_uid == old_uid) {
+               new_uid = -1;
+       }
+
+       if (new_gid == old_gid) {
+               new_gid = -1;
+       }
+
+       /* if there's something to change try it */
+       if (new_uid != -1 || new_gid != -1) {
                int ret;
                if (fd == -1) {
-                       ret = chown(name->full_name, uid, gid);
+                       ret = chown(name->full_name, new_uid, new_gid);
                } else {
-                       ret = fchown(fd, uid, gid);
+                       ret = fchown(fd, new_uid, new_gid);
                }
                if (ret == -1) {
                        return pvfs_map_errno(pvfs, errno);
@@ -269,8 +392,8 @@ NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
        /* we avoid saving if the sd is the same. This means when clients
           copy files and end up copying the default sd that we don't
           needlessly use xattrs */
-       if (!security_descriptor_equal(sd, &orig_sd)) {
-               status = pvfs_acl_save(pvfs, name, fd, acl);
+       if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
+               status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
        }
 
        return status;
@@ -281,35 +404,23 @@ NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
   answer a fileinfo query for the ACL
 */
 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 
-                       struct smbsrv_request *req,
+                       struct ntvfs_request *req,
                        struct pvfs_filename *name, int fd, 
                        union smb_fileinfo *info)
 {
-       struct xattr_NTACL *acl;
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_NOT_FOUND;
        struct security_descriptor *sd;
 
-       acl = talloc_p(req, struct xattr_NTACL);
-       if (acl == NULL) {
-               return NT_STATUS_NO_MEMORY;
+       if (pvfs->acl_ops) {
+               status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
        }
-
-       status = pvfs_acl_load(pvfs, name, fd, acl);
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
-               status = pvfs_default_acl(pvfs, req, name, fd, acl);
+               status = pvfs_default_acl(pvfs, req, name, fd, &sd);
        }
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       switch (acl->version) {
-       case 1:
-               sd = acl->info.sd;
-               break;
-       default:
-               return NT_STATUS_INVALID_ACL;
-       }
-
        normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
 
        info->query_secdesc.out.sd = sd;
@@ -318,6 +429,25 @@ NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
 }
 
 
+/*
+  check the read only bit against any of the write access bits
+*/
+static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
+{
+       if ((pvfs->flags & PVFS_FLAG_READONLY) &&
+           (access_mask & (SEC_FILE_WRITE_DATA |
+                           SEC_FILE_APPEND_DATA | 
+                           SEC_FILE_WRITE_EA | 
+                           SEC_FILE_WRITE_ATTRIBUTE | 
+                           SEC_STD_DELETE | 
+                           SEC_STD_WRITE_DAC | 
+                           SEC_STD_WRITE_OWNER | 
+                           SEC_DIR_DELETE_CHILD))) {
+               return true;
+       }
+       return false;
+}
+
 /*
   default access check function based on unix permissions
   doing this saves on building a full security descriptor
@@ -325,15 +455,21 @@ NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
   specific NT ACL
 */
 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 
-                               struct smbsrv_request *req,
+                               struct ntvfs_request *req,
                                struct pvfs_filename *name,
                                uint32_t *access_mask)
 {
        uid_t uid = geteuid();
        uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
 
+       if (pvfs_read_only(pvfs, *access_mask)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        /* owner and root get extra permissions */
-       if (uid == 0 || uid == name->st.st_uid) {
+       if (uid == 0) {
+               max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;
+       } else if (uid == name->st.st_uid) {
                max_bits |= SEC_STD_ALL;
        }
 
@@ -342,11 +478,19 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
                return NT_STATUS_OK;
        }
 
+       if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        if (*access_mask & ~max_bits) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       *access_mask |= SEC_FILE_READ_ATTRIBUTE;
+       if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
+               /* on SMB, this bit is always granted, even if not
+                  asked for */
+               *access_mask |= SEC_FILE_READ_ATTRIBUTE;
+       }
 
        return NT_STATUS_OK;
 }
@@ -358,20 +502,36 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
   *access_mask is modified with the access actually granted
 */
 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
-                          struct smbsrv_request *req,
+                          struct ntvfs_request *req,
                           struct pvfs_filename *name,
                           uint32_t *access_mask)
 {
-       struct security_token *token = req->session->session_info->security_token;
+       struct security_token *token = req->session_info->security_token;
        struct xattr_NTACL *acl;
        NTSTATUS status;
        struct security_descriptor *sd;
 
-       acl = talloc_p(req, struct xattr_NTACL);
+       /* on SMB2 a blank access mask is always denied */
+       if (pvfs->ntvfs->ctx->protocol == PROTOCOL_SMB2 &&
+           *access_mask == 0) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (pvfs_read_only(pvfs, *access_mask)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       acl = talloc(req, struct xattr_NTACL);
        if (acl == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
+       /* expand the generic access bits to file specific bits */
+       *access_mask = pvfs_translate_mask(*access_mask);
+       if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
+               *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
+       }
+
        status = pvfs_acl_load(pvfs, name, -1, acl);
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
                talloc_free(acl);
@@ -389,16 +549,14 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
                return NT_STATUS_INVALID_ACL;
        }
 
-       /* expand the generic access bits to file specific bits */
-       *access_mask = pvfs_translate_mask(*access_mask);
-
-       *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
-
        /* check the acl against the required access mask */
        status = sec_access_check(sd, token, *access_mask, access_mask);
 
-       /* this bit is always granted, even if not asked for */
-       *access_mask |= SEC_FILE_READ_ATTRIBUTE;
+       if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
+               /* on SMB, this bit is always granted, even if not
+                  asked for */
+               *access_mask |= SEC_FILE_READ_ATTRIBUTE;
+       }
 
        talloc_free(acl);
        
@@ -411,7 +569,7 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
   do not take or return an access check mask
 */
 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
-                                 struct smbsrv_request *req,
+                                 struct ntvfs_request *req,
                                  struct pvfs_filename *name,
                                  uint32_t access_needed)
 {
@@ -425,7 +583,7 @@ NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
   access check for creating a new file/directory
 */
 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
-                                 struct smbsrv_request *req,
+                                 struct ntvfs_request *req,
                                  struct pvfs_filename *name,
                                  uint32_t *access_mask)
 {
@@ -453,7 +611,7 @@ NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
   access check for creating a new file/directory - no access mask supplied
 */
 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs, 
-                                 struct smbsrv_request *req,
+                                 struct ntvfs_request *req,
                                  struct pvfs_filename *name,
                                  uint32_t access_mask)
 {
@@ -472,24 +630,24 @@ NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
 /*
   determine if an ACE is inheritable
 */
-static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
+static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
                                 const struct security_ace *ace,
-                                BOOL container)
+                                bool container)
 {
        if (!container) {
                return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
        }
 
        if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
-               return True;
+               return true;
        }
 
        if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
            !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
-               return True;
+               return true;
        }
 
-       return False;
+       return false;
 }
 
 /*
@@ -500,7 +658,7 @@ static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
                                      struct security_descriptor *parent_sd,
                                      struct security_descriptor *sd,
-                                     BOOL container)
+                                     bool container)
 {
        int i;
        
@@ -579,7 +737,7 @@ static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
   as the default ACL applies anyway
 */
 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
-                         struct smbsrv_request *req,
+                         struct ntvfs_request *req,
                          struct pvfs_filename *name,
                          int fd)
 {
@@ -587,7 +745,9 @@ NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
        NTSTATUS status;
        struct pvfs_filename *parent;
        struct security_descriptor *parent_sd, *sd;
-       BOOL container;
+       bool container;
+       struct id_mapping *ids;
+       struct composite_context *ctx;
 
        /* form the parents path */
        status = pvfs_resolve_parent(pvfs, req, name, &parent);
@@ -595,7 +755,7 @@ NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
                return status;
        }
 
-       acl = talloc_p(req, struct xattr_NTACL);
+       acl = talloc(req, struct xattr_NTACL);
        if (acl == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -629,18 +789,35 @@ NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-       status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
+       ids = talloc_array(sd, struct id_mapping, 2);
+       NT_STATUS_HAVE_NO_MEMORY(ids);
+
+       ids[0].unixid = talloc(ids, struct unixid);
+       NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
+       ids[0].unixid->id = name->st.st_uid;
+       ids[0].unixid->type = ID_TYPE_UID;
+       ids[0].sid = NULL;
+       ids[0].status = NT_STATUS_NONE_MAPPED;
+
+       ids[1].unixid = talloc(ids, struct unixid);
+       NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
+       ids[1].unixid->id = name->st.st_gid;
+       ids[1].unixid->type = ID_TYPE_GID;
+       ids[1].sid = NULL;
+       ids[1].status = NT_STATUS_NONE_MAPPED;
+
+       ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
+       NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+       status = wbc_xids_to_sids_recv(ctx, &ids);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       sd->owner_sid = talloc_steal(sd, ids[0].sid);
+       sd->group_sid = talloc_steal(sd, ids[1].sid);
 
        sd->type |= SEC_DESC_DACL_PRESENT;
 
-       container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
+       container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
 
        /* fill in the aces from the parent */
        status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
@@ -660,3 +837,15 @@ NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
        
        return status;
 }
+
+/*
+  return the maximum allowed access mask
+*/
+NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs, 
+                                    struct ntvfs_request *req,
+                                    struct pvfs_filename *name,
+                                    uint32_t *maximal_access)
+{
+       *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
+       return pvfs_access_check(pvfs, req, name, maximal_access);
+}