static int fake_acls_stat(vfs_handle_struct *handle,
struct smb_filename *smb_fname)
{
- int ret = -1;
- struct in_pathref_data *prd = NULL;
- struct smb_filename *smb_fname_cp = NULL;
- struct files_struct *fsp = NULL;
- NTSTATUS status;
-
- SMB_VFS_HANDLE_GET_DATA(handle,
- prd,
- struct in_pathref_data,
- return -1);
-
- ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
- if (ret != 0) {
- return ret;
- }
-
- if (smb_fname->fsp != NULL) {
- ret = fake_acls_fuidgid(handle,
- metadata_fsp(smb_fname->fsp),
- &smb_fname->st.st_ex_uid,
- &smb_fname->st.st_ex_gid);
- return ret;
- }
-
- /*
- * Ensure openat_pathref_fsp() can't recurse into
- * fake_acls_stat(). openat_pathref_fsp() doesn't care about
- * the uid/gid values, it only wants a valid/invalid stat
- * answer and we know smb_fname exists as the
- * SMB_VFS_NEXT_STAT() returned zero above.
- */
- if (prd->calling_pathref_fsp) {
- return 0;
- }
-
- if (fsp_get_pathref_fd(handle->conn->cwd_fsp) == -1) {
- /*
- * No tcon around, fail as if we don't have the EAs
- */
- return 0;
- }
+ struct stat_ex st = {};
+ int ret;
- /*
- * openat_pathref_fsp() expects a talloc'ed smb_filename. stat
- * can be passed a struct from the stack. Make a talloc'ed
- * copy so openat_pathref_fsp() can add its destructor.
- */
- smb_fname_cp = cp_smb_filename(talloc_tos(), smb_fname);
- if (smb_fname_cp == NULL) {
- errno = ENOMEM;
+ ret = fake_acls_fstatat(
+ handle, handle->conn->cwd_fsp, smb_fname, &st, 0);
+ if (ret == -1) {
return -1;
}
- /* Recursion guard. */
- prd->calling_pathref_fsp = true;
-
- status = openat_pathref_fsp(handle->conn->cwd_fsp, smb_fname_cp);
-
- /* End recursion guard. */
- prd->calling_pathref_fsp = false;
-
- if (!NT_STATUS_IS_OK(status)) {
- /*
- * Ignore errors here. We know the path exists (the
- * SMB_VFS_NEXT_STAT() above succeeded. So being
- * unable to open a pathref fsp can be due to a range
- * of errors (startup path beginning with '/' for
- * example, path = ".." when enumerating a
- * directory. Just treat this the same way as the path
- * not having the FAKE_UID or FAKE_GID EA's
- * present. For the test purposes of this module (fake
- * NT ACLs from windows clients) this is close enough.
- * Just report for debugging purposes.
- */
- DBG_DEBUG("Unable to get pathref fsp on %s. "
- "Error %s\n",
- smb_fname_str_dbg(smb_fname_cp),
- nt_errstr(status));
- TALLOC_FREE(smb_fname_cp);
- return 0;
- }
- fsp = smb_fname_cp->fsp;
-
- ret = fake_acls_fuidgid(handle,
- fsp,
- &smb_fname->st.st_ex_uid,
- &smb_fname->st.st_ex_gid);
- TALLOC_FREE(smb_fname_cp);
- return ret;
+ smb_fname->st = st;
+ return 0;
}
static int fake_acls_lstat(vfs_handle_struct *handle,
struct smb_filename *smb_fname)
{
- int ret = -1;
- struct in_pathref_data *prd = NULL;
- struct smb_filename *smb_fname_base = NULL;
- SMB_STRUCT_STAT sbuf = {0};
- NTSTATUS status;
-
- SMB_VFS_HANDLE_GET_DATA(handle,
- prd,
- struct in_pathref_data,
- return -1);
-
- ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
- if (ret != 0) {
- return ret;
- }
-
- /*
- * Ensure synthetic_pathref() can't recurse into
- * fake_acls_lstat(). synthetic_pathref() doesn't care about
- * the uid/gid values, it only wants a valid/invalid stat
- * answer and we know smb_fname exists as the
- * SMB_VFS_NEXT_LSTAT() returned zero above.
- */
- if (prd->calling_pathref_fsp) {
- return 0;
- }
+ struct stat_ex st = {};
+ int ret;
- /* Recursion guard. */
- prd->calling_pathref_fsp = true;
- status = synthetic_pathref(talloc_tos(),
- handle->conn->cwd_fsp,
- smb_fname->base_name,
- NULL,
- &sbuf,
- smb_fname->twrp,
- 0, /* we want stat, not lstat. */
- &smb_fname_base);
- /* End recursion guard. */
- prd->calling_pathref_fsp = false;
- if (NT_STATUS_IS_OK(status)) {
- /*
- * This isn't quite right (calling fgetxattr not
- * lgetxattr), but for the test purposes of this
- * module (fake NT ACLs from windows clients), it is
- * close enough. We removed the l*xattr functions
- * because linux doesn't support using them, but we
- * could fake them in xattr_tdb if we really wanted
- * to. We ignore errors because the link might not
- * point anywhere */
- fake_acls_fuidgid(handle,
- smb_fname_base->fsp,
- &smb_fname->st.st_ex_uid,
- &smb_fname->st.st_ex_gid);
+ ret = fake_acls_fstatat(handle,
+ handle->conn->cwd_fsp,
+ smb_fname,
+ &st,
+ AT_SYMLINK_NOFOLLOW);
+ if (ret == -1) {
+ return -1;
}
- TALLOC_FREE(smb_fname_base);
- return ret;
+ smb_fname->st = st;
+ return 0;
}
static int fake_acls_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)