r4448: - fixed access_mask checking on acl set
authorAndrew Tridgell <tridge@samba.org>
Fri, 31 Dec 2004 08:56:32 +0000 (08:56 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:07:51 +0000 (13:07 -0500)
- 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
source4/ntvfs/posix/pvfs_open.c
source4/ntvfs/posix/pvfs_qfileinfo.c
source4/ntvfs/posix/pvfs_setfileinfo.c

index 4cc22b0918d934d755bcf333cedada1b36275a67..ce5f3a248b21f75c6f7133e4ca7726e6edc4863d 100644 (file)
@@ -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;
index 3941414cd8fda0476b5de97ab9999fcb0da6ff4a..c59f2d22e98d48063e0e95573c0486a2c2d50e03 100644 (file)
@@ -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 {
index efd95e76749794c08debf5e5b8e4c019e7495528..463574c8cffb786b56762041ebf252db007e2874 100644 (file)
@@ -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;
index fbc71dc9d4fffdeef801ffbc5212f92f26bf23e6..7144f37a14d88d24216754b910b0b709379a6dba 100644 (file)
 /*
   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;