diff options
-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_ */ |