s3-auth Rename NT_USER_TOKEN user_sids -> sids
[idra/samba.git] / source3 / modules / vfs_acl_common.c
index 1eec44808377621c41637d27be91112fab634fec..e759dc2df3f3b1e82d9b19229fe426c7733377b9 100644 (file)
@@ -19,6 +19,8 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "../librpc/gen_ndr/ndr_security.h"
+
 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
                        DATA_BLOB *pblob,
                        uint16_t hash_type,
@@ -34,10 +36,10 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
                        files_struct *fsp,
                        DATA_BLOB *pblob);
 
-#define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
-                               GROUP_SECURITY_INFORMATION | \
-                               DACL_SECURITY_INFORMATION | \
-                               SACL_SECURITY_INFORMATION)
+#define HASH_SECURITY_INFO (SECINFO_OWNER | \
+                               SECINFO_GROUP | \
+                               SECINFO_DACL | \
+                               SECINFO_SACL)
 
 /*******************************************************************
  Hash a security descriptor.
@@ -77,7 +79,7 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
        enum ndr_err_code ndr_err;
        size_t sd_size;
 
-       ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
+       ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
                        (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -88,7 +90,7 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
 
        switch (xacl.version) {
                case 2:
-                       *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
+                       *ppdesc = make_sec_desc(ctx, SD_REVISION,
                                        xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
                                        xacl.info.sd_hs2->sd->owner_sid,
                                        xacl.info.sd_hs2->sd->group_sid,
@@ -100,7 +102,7 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
                        memset(hash, '\0', XATTR_SD_HASH_SIZE);
                        break;
                case 3:
-                       *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
+                       *ppdesc = make_sec_desc(ctx, SD_REVISION,
                                        xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
                                        xacl.info.sd_hs3->sd->owner_sid,
                                        xacl.info.sd_hs3->sd->group_sid,
@@ -144,7 +146,7 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
        memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
 
        ndr_err = ndr_push_struct_blob(
-                       pblob, ctx, NULL, &xacl,
+                       pblob, ctx, &xacl,
                        (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -169,7 +171,7 @@ static void add_directory_inheritable_components(vfs_handle_struct *handle,
        struct connection_struct *conn = handle->conn;
        int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
        struct smb_filename smb_fname;
-       enum security_ace_type acl_type;
+       enum security_ace_type acltype;
        uint32_t access_mask;
        mode_t dir_mode;
        mode_t file_mode;
@@ -203,30 +205,30 @@ static void add_directory_inheritable_components(vfs_handle_struct *handle,
                memcpy(new_ace_list, psd->dacl->aces,
                        num_aces * sizeof(struct security_ace));
        }
-       access_mask = map_canon_ace_perms(SNUM(conn), &acl_type,
+       access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
                                mode & 0700, false);
 
        init_sec_ace(&new_ace_list[num_aces],
                        &global_sid_Creator_Owner,
-                       acl_type,
+                       acltype,
                        access_mask,
                        SEC_ACE_FLAG_CONTAINER_INHERIT|
                                SEC_ACE_FLAG_OBJECT_INHERIT|
                                SEC_ACE_FLAG_INHERIT_ONLY);
-       access_mask = map_canon_ace_perms(SNUM(conn), &acl_type,
+       access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
                                (mode << 3) & 0700, false);
        init_sec_ace(&new_ace_list[num_aces+1],
                        &global_sid_Creator_Group,
-                       acl_type,
+                       acltype,
                        access_mask,
                        SEC_ACE_FLAG_CONTAINER_INHERIT|
                                SEC_ACE_FLAG_OBJECT_INHERIT|
                                SEC_ACE_FLAG_INHERIT_ONLY);
-       access_mask = map_canon_ace_perms(SNUM(conn), &acl_type,
+       access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
                                (mode << 6) & 0700, false);
        init_sec_ace(&new_ace_list[num_aces+2],
                        &global_sid_World,
-                       acl_type,
+                       acltype,
                        access_mask,
                        SEC_ACE_FLAG_CONTAINER_INHERIT|
                                SEC_ACE_FLAG_OBJECT_INHERIT|
@@ -249,7 +251,7 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
 {
        DATA_BLOB blob;
        NTSTATUS status;
-       uint16_t hash_type;
+       uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
        uint8_t hash[XATTR_SD_HASH_SIZE];
        uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
        struct security_descriptor *psd = NULL;
@@ -369,16 +371,16 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                }
        }
 
-       if (!(security_info & OWNER_SECURITY_INFORMATION)) {
+       if (!(security_info & SECINFO_OWNER)) {
                psd->owner_sid = NULL;
        }
-       if (!(security_info & GROUP_SECURITY_INFORMATION)) {
+       if (!(security_info & SECINFO_GROUP)) {
                psd->group_sid = NULL;
        }
-       if (!(security_info & DACL_SECURITY_INFORMATION)) {
+       if (!(security_info & SECINFO_DACL)) {
                psd->dacl = NULL;
        }
-       if (!(security_info & SACL_SECURITY_INFORMATION)) {
+       if (!(security_info & SECINFO_SACL)) {
                psd->sacl = NULL;
        }
 
@@ -420,8 +422,8 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
                        &psd,
                        &size,
                        parent_desc,
-                       &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
-                       &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
+                       &handle->conn->server_info->ptok->sids[PRIMARY_USER_SID_INDEX],
+                       &handle->conn->server_info->ptok->sids[PRIMARY_GROUP_SID_INDEX],
                        is_directory);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -434,9 +436,9 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
        }
 
        return SMB_VFS_FSET_NT_ACL(fsp,
-                               (OWNER_SECURITY_INFORMATION |
-                                GROUP_SECURITY_INFORMATION |
-                                DACL_SECURITY_INFORMATION),
+                               (SECINFO_OWNER |
+                                SECINFO_GROUP |
+                                SECINFO_DACL),
                                psd);
 }
 
@@ -457,9 +459,9 @@ static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
        status = get_nt_acl_internal(handle,
                                        NULL,
                                        parent_name,
-                                       (OWNER_SECURITY_INFORMATION |
-                                        GROUP_SECURITY_INFORMATION |
-                                        DACL_SECURITY_INFORMATION),
+                                       (SECINFO_OWNER |
+                                        SECINFO_GROUP |
+                                        SECINFO_DACL),
                                        &parent_desc);
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -471,8 +473,12 @@ static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
                        nt_errstr(status) ));
                return status;
        }
-       status = smb1_file_se_access_check(parent_desc,
-                                       handle->conn->server_info->ptok,
+       if (pp_parent_desc) {
+               *pp_parent_desc = parent_desc;
+       }
+       status = smb1_file_se_access_check(handle->conn,
+                                       parent_desc,
+                                       get_current_nttok(handle->conn),
                                        access_mask,
                                        &access_granted);
        if(!NT_STATUS_IS_OK(status)) {
@@ -485,9 +491,6 @@ static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle,
                        nt_errstr(status) ));
                return status;
        }
-       if (pp_parent_desc) {
-               *pp_parent_desc = parent_desc;
-       }
        return NT_STATUS_OK;
 }
 
@@ -529,14 +532,15 @@ static int open_acl_common(vfs_handle_struct *handle,
        status = get_nt_acl_internal(handle,
                                NULL,
                                fname,
-                               (OWNER_SECURITY_INFORMATION |
-                                GROUP_SECURITY_INFORMATION |
-                                DACL_SECURITY_INFORMATION),
+                               (SECINFO_OWNER |
+                                SECINFO_GROUP |
+                                SECINFO_DACL),
                                &pdesc);
         if (NT_STATUS_IS_OK(status)) {
                /* See if we can access it. */
-               status = smb1_file_se_access_check(pdesc,
-                                       handle->conn->server_info->ptok,
+               status = smb1_file_se_access_check(handle->conn,
+                                       pdesc,
+                                       get_current_nttok(handle->conn),
                                        fsp->access_mask,
                                        &access_granted);
                if (!NT_STATUS_IS_OK(status)) {
@@ -674,20 +678,20 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
 
         /* Ensure we have OWNER/GROUP/DACL set. */
 
-       if ((security_info_sent & (OWNER_SECURITY_INFORMATION|
-                               GROUP_SECURITY_INFORMATION|
-                               DACL_SECURITY_INFORMATION)) !=
-                               (OWNER_SECURITY_INFORMATION|
-                                GROUP_SECURITY_INFORMATION|
-                                DACL_SECURITY_INFORMATION)) {
+       if ((security_info_sent & (SECINFO_OWNER|
+                               SECINFO_GROUP|
+                               SECINFO_DACL)) !=
+                               (SECINFO_OWNER|
+                                SECINFO_GROUP|
+                                SECINFO_DACL)) {
                /* No we don't - read from the existing SD. */
                struct security_descriptor *nc_psd = NULL;
 
                status = get_nt_acl_internal(handle, fsp,
                                NULL,
-                               (OWNER_SECURITY_INFORMATION|
-                                GROUP_SECURITY_INFORMATION|
-                                DACL_SECURITY_INFORMATION),
+                               (SECINFO_OWNER|
+                                SECINFO_GROUP|
+                                SECINFO_DACL),
                                &nc_psd);
 
                if (!NT_STATUS_IS_OK(status)) {
@@ -695,23 +699,23 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
                }
 
                /* This is safe as nc_psd is discarded at fn exit. */
-               if (security_info_sent & OWNER_SECURITY_INFORMATION) {
+               if (security_info_sent & SECINFO_OWNER) {
                        nc_psd->owner_sid = psd->owner_sid;
                }
-               security_info_sent |= OWNER_SECURITY_INFORMATION;
+               security_info_sent |= SECINFO_OWNER;
 
-               if (security_info_sent & GROUP_SECURITY_INFORMATION) {
+               if (security_info_sent & SECINFO_GROUP) {
                        nc_psd->group_sid = psd->group_sid;
                }
-               security_info_sent |= GROUP_SECURITY_INFORMATION;
+               security_info_sent |= SECINFO_GROUP;
 
-               if (security_info_sent & DACL_SECURITY_INFORMATION) {
+               if (security_info_sent & SECINFO_DACL) {
                        nc_psd->dacl = dup_sec_acl(talloc_tos(), psd->dacl);
                        if (nc_psd->dacl == NULL) {
                                return NT_STATUS_NO_MEMORY;
                        }
                }
-               security_info_sent |= DACL_SECURITY_INFORMATION;
+               security_info_sent |= SECINFO_DACL;
                psd = nc_psd;
        }
 
@@ -760,6 +764,108 @@ static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle,
        return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
 }
 
+static int acl_common_remove_object(vfs_handle_struct *handle,
+                                       const char *path,
+                                       bool is_directory)
+{
+       connection_struct *conn = handle->conn;
+       struct file_id id;
+       files_struct *fsp = NULL;
+       int ret = 0;
+       char *parent_dir = NULL;
+       const char *final_component = NULL;
+       struct smb_filename local_fname;
+       int saved_errno = 0;
+
+       if (!parent_dirname(talloc_tos(), path,
+                       &parent_dir, &final_component)) {
+               saved_errno = ENOMEM;
+               goto out;
+       }
+
+       DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
+               is_directory ? "directory" : "file",
+               parent_dir, final_component ));
+
+       /* cd into the parent dir to pin it. */
+       ret = SMB_VFS_CHDIR(conn, parent_dir);
+       if (ret == -1) {
+               saved_errno = errno;
+               goto out;
+       }
+
+       ZERO_STRUCT(local_fname);
+       local_fname.base_name = CONST_DISCARD(char *,final_component);
+
+       /* Must use lstat here. */
+       ret = SMB_VFS_LSTAT(conn, &local_fname);
+       if (ret == -1) {
+               saved_errno = errno;
+               goto out;
+       }
+
+       /* Ensure we have this file open with DELETE access. */
+       id = vfs_file_id_from_sbuf(conn, &local_fname.st);
+       for (fsp = file_find_di_first(id); fsp; file_find_di_next(fsp)) {
+               if (fsp->access_mask & DELETE_ACCESS &&
+                               fsp->delete_on_close) {
+                       /* We did open this for delete,
+                        * allow the delete as root.
+                        */
+                       break;
+               }
+       }
+
+       if (!fsp) {
+               DEBUG(10,("acl_common_remove_object: %s %s/%s "
+                       "not an open file\n",
+                       is_directory ? "directory" : "file",
+                       parent_dir, final_component ));
+               saved_errno = EACCES;
+               goto out;
+       }
+
+       become_root();
+       if (is_directory) {
+               ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
+       } else {
+               ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
+       }
+       unbecome_root();
+
+       if (ret == -1) {
+               saved_errno = errno;
+       }
+
+  out:
+
+       TALLOC_FREE(parent_dir);
+
+       vfs_ChDir(conn, conn->connectpath);
+       if (saved_errno) {
+               errno = saved_errno;
+       }
+       return ret;
+}
+
+static int rmdir_acl_common(struct vfs_handle_struct *handle,
+                               const char *path)
+{
+       int ret;
+
+       ret = SMB_VFS_NEXT_RMDIR(handle, path);
+       if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
+               DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
+                       path,
+                       strerror(errno) ));
+               return ret;
+       }
+
+       return acl_common_remove_object(handle,
+                                       path,
+                                       true);
+}
+
 static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
                                struct smb_request *req,
                                uint16_t root_dir_fid,
@@ -771,6 +877,7 @@ static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
                                uint32_t file_attributes,
                                uint32_t oplock_request,
                                uint64_t allocation_size,
+                               uint32_t private_flags,
                                struct security_descriptor *sd,
                                struct ea_list *ea_list,
                                files_struct **result,
@@ -792,6 +899,7 @@ static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
                                        file_attributes,
                                        oplock_request,
                                        allocation_size,
+                                       private_flags,
                                        sd,
                                        ea_list,
                                        result,
@@ -857,3 +965,25 @@ static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
        /* NOTREACHED */
        return status;
 }
+
+static int unlink_acl_common(struct vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
+{
+       int ret;
+
+       ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+       if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
+               DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
+                       smb_fname->base_name,
+                       strerror(errno) ));
+               return ret;
+       }
+       /* Don't do anything fancy for streams. */
+       if (smb_fname->stream_name) {
+               return ret;
+       }
+
+       return acl_common_remove_object(handle,
+                                       smb_fname->base_name,
+                                       false);
+}