diff options
Diffstat (limited to 'source4/ntvfs')
-rw-r--r-- | source4/ntvfs/posix/config.mk | 12 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_acl_nfs4.c | 163 |
2 files changed, 174 insertions, 1 deletions
diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index 57ee5b4090..ed182d9a98 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -9,6 +9,16 @@ OBJ_FILES = \ ################################################ ################################################ +# Start MODULE pvfs_acl_nfs4 +[MODULE::pvfs_acl_nfs4] +INIT_FUNCTION = pvfs_acl_nfs4_init +SUBSYSTEM = ntvfs +OBJ_FILES = \ + pvfs_acl_nfs4.o +# End MODULE pvfs_acl_nfs4 +################################################ + +################################################ # Start MODULE ntvfs_posix [MODULE::ntvfs_posix] SUBSYSTEM = ntvfs @@ -42,7 +52,7 @@ OBJ_FILES = \ pvfs_notify.o \ xattr_system.o \ xattr_tdb.o -PRIVATE_DEPENDENCIES = pvfs_acl_xattr +PRIVATE_DEPENDENCIES = pvfs_acl_xattr pvfs_acl_nfs4 PUBLIC_DEPENDENCIES = NDR_XATTR WRAP_XATTR BLKID ntvfs_common MESSAGING # End MODULE ntvfs_posix ################################################ diff --git a/source4/ntvfs/posix/pvfs_acl_nfs4.c b/source4/ntvfs/posix/pvfs_acl_nfs4.c new file mode 100644 index 0000000000..b0a329c639 --- /dev/null +++ b/source4/ntvfs/posix/pvfs_acl_nfs4.c @@ -0,0 +1,163 @@ +/* + Unix SMB/CIFS implementation. + + POSIX NTVFS backend - NT ACLs mapped to NFS4 ACLs, as per + http://www.suse.de/~agruen/nfs4acl/ + + 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_nfs4acl.h" +#include "libcli/security/security.h" + +#define ACE4_IDENTIFIER_GROUP 0x40 + +/* + load the current ACL from system.nfs4acl +*/ +static NTSTATUS pvfs_acl_load_nfs4(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, + TALLOC_CTX *mem_ctx, + struct security_descriptor **psd) +{ + NTSTATUS status; + struct nfs4acl *acl; + struct security_descriptor *sd; + int i; + + acl = talloc_zero(mem_ctx, struct nfs4acl); + NT_STATUS_HAVE_NO_MEMORY(acl); + + status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name, fd, + NFS4ACL_XATTR_NAME, + acl, ndr_pull_nfs4acl); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(acl); + return status; + } + + *psd = security_descriptor_initialise(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(*psd); + + sd = *psd; + + sd->type |= acl->a_flags; + status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid); + NT_STATUS_NOT_OK_RETURN(status); + status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid); + NT_STATUS_NOT_OK_RETURN(status); + + for (i=0;i<acl->a_count;i++) { + struct nfs4ace *a = &acl->ace[i]; + struct security_ace ace; + struct dom_sid *sid; + ace.type = a->e_type; + ace.flags = a->e_flags; + ace.access_mask = a->e_mask; + if (a->e_flags & ACE4_IDENTIFIER_GROUP) { + status = sidmap_gid_to_sid(pvfs->sidmap, sd, a->e_id, &sid); + } else { + status = sidmap_uid_to_sid(pvfs->sidmap, sd, a->e_id, &sid); + } + NT_STATUS_NOT_OK_RETURN(status); + ace.trustee = *sid; + security_descriptor_dacl_add(sd, &ace); + } + + return NT_STATUS_OK; +} + +/* + save the acl for a file into system.nfs4acl +*/ +static NTSTATUS pvfs_acl_save_nfs4(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, + struct security_descriptor *sd) +{ + NTSTATUS status; + void *privs; + struct nfs4acl acl; + int i; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(pvfs); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + acl.a_version = 0; + acl.a_flags = sd->type; + acl.a_count = sd->dacl?sd->dacl->num_aces:0; + acl.a_owner_mask = 0; + acl.a_group_mask = 0; + acl.a_other_mask = 0; + + acl.ace = talloc_array(tmp_ctx, struct nfs4ace, acl.a_count); + if (!acl.ace) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + for (i=0;i<acl.a_count;i++) { + struct nfs4ace *a = &acl.ace[i]; + struct security_ace *ace = &sd->dacl->aces[i]; + a->e_type = ace->type; + a->e_flags = ace->flags; + a->e_mask = ace->access_mask; + if (sidmap_sid_is_group(pvfs->sidmap, &ace->trustee)) { + gid_t gid; + a->e_flags |= ACE4_IDENTIFIER_GROUP; + status = sidmap_sid_to_unixgid(pvfs->sidmap, &ace->trustee, &gid); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + a->e_id = gid; + } else { + uid_t uid; + status = sidmap_sid_to_unixuid(pvfs->sidmap, &ace->trustee, &uid); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + a->e_id = uid; + } + a->e_who = ""; + } + + privs = root_privileges(); + status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd, + NFS4ACL_XATTR_NAME, + &acl, ndr_push_nfs4acl); + talloc_free(privs); + + talloc_free(tmp_ctx); + return status; +} + + +/* + initialise pvfs acl NFS4 backend +*/ +NTSTATUS pvfs_acl_nfs4_init(void) +{ + struct pvfs_acl_ops ops = { + .name = "nfs4acl", + .acl_load = pvfs_acl_load_nfs4, + .acl_save = pvfs_acl_save_nfs4 + }; + return pvfs_acl_register(&ops); +} |