summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/ntvfs/posix/config.mk11
-rw-r--r--source4/ntvfs/posix/pvfs_acl.c108
-rw-r--r--source4/ntvfs/posix/pvfs_acl_xattr.c105
-rw-r--r--source4/ntvfs/posix/pvfs_xattr.c18
-rw-r--r--source4/ntvfs/posix/vfs_posix.c3
-rw-r--r--source4/ntvfs/posix/vfs_posix.h11
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_ */