mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
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 5761fa35ab
)
This commit is contained in:
parent
90a322f6d7
commit
291b02a639
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user