return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
}
-NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
-{
- int ret;
- bool as_root = false;
- NTSTATUS status;
-
- if (fsp->fh->fd != -1) {
- /* Try fchown. */
- ret = SMB_VFS_FCHOWN(fsp, uid, gid);
- if (ret == 0) {
- return NT_STATUS_OK;
- }
- if (ret == -1 && errno != ENOSYS) {
- return map_nt_error_from_unix(errno);
- }
- }
-
- as_root = (geteuid() == 0);
-
- if (as_root) {
- /*
- * We are being asked to chown as root. Make
- * sure we chdir() into the path to pin it,
- * and always act using lchown to ensure we
- * don't deref any symbolic links.
- */
- char *parent_dir = NULL;
- const char *final_component = NULL;
- struct smb_filename *local_smb_fname = NULL;
- struct smb_filename parent_dir_fname = {0};
- struct smb_filename *saved_dir_fname = NULL;
-
- saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
- if (!saved_dir_fname) {
- status = map_nt_error_from_unix(errno);
- DEBUG(0,("vfs_chown_fsp: failed to get "
- "current working directory. Error was %s\n",
- strerror(errno)));
- return status;
- }
-
- if (!parent_dirname(talloc_tos(),
- fsp->fsp_name->base_name,
- &parent_dir,
- &final_component)) {
- return NT_STATUS_NO_MEMORY;
- }
-
- parent_dir_fname = (struct smb_filename) {
- .base_name = parent_dir,
- .flags = fsp->fsp_name->flags
- };
-
- /* cd into the parent dir to pin it. */
- ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
- if (ret == -1) {
- return map_nt_error_from_unix(errno);
- }
-
- local_smb_fname = synthetic_smb_fname(talloc_tos(),
- final_component,
- NULL,
- NULL,
- fsp->fsp_name->flags);
- if (local_smb_fname == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
-
- /* Must use lstat here. */
- ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
- if (ret == -1) {
- status = map_nt_error_from_unix(errno);
- goto out;
- }
-
- /* Ensure it matches the fsp stat. */
- if (!check_same_stat(&local_smb_fname->st,
- &fsp->fsp_name->st)) {
- status = NT_STATUS_ACCESS_DENIED;
- goto out;
- }
-
- ret = SMB_VFS_LCHOWN(fsp->conn,
- local_smb_fname,
- uid, gid);
-
- if (ret == 0) {
- status = NT_STATUS_OK;
- } else {
- status = map_nt_error_from_unix(errno);
- }
-
- out:
-
- vfs_ChDir(fsp->conn, saved_dir_fname);
- TALLOC_FREE(local_smb_fname);
- TALLOC_FREE(saved_dir_fname);
- TALLOC_FREE(parent_dir);
-
- return status;
- }
-
- if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
- ret = SMB_VFS_LCHOWN(fsp->conn,
- fsp->fsp_name,
- uid, gid);
- } else {
- ret = SMB_VFS_CHOWN(fsp->conn,
- fsp->fsp_name,
- uid, gid);
- }
-
- if (ret == 0) {
- status = NT_STATUS_OK;
- } else {
- status = map_nt_error_from_unix(errno);
- }
- return status;
-}
-
int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname)
{