static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle, const char *path, uint32_t access_mask, struct security_descriptor **pp_parent_desc) { char *parent_name = NULL; struct security_descriptor *parent_desc = NULL; uint32_t access_granted = 0; NTSTATUS status; if (!parent_dirname(talloc_tos(), path, &parent_name, NULL)) { return NT_STATUS_NO_MEMORY; } status = get_nt_acl_internal(handle, NULL, parent_name, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), &parent_desc); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("check_parent_acl_common: get_nt_acl_internal " "on directory %s for " "path %s returned %s\n", parent_name, path, nt_errstr(status) )); return status; } status = smb1_file_se_access_check(handle->conn, parent_desc, handle->conn->server_info->ptok, access_mask, &access_granted); if(!NT_STATUS_IS_OK(status)) { DEBUG(10,("check_parent_acl_common: access check " "on directory %s for " "path %s for mask 0x%x returned %s\n", parent_name, path, access_mask, nt_errstr(status) )); return status; } if (pp_parent_desc) { *pp_parent_desc = parent_desc; } return NT_STATUS_OK; }
static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd) { NTSTATUS status; DATA_BLOB blob; struct security_descriptor *pdesc_next = NULL; uint8_t hash[XATTR_SD_HASH_SIZE]; if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } /* 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)) { /* 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), &nc_psd); if (!NT_STATUS_IS_OK(status)) { return status; } /* This is safe as nc_psd is discarded at fn exit. */ if (security_info_sent & OWNER_SECURITY_INFORMATION) { nc_psd->owner_sid = psd->owner_sid; } security_info_sent |= OWNER_SECURITY_INFORMATION; if (security_info_sent & GROUP_SECURITY_INFORMATION) { nc_psd->group_sid = psd->group_sid; } security_info_sent |= GROUP_SECURITY_INFORMATION; if (security_info_sent & DACL_SECURITY_INFORMATION) { 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; psd = nc_psd; } status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); if (!NT_STATUS_IS_OK(status)) { return status; } /* Get the full underlying sd, then hash. */ status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, HASH_SECURITY_INFO, &pdesc_next); if (!NT_STATUS_IS_OK(status)) { return status; } status = hash_sd_sha256(pdesc_next, hash); if (!NT_STATUS_IS_OK(status)) { return status; } if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash); store_acl_blob_fsp(handle, fsp, &blob); return NT_STATUS_OK; }
static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle, const char *name, uint32_t security_info, struct security_descriptor **ppdesc) { return get_nt_acl_internal(handle, NULL, name, security_info, ppdesc); }
static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info, struct security_descriptor **ppdesc) { return get_nt_acl_internal(handle, fsp, NULL, security_info, ppdesc); }
static int open_acl_common(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { uint32_t access_granted = 0; struct security_descriptor *pdesc = NULL; struct security_descriptor *parent_desc = NULL; bool file_existed = true; char *fname = NULL; NTSTATUS status; if (fsp->base_fsp) { /* Stream open. Base filename open already did the ACL check. */ DEBUG(10,("open_acl_common: stream open on %s\n", fsp_str_dbg(fsp) )); return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); } status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); if (!NT_STATUS_IS_OK(status)) { goto err; } status = get_nt_acl_internal(handle, NULL, fname, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), &pdesc); if (NT_STATUS_IS_OK(status)) { /* See if we can access it. */ status = smb1_file_se_access_check(handle->conn, pdesc, handle->conn->server_info->ptok, fsp->access_mask, &access_granted); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("open_acl_xattr: %s open " "refused with error %s\n", fsp_str_dbg(fsp), nt_errstr(status) )); goto err; } } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) { file_existed = false; /* * If O_CREAT is true then we're trying to create a file. * Check the parent directory ACL will allow this. */ if (flags & O_CREAT) { struct security_descriptor *psd = NULL; status = check_parent_acl_common(handle, fname, SEC_DIR_ADD_FILE, &parent_desc); if (!NT_STATUS_IS_OK(status)) { goto err; } /* Cache the parent security descriptor for * later use. We do have an fsp here, but to * keep the code consistent with the directory * case which doesn't, use the handle. */ /* Attach this to the conn, move from talloc_tos(). */ psd = (struct security_descriptor *)talloc_move(handle->conn, &parent_desc); if (!psd) { status = NT_STATUS_NO_MEMORY; goto err; } status = NT_STATUS_NO_MEMORY; SMB_VFS_HANDLE_SET_DATA(handle, psd, free_sd_common, struct security_descriptor *, goto err); status = NT_STATUS_OK; } } DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for " "%s returned %s\n", fsp_str_dbg(fsp), nt_errstr(status) )); fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); return fsp->fh->fd; err: errno = map_errno_from_nt_status(status); return -1; }
static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *orig_psd) { NTSTATUS status; DATA_BLOB blob; struct security_descriptor *pdesc_next = NULL; struct security_descriptor *psd = NULL; uint8_t hash[XATTR_SD_HASH_SIZE]; bool chown_needed = false; if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, discard_const_p(struct security_descriptor, orig_psd)); } status = get_nt_acl_internal(handle, fsp, NULL, SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL, &psd); if (!NT_STATUS_IS_OK(status)) { return status; } psd->revision = orig_psd->revision; /* All our SD's are self relative. */ psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE; if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) { if (!dom_sid_equal(orig_psd->owner_sid, psd->owner_sid)) { /* We're changing the owner. */ chown_needed = true; } psd->owner_sid = orig_psd->owner_sid; } if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) { if (!dom_sid_equal(orig_psd->group_sid, psd->group_sid)) { /* We're changing the group. */ chown_needed = true; } psd->group_sid = orig_psd->group_sid; } if (security_info_sent & SECINFO_DACL) { psd->dacl = orig_psd->dacl; psd->type |= SEC_DESC_DACL_PRESENT; } if (security_info_sent & SECINFO_SACL) { psd->sacl = orig_psd->sacl; psd->type |= SEC_DESC_SACL_PRESENT; } status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { return status; } /* We got access denied here. If we're already root, or we didn't need to do a chown, or the fsp isn't open with WRITE_OWNER access, just return. */ if (get_current_uid(handle->conn) == 0 || chown_needed == false || !(fsp->access_mask & SEC_STD_WRITE_OWNER)) { return NT_STATUS_ACCESS_DENIED; } DEBUG(10,("fset_nt_acl_common: overriding chown on file %s " "for sid %s\n", fsp_str_dbg(fsp), sid_string_tos(psd->owner_sid) )); /* Ok, we failed to chown and we have SEC_STD_WRITE_OWNER access - override. */ become_root(); status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { return status; } } /* Get the full underlying sd, then hash. */ status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, HASH_SECURITY_INFO, &pdesc_next); if (!NT_STATUS_IS_OK(status)) { return status; } status = hash_sd_sha256(pdesc_next, hash); if (!NT_STATUS_IS_OK(status)) { return status; } if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, discard_const_p(struct security_descriptor, psd)); } create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash); store_acl_blob_fsp(handle, fsp, &blob); return NT_STATUS_OK; }