r19199: split out the xattr NTACL code into a separate part of the posix
authorAndrew Tridgell <tridge@samba.org>
Mon, 9 Oct 2006 11:13:49 +0000 (11:13 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:20:52 +0000 (14:20 -0500)
backend, allowing other ACL backends to be added. The xattr backend is
still the default backend
(This used to be commit 90f044e63b12d32228310c7529382198bd7e6dfe)

source4/ntvfs/posix/config.mk
source4/ntvfs/posix/pvfs_acl.c
source4/ntvfs/posix/pvfs_acl_xattr.c [new file with mode: 0644]
source4/ntvfs/posix/pvfs_xattr.c
source4/ntvfs/posix/vfs_posix.c
source4/ntvfs/posix/vfs_posix.h

index 2835fc457587bdcc85b122f81ea72b701dc9cdbb..57ee5b40906b9bbc57fe5f007931bd22ff390e82 100644 (file)
@@ -1,3 +1,13 @@
+################################################
+# Start MODULE pvfs_acl_xattr
+[MODULE::pvfs_acl_xattr]
+INIT_FUNCTION = pvfs_acl_xattr_init 
+SUBSYSTEM = ntvfs
+OBJ_FILES = \
+               pvfs_acl_xattr.o
+# End MODULE pvfs_acl_xattr
+################################################
+
 ################################################
 # Start MODULE ntvfs_posix
 [MODULE::ntvfs_posix]
@@ -32,6 +42,7 @@ OBJ_FILES = \
                pvfs_notify.o \
                xattr_system.o \
                xattr_tdb.o
+PRIVATE_DEPENDENCIES = pvfs_acl_xattr
 PUBLIC_DEPENDENCIES = NDR_XATTR WRAP_XATTR BLKID ntvfs_common MESSAGING
 # End MODULE ntvfs_posix
 ################################################
index 62ef19697732089560348d7d21ab1c0c077b093b..1a3fc184def1fbe667550b0d77b679833f62774e 100644 (file)
 #include "libcli/security/security.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.  
+*/
+_PUBLIC_ 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
+*/
+_PUBLIC_ 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;
+}
+
+
 /*
   map a single access_mask from generic to specific bits for files/dirs
 */
@@ -67,17 +121,18 @@ static void pvfs_translate_generic_bits(struct security_acl *acl)
 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
                                 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;
 
-       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)) {
@@ -154,9 +209,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;
 }
                                 
@@ -190,36 +242,24 @@ NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
                      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;
+       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;
 
-       acl = talloc(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;
-       }
-
        new_sd = info->set_secdesc.in.sd;
        orig_sd = *sd;
 
@@ -286,8 +326,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;
@@ -302,31 +342,19 @@ NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
                        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(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;
diff --git a/source4/ntvfs/posix/pvfs_acl_xattr.c b/source4/ntvfs/posix/pvfs_acl_xattr.c
new file mode 100644 (file)
index 0000000..705f525
--- /dev/null
@@ -0,0 +1,105 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   POSIX NTVFS backend - NT ACLs in xattrs
+
+   Copyright (C) Andrew Tridgell 2006
+
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+*/
+
+#include "includes.h"
+#include "vfs_posix.h"
+#include "lib/util/unix_privs.h"
+#include "librpc/gen_ndr/ndr_xattr.h"
+
+/*
+  load the current ACL from extended attributes
+*/
+static NTSTATUS pvfs_acl_load_xattr(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
+                                   TALLOC_CTX *mem_ctx,
+                                   struct security_descriptor **sd)
+{
+       NTSTATUS status;
+       struct xattr_NTACL *acl;
+
+       if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+               return NT_STATUS_NOT_FOUND;
+       }
+
+       acl = talloc_zero(mem_ctx, struct xattr_NTACL);
+       NT_STATUS_HAVE_NO_MEMORY(acl);
+
+       status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name, fd, 
+                                    XATTR_NTACL_NAME,
+                                    acl, 
+                                    (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(acl);
+               return status;
+       }
+
+       if (acl->version != 1) {
+               talloc_free(acl);
+               return NT_STATUS_INVALID_ACL;
+       }
+       
+       *sd = talloc_steal(mem_ctx, acl->info.sd);
+
+       return NT_STATUS_OK;
+}
+
+/*
+  save the acl for a file into filesystem xattr
+*/
+static NTSTATUS pvfs_acl_save_xattr(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
+                                   struct security_descriptor *sd)
+{
+       NTSTATUS status;
+       void *privs;
+       struct xattr_NTACL acl;
+
+       if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
+               return NT_STATUS_OK;
+       }
+
+       acl.version = 1;
+       acl.info.sd = sd;
+
+       /* this xattr is in the "system" namespace, so we need
+          admin privileges to set it */
+       privs = root_privileges();
+       status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd, 
+                                    XATTR_NTACL_NAME, 
+                                    &acl, 
+                                    (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
+       talloc_free(privs);
+       return status;
+}
+
+
+/*
+  initialise pvfs acl xattr backend
+*/
+NTSTATUS pvfs_acl_xattr_init(void)
+{
+       struct pvfs_acl_ops ops = {
+               .name = "xattr",
+               .acl_load = pvfs_acl_load_xattr,
+               .acl_save = pvfs_acl_save_xattr
+       };
+       return pvfs_acl_register(&ops);
+}
index e5b4fdaa905fff85297d6508682cbe502b810189..ab2f3fef6c5927054ec643e4bb279d02708c5274 100644 (file)
@@ -101,10 +101,10 @@ NTSTATUS pvfs_xattr_unlink_hook(struct pvfs_state *pvfs, const char *fname)
 /*
   load a NDR structure from a xattr
 */
-static NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
-                                   TALLOC_CTX *mem_ctx,
-                                   const char *fname, int fd, const char *attr_name,
-                                   void *p, ndr_pull_flags_fn_t pull_fn)
+NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
+                            TALLOC_CTX *mem_ctx,
+                            const char *fname, int fd, const char *attr_name,
+                            void *p, void *pull_fn)
 {
        NTSTATUS status;
        DATA_BLOB blob;
@@ -116,7 +116,7 @@ static NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
        }
 
        /* pull the blob */
-       status = ndr_pull_struct_blob(&blob, mem_ctx, p, pull_fn);
+       status = ndr_pull_struct_blob(&blob, mem_ctx, p, (ndr_pull_flags_fn_t)pull_fn);
 
        data_blob_free(&blob);
 
@@ -126,15 +126,15 @@ static NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
 /*
   save a NDR structure into a xattr
 */
-static NTSTATUS pvfs_xattr_ndr_save(struct pvfs_state *pvfs,
-                                   const char *fname, int fd, const char *attr_name, 
-                                   void *p, ndr_push_flags_fn_t push_fn)
+NTSTATUS pvfs_xattr_ndr_save(struct pvfs_state *pvfs,
+                            const char *fname, int fd, const char *attr_name, 
+                            void *p, void *push_fn)
 {
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
        DATA_BLOB blob;
        NTSTATUS status;
 
-       status = ndr_push_struct_blob(&blob, mem_ctx, p, push_fn);
+       status = ndr_push_struct_blob(&blob, mem_ctx, p, (ndr_push_flags_fn_t)push_fn);
        if (!NT_STATUS_IS_OK(status)) {
                talloc_free(mem_ctx);
                return status;
index 975649eeb5a74f88abcf52ee96392009d6377c1d..ad47908b6e8e5640cd7a2872ce1b5544e3d1cd5d 100644 (file)
@@ -113,6 +113,9 @@ static void pvfs_setup_options(struct pvfs_state *pvfs)
        if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
                pvfs_xattr_probe(pvfs);
        }
+
+       /* enable an ACL backend */
+       pvfs->acl_ops = pvfs_acl_backend_byname(share_string_option(scfg, PVFS_ACL, "xattr"));
 }
 
 static int pvfs_state_destructor(struct pvfs_state *pvfs)
index 82a3d341725779c0d640db1c657621fb134ad956..4a81088d1ca08b09b9be1704bc2a8b9b88150f04 100644 (file)
@@ -83,6 +83,9 @@ struct pvfs_state {
                const struct dom_sid *creator_owner;
                const struct dom_sid *creator_group;            
        } sid_cache;
+
+       /* the acl backend */
+       const struct pvfs_acl_ops *acl_ops;
 };
 
 /* this is the basic information needed about a file from the filesystem */
@@ -220,6 +223,7 @@ enum pvfs_wait_notice {PVFS_WAIT_EVENT, PVFS_WAIT_TIMEOUT, PVFS_WAIT_CANCEL};
 #define PVFS_SHARE_DELAY               "posix:sharedelay"
 #define PVFS_ALLOCATION_ROUNDING       "posix:allocationrounding"
 #define PVFS_SEARCH_INACTIVITY         "posix:searchinactivity"
+#define PVFS_ACL                       "posix:acl"
 
 #define PVFS_XATTR_DEFAULT                     True
 #define PVFS_FAKE_OPLOCKS_DEFAULT              False
@@ -227,6 +231,13 @@ enum pvfs_wait_notice {PVFS_WAIT_EVENT, PVFS_WAIT_TIMEOUT, PVFS_WAIT_CANCEL};
 #define PVFS_ALLOCATION_ROUNDING_DEFAULT       512
 #define PVFS_SEARCH_INACTIVITY_DEFAULT         300
 
+struct pvfs_acl_ops {
+       const char *name;
+       NTSTATUS (*acl_load)(struct pvfs_state *, struct pvfs_filename *, int , TALLOC_CTX *, 
+                            struct security_descriptor **);
+       NTSTATUS (*acl_save)(struct pvfs_state *, struct pvfs_filename *, int , struct security_descriptor *);
+};
+
 #include "ntvfs/posix/vfs_posix_proto.h"
 
 #endif /* _VFS_POSIX_H_ */