diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-11-18 03:31:35 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:05:57 -0500 |
commit | bc7b4abc3a85e78a73d401345265b2c022f0f04d (patch) | |
tree | 198b8203af8003f3e08c351f27425236bfd38227 | |
parent | 3c25dfe78905984da1b18a7c136f954bfcdece42 (diff) | |
download | samba-bc7b4abc3a85e78a73d401345265b2c022f0f04d.tar.gz samba-bc7b4abc3a85e78a73d401345265b2c022f0f04d.tar.bz2 samba-bc7b4abc3a85e78a73d401345265b2c022f0f04d.zip |
r3832: added NT ACL query/set to the posix NTVFS backend. The default ACL is
based on the current nttoken, which is completely wrong, but works as a start.
The ACL is stored in the xattr system.DosAcl, using a NDR encoded IDL
union with a version number to allow for future expansion.
pvfs does not yet check the ACL for file access. At the moment the ACL
is just query/set.
We also need to do some RPC work to allow the windows ACL editor to be
used. At the moment is queries the ACL fine, but displays an error
when it fails to map the SIDs via rpc.
(This used to be commit 3a1f20d874ab2d8b2a2f2485b7a705847abf1263)
-rw-r--r-- | source4/include/rpc_secdes.h | 3 | ||||
-rw-r--r-- | source4/include/structs.h | 1 | ||||
-rw-r--r-- | source4/libcli/security/security_descriptor.c | 2 | ||||
-rw-r--r-- | source4/librpc/idl/xattr.idl | 23 | ||||
-rw-r--r-- | source4/ntvfs/posix/config.mk | 1 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_acl.c | 193 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_qfileinfo.c | 10 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_setfileinfo.c | 3 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_xattr.c | 43 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.c | 3 | ||||
-rw-r--r-- | source4/ntvfs/unixuid/vfs_unixuid.c | 4 |
11 files changed, 281 insertions, 5 deletions
diff --git a/source4/include/rpc_secdes.h b/source4/include/rpc_secdes.h index 9cf899a59a..1a7e56974a 100644 --- a/source4/include/rpc_secdes.h +++ b/source4/include/rpc_secdes.h @@ -54,11 +54,12 @@ typedef struct security_descriptor SEC_DESC; /* Don't know what this means. */ -/* security information */ +/* security information flags used in query_secdesc and set_secdesc */ #define OWNER_SECURITY_INFORMATION 0x00000001 #define GROUP_SECURITY_INFORMATION 0x00000002 #define DACL_SECURITY_INFORMATION 0x00000004 #define SACL_SECURITY_INFORMATION 0x00000008 + /* Extra W2K flags. */ #define UNPROTECTED_SACL_SECURITY_INFORMATION 0x10000000 #define UNPROTECTED_DACL_SECURITY_INFORMATION 0x20000000 diff --git a/source4/include/structs.h b/source4/include/structs.h index 61749111d9..d2f86e2e8a 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -112,6 +112,7 @@ struct file_info; struct xattr_DosEAs; struct xattr_DosStreams; +struct xattr_DosAcl; struct test_join; diff --git a/source4/libcli/security/security_descriptor.c b/source4/libcli/security/security_descriptor.c index 671174a824..00857de1c6 100644 --- a/source4/libcli/security/security_descriptor.c +++ b/source4/libcli/security/security_descriptor.c @@ -108,7 +108,7 @@ NTSTATUS security_check_dacl(struct security_token *st, add an ACE to the DACL of a security_descriptor */ NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd, - struct security_ace *ace) + const struct security_ace *ace) { if (sd->dacl == NULL) { sd->dacl = talloc_p(sd, struct security_acl); diff --git a/source4/librpc/idl/xattr.idl b/source4/librpc/idl/xattr.idl index 703fb2325b..153561ac1a 100644 --- a/source4/librpc/idl/xattr.idl +++ b/source4/librpc/idl/xattr.idl @@ -8,6 +8,9 @@ about a file in a architecture independent manner */ +[ + depends(security) +] interface xattr { const string XATTR_DOSATTRIB_NAME = "user.DosAttrib"; @@ -72,4 +75,24 @@ interface xattr uint32 num_streams; [size_is(num_streams)] xattr_DosStream *streams; } xattr_DosStreams; + + + /* we store the NT ACL a DosAcl xattr. It is versioned so we + can later add other acl attribs (such as posix acl + mapping) + + we put this xattr in the security namespace to ensure that + only trusted users can write to the ACL + */ + const string XATTR_DOSACL_NAME = "security.DosAcl"; + + typedef union { + [case(1)] security_descriptor *sd; + } xattr_DosAclInfo; + + typedef [public] struct { + uint16 version; + [switch_is(version)] xattr_DosAclInfo info; + } xattr_DosAcl; + } diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index 1d33d8b381..7999a32741 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -28,6 +28,7 @@ ADD_OBJ_FILES = \ ntvfs/posix/pvfs_ioctl.o \ ntvfs/posix/pvfs_xattr.o \ ntvfs/posix/pvfs_streams.o \ + ntvfs/posix/pvfs_acl.o \ ntvfs/common/opendb.o \ ntvfs/common/brlock.o # End MODULE ntvfs_posix diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c new file mode 100644 index 0000000000..2885604311 --- /dev/null +++ b/source4/ntvfs/posix/pvfs_acl.c @@ -0,0 +1,193 @@ +/* + Unix SMB/CIFS implementation. + + POSIX NTVFS backend - ACL support + + Copyright (C) Andrew Tridgell 2004 + + 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 "auth/auth.h" +#include "system/filesys.h" +#include "vfs_posix.h" +#include "librpc/gen_ndr/ndr_xattr.h" + + +/* + setup a default ACL for a file +*/ +static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, int fd, + struct xattr_DosAcl *acl) +{ + struct security_descriptor *sd; + struct nt_user_token *token = req->session->session_info->nt_user_token; + int i; + + sd = security_descriptor_initialise(req); + if (sd == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* nasty hack to get a reasonable sec desc - should be based on posix uid/gid + and perms */ + if (token->num_sids > 0) { + sd->owner_sid = token->user_sids[0]; + } + if (token->num_sids > 1) { + sd->group_sid = token->user_sids[1]; + } + + for (i=0;i<token->num_sids;i++) { + struct security_ace ace; + NTSTATUS status; + + ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; + ace.flags = 0; + ace.access_mask = SEC_RIGHTS_FULL_CTRL | STD_RIGHT_ALL_ACCESS; + ace.trustee = *token->user_sids[i]; + + status = security_descriptor_dacl_add(sd, &ace); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + acl->version = 1; + acl->info.sd = sd; + + return NT_STATUS_OK; +} + + +/* + omit any security_descriptor elements not specified in the given + secinfo flags +*/ +static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags) +{ + if (!(secinfo_flags & OWNER_SECURITY_INFORMATION)) { + sd->owner_sid = NULL; + } + if (!(secinfo_flags & GROUP_SECURITY_INFORMATION)) { + sd->group_sid = NULL; + } + if (!(secinfo_flags & DACL_SECURITY_INFORMATION)) { + sd->dacl = NULL; + } + if (!(secinfo_flags & SACL_SECURITY_INFORMATION)) { + sd->sacl = NULL; + } +} + +/* + answer a setfileinfo for an ACL +*/ +NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, int fd, + union smb_setfileinfo *info) +{ + struct xattr_DosAcl *acl; + uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags; + struct security_descriptor *new_sd, *sd; + NTSTATUS status; + + acl = talloc_p(req, struct xattr_DosAcl); + if (acl == NULL) { + return NT_STATUS_NO_MEMORY; + } + + 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); + } + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + switch (acl->version) { + case 1: + sd = acl->info.sd; + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + new_sd = info->set_secdesc.in.sd; + + /* only set the elements that have been specified */ + if (secinfo_flags & OWNER_SECURITY_INFORMATION) { + sd->owner_sid = new_sd->owner_sid; + } + if (secinfo_flags & GROUP_SECURITY_INFORMATION) { + sd->group_sid = new_sd->group_sid; + } + if (secinfo_flags & DACL_SECURITY_INFORMATION) { + sd->dacl = new_sd->dacl; + } + if (secinfo_flags & SACL_SECURITY_INFORMATION) { + sd->sacl = new_sd->sacl; + } + + status = pvfs_acl_save(pvfs, name, fd, acl); + + return status; +} + + +/* + answer a fileinfo query for the ACL +*/ +NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, int fd, + union smb_fileinfo *info) +{ + struct xattr_DosAcl *acl; + NTSTATUS status; + struct security_descriptor *sd; + + acl = talloc_p(req, struct xattr_DosAcl); + if (acl == NULL) { + return NT_STATUS_NO_MEMORY; + } + + 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); + } + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + switch (acl->version) { + case 1: + sd = acl->info.sd; + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags); + + info->query_secdesc.out.sd = sd; + + return NT_STATUS_OK; +} + diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index f6e1288b1d..fe53b0a415 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -56,7 +56,8 @@ static NTSTATUS pvfs_query_all_eas(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* approximately map a struct pvfs_filename to a generic fileinfo struct */ -static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, +static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, + struct smbsrv_request *req, struct pvfs_filename *name, union smb_fileinfo *info, int fd) { @@ -91,7 +92,7 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; case RAW_FILEINFO_ALL_EAS: - return pvfs_query_all_eas(pvfs, mem_ctx, name, fd, &info->all_eas.out); + return pvfs_query_all_eas(pvfs, req, name, fd, &info->all_eas.out); case RAW_FILEINFO_IS_NAME_VALID: return NT_STATUS_OK; @@ -149,7 +150,7 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, case RAW_FILEINFO_STREAM_INFO: case RAW_FILEINFO_STREAM_INFORMATION: - return pvfs_stream_information(pvfs, mem_ctx, name, fd, &info->stream_info.out); + return pvfs_stream_information(pvfs, req, name, fd, &info->stream_info.out); case RAW_FILEINFO_COMPRESSION_INFO: case RAW_FILEINFO_COMPRESSION_INFORMATION: @@ -194,6 +195,9 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, info->attribute_tag_information.out.attrib = name->dos.attrib; info->attribute_tag_information.out.reparse_tag = 0; return NT_STATUS_OK; + + case RAW_FILEINFO_SEC_DESC: + return pvfs_acl_query(pvfs, req, name, fd, info); } return NT_STATUS_INVALID_LEVEL; diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index d31bcac337..cc1b69b8ea 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -301,6 +301,9 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, return pvfs_setfileinfo_rename(pvfs, req, h->name, &info->rename_information.in); + case RAW_SFILEINFO_SEC_DESC: + return pvfs_acl_set(pvfs, req, h->name, h->fd, info); + default: return NT_STATUS_INVALID_LEVEL; } diff --git a/source4/ntvfs/posix/pvfs_xattr.c b/source4/ntvfs/posix/pvfs_xattr.c index 6984c2d284..a50348ef04 100644 --- a/source4/ntvfs/posix/pvfs_xattr.c +++ b/source4/ntvfs/posix/pvfs_xattr.c @@ -348,6 +348,49 @@ NTSTATUS pvfs_streams_save(struct pvfs_state *pvfs, struct pvfs_filename *name, (ndr_push_flags_fn_t)ndr_push_xattr_DosStreams); } + +/* + load the current ACL from extended attributes +*/ +NTSTATUS pvfs_acl_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, + struct xattr_DosAcl *acl) +{ + NTSTATUS status; + ZERO_STRUCTP(acl); + if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) { + return NT_STATUS_OK; + } + status = pvfs_xattr_ndr_load(pvfs, acl, name->full_name, fd, + XATTR_DOSACL_NAME, + acl, + (ndr_pull_flags_fn_t)ndr_pull_xattr_DosAcl); + return status; +} + +/* + save the acl for a file into filesystem xattr +*/ +NTSTATUS pvfs_acl_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, + struct xattr_DosAcl *acl) +{ + NTSTATUS status; + void *privs; + + if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) { + return NT_STATUS_OK; + } + + /* 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_DOSACL_NAME, + acl, + (ndr_push_flags_fn_t)ndr_push_xattr_DosAcl); + talloc_free(privs); + return status; +} + /* create a zero length xattr with the given name */ diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index e02bd7aa32..e19b0739c7 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -65,6 +65,9 @@ static void pvfs_setup_options(struct pvfs_state *pvfs) if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { pvfs->fs_attribs |= FS_ATTR_NAMED_STREAMS; } + if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { + pvfs->fs_attribs |= FS_ATTR_PERSISTANT_ACLS; + } } diff --git a/source4/ntvfs/unixuid/vfs_unixuid.c b/source4/ntvfs/unixuid/vfs_unixuid.c index 4520df59fc..674ce3e5cf 100644 --- a/source4/ntvfs/unixuid/vfs_unixuid.c +++ b/source4/ntvfs/unixuid/vfs_unixuid.c @@ -294,6 +294,10 @@ static NTSTATUS unixuid_setup_security(struct ntvfs_module_context *ntvfs, struct unix_sec_ctx *newsec; NTSTATUS status; + if (req->session == NULL) { + return NT_STATUS_ACCESS_DENIED; + } + *sec = save_unix_security(req); if (*sec == NULL) { return NT_STATUS_NO_MEMORY; |