From 291b02a639aa6551ac1f59e47a78d5590d2b7f6e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 31 Dec 2004 08:56:32 +0000 Subject: r4448: - fixed access_mask checking on acl set - honor the change ownership requests of acl set, changing the underlying unix owner/group - fix the access mask on file create with SEC_FLAG_MAXIMUM_ALLOWED (This used to be commit 5761fa35ab727b51ef1b52459911bafbdd788755) --- source4/ntvfs/posix/pvfs_acl.c | 38 ++++++++++++++++++++++++++++++++-- source4/ntvfs/posix/pvfs_open.c | 7 +++++-- source4/ntvfs/posix/pvfs_qfileinfo.c | 4 ++++ source4/ntvfs/posix/pvfs_setfileinfo.c | 17 ++++++++++----- 4 files changed, 57 insertions(+), 9 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c index 4cc22b0918..ce5f3a248b 100644 --- a/source4/ntvfs/posix/pvfs_acl.c +++ b/source4/ntvfs/posix/pvfs_acl.c @@ -185,12 +185,15 @@ static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_ NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, struct smbsrv_request *req, struct pvfs_filename *name, int fd, + 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; NTSTATUS status; + uid_t uid = -1; + gid_t gid = -1; acl = talloc_p(req, struct xattr_NTACL); if (acl == NULL) { @@ -215,12 +218,28 @@ NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, new_sd = info->set_secdesc.in.sd; + uid = name->st.st_uid; + gid = name->st.st_gid; + /* only set the elements that have been specified */ - if (secinfo_flags & SECINFO_OWNER) { + if ((secinfo_flags & SECINFO_OWNER) && + !dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) { + if (!(access_mask & SEC_STD_WRITE_OWNER)) { + return NT_STATUS_ACCESS_DENIED; + } sd->owner_sid = new_sd->owner_sid; + status = sidmap_sid_to_unixuid(pvfs->sidmap, sd->owner_sid, &uid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } - if (secinfo_flags & SECINFO_GROUP) { + if ((secinfo_flags & SECINFO_GROUP) && + !dom_sid_equal(sd->group_sid, new_sd->group_sid)) { sd->group_sid = new_sd->group_sid; + status = sidmap_sid_to_unixgid(pvfs->sidmap, sd->owner_sid, &gid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } if (secinfo_flags & SECINFO_DACL) { sd->dacl = new_sd->dacl; @@ -228,9 +247,24 @@ NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, } if (secinfo_flags & SECINFO_SACL) { sd->sacl = new_sd->sacl; + if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) { + return NT_STATUS_ACCESS_DENIED; + } pvfs_translate_generic_bits(sd->sacl); } + if (uid != -1 || gid != -1) { + int ret; + if (fd == -1) { + ret = chown(name->full_name, uid, gid); + } else { + ret = fchown(fd, uid, gid); + } + if (ret == -1) { + return pvfs_map_errno(pvfs, errno); + } + } + status = pvfs_acl_save(pvfs, name, fd, acl); return status; diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3941414cd8..c59f2d22e9 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -124,7 +124,7 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; - status = pvfs_acl_set(pvfs, req, name, fd, &set); + status = pvfs_acl_set(pvfs, req, name, fd, SEC_STD_WRITE_DAC, &set); } else { /* otherwise setup an inherited acl from the parent */ status = pvfs_acl_inherit(pvfs, req, name, fd); @@ -463,9 +463,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } if (access_mask & SEC_FLAG_MAXIMUM_ALLOWED) { - access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE; + access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE | + SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL; } + access_mask |= SEC_FILE_READ_ATTRIBUTE; + if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { flags = O_RDWR; } else { diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index efd95e7674..463574c8cf 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -42,6 +42,10 @@ static uint32_t pvfs_fileinfo_access(enum smb_fileinfo_level level) needed = 0; break; + case RAW_FILEINFO_SEC_DESC: + needed = SEC_STD_READ_CONTROL; + break; + default: needed = SEC_FILE_READ_ATTRIBUTE; break; diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index fbc71dc9d4..7144f37a14 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -29,11 +29,11 @@ /* determine what access bits are needed for a call */ -static uint32_t pvfs_setfileinfo_access(enum smb_setfileinfo_level level) +static uint32_t pvfs_setfileinfo_access(union smb_setfileinfo *info) { uint32_t needed; - switch (level) { + switch (info->generic.level) { case RAW_SFILEINFO_EA_SET: needed = SEC_FILE_WRITE_EA; break; @@ -51,6 +51,13 @@ static uint32_t pvfs_setfileinfo_access(enum smb_setfileinfo_level level) needed = 0; break; + case RAW_SFILEINFO_SEC_DESC: + needed = 0; + if (info->set_secdesc.in.secinfo_flags & (SECINFO_DACL|SECINFO_SACL)) { + needed |= SEC_STD_WRITE_DAC; + } + break; + default: needed = SEC_FILE_WRITE_ATTRIBUTE; break; @@ -248,7 +255,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, h = f->handle; - access_needed = pvfs_setfileinfo_access(info->generic.level); + access_needed = pvfs_setfileinfo_access(info); if ((f->access_mask & access_needed) != access_needed) { return NT_STATUS_ACCESS_DENIED; } @@ -358,7 +365,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, &info->rename_information.in); case RAW_SFILEINFO_SEC_DESC: - return pvfs_acl_set(pvfs, req, h->name, h->fd, info); + return pvfs_acl_set(pvfs, req, h->name, h->fd, f->access_mask, info); default: return NT_STATUS_INVALID_LEVEL; @@ -442,7 +449,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - access_needed = pvfs_setfileinfo_access(info->generic.level); + access_needed = pvfs_setfileinfo_access(info); status = pvfs_access_check_simple(pvfs, req, name, access_needed); if (!NT_STATUS_IS_OK(status)) { return status; -- cgit