diff options
author | Andrew Tridgell <tridge@samba.org> | 2006-10-09 11:13:49 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:20:52 -0500 |
commit | 2338e978322510d5b6def6edac40a868e4945d2e (patch) | |
tree | f040d75a6ba906d6bfebce3ad35dd19ee588d0db /source4/ntvfs | |
parent | 0019163d85fce2e83cd3e6193479b59e88d37d98 (diff) | |
download | samba-2338e978322510d5b6def6edac40a868e4945d2e.tar.gz samba-2338e978322510d5b6def6edac40a868e4945d2e.tar.bz2 samba-2338e978322510d5b6def6edac40a868e4945d2e.zip |
r19199: split out the xattr NTACL code into a separate part of the posix
backend, allowing other ACL backends to be added. The xattr backend is
still the default backend
(This used to be commit 90f044e63b12d32228310c7529382198bd7e6dfe)
Diffstat (limited to 'source4/ntvfs')
-rw-r--r-- | source4/ntvfs/posix/config.mk | 11 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_acl.c | 108 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_acl_xattr.c | 105 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_xattr.c | 18 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.c | 3 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.h | 11 |
6 files changed, 207 insertions, 49 deletions
diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index 2835fc4575..57ee5b4090 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -1,4 +1,14 @@ ################################################ +# 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] SUBSYSTEM = ntvfs @@ -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 ################################################ diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c index 62ef196977..1a3fc184de 100644 --- a/source4/ntvfs/posix/pvfs_acl.c +++ b/source4/ntvfs/posix/pvfs_acl.c @@ -27,6 +27,60 @@ #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 index 0000000000..705f525507 --- /dev/null +++ b/source4/ntvfs/posix/pvfs_acl_xattr.c @@ -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); +} diff --git a/source4/ntvfs/posix/pvfs_xattr.c b/source4/ntvfs/posix/pvfs_xattr.c index e5b4fdaa90..ab2f3fef6c 100644 --- a/source4/ntvfs/posix/pvfs_xattr.c +++ b/source4/ntvfs/posix/pvfs_xattr.c @@ -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; diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index 975649eeb5..ad47908b6e 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -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) diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 82a3d34172..4a81088d1c 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -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_ */ |