files_struct *fsp,
const SMB_STRUCT_STAT *psbuf);
+/****************************************************************************
+ Check if an open file handle or pathname is a symlink.
+****************************************************************************/
+
+static NTSTATUS refuse_symlink(connection_struct *conn,
+ const files_struct *fsp,
+ const char *name)
+{
+ SMB_STRUCT_STAT sbuf;
+ const SMB_STRUCT_STAT *pst = NULL;
+
+ if (fsp) {
+ pst = &fsp->fsp_name->st;
+ } else {
+ int ret = vfs_stat_smb_basename(conn,
+ name,
+ &sbuf);
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ pst = &sbuf;
+ }
+ if (S_ISLNK(pst->st_ex_mode)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ return NT_STATUS_OK;
+}
+
NTSTATUS check_access_fsp(const struct files_struct *fsp,
uint32_t access_mask)
{
char **names, **tmp;
size_t num_names;
ssize_t sizeret = -1;
+ NTSTATUS status;
+
+ if (pnames) {
+ *pnames = NULL;
+ }
+ *pnum_names = 0;
if (!lp_ea_support(SNUM(conn))) {
- if (pnames) {
- *pnames = NULL;
- }
- *pnum_names = 0;
+ return NT_STATUS_OK;
+ }
+
+ status = refuse_symlink(conn, fsp, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * Just return no EA's on a symlink.
+ */
return NT_STATUS_OK;
}
if (sizeret == 0) {
TALLOC_FREE(names);
- if (pnames) {
- *pnames = NULL;
- }
- *pnum_names = 0;
return NT_STATUS_OK;
}
Ensure the EA name is case insensitive by matching any existing EA name.
****************************************************************************/
-static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
+static void canonicalize_ea_name(connection_struct *conn,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ fstring unix_ea_name)
{
size_t total_ea_len;
TALLOC_CTX *mem_ctx = talloc_tos();
struct ea_list *ea_list;
- NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
+ NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
+ conn,
+ fsp,
+ smb_fname->base_name,
+ &total_ea_len,
+ &ea_list);
if (!NT_STATUS_IS_OK(status)) {
return;
}
const struct smb_filename *smb_fname, struct ea_list *ea_list)
{
NTSTATUS status;
- char *fname = NULL;
if (!lp_ea_support(SNUM(conn))) {
return NT_STATUS_EAS_NOT_SUPPORTED;
}
+ status = refuse_symlink(conn, fsp, smb_fname->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
if (!NT_STATUS_IS_OK(status)) {
return status;
return STATUS_INVALID_EA_NAME;
}
- fname = smb_fname->base_name;
-
for (;ea_list; ea_list = ea_list->next) {
int ret;
fstring unix_ea_name;
fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
fstrcat(unix_ea_name, ea_list->ea.name);
- canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
+ canonicalize_ea_name(conn,
+ fsp,
+ smb_fname,
+ unix_ea_name);
DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
} else {
DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
- unix_ea_name, fname));
- ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
+ unix_ea_name, smb_fname->base_name));
+ ret = SMB_VFS_REMOVEXATTR(conn,
+ smb_fname->base_name,
+ unix_ea_name);
}
#ifdef ENOATTR
/* Removing a non existent attribute always succeeds. */
ea_list->ea.value.data, ea_list->ea.value.length, 0);
} else {
DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
- unix_ea_name, fname));
- ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
- ea_list->ea.value.data, ea_list->ea.value.length, 0);
+ unix_ea_name, smb_fname->base_name));
+ ret = SMB_VFS_SETXATTR(conn,
+ smb_fname->base_name,
+ unix_ea_name,
+ ea_list->ea.value.data,
+ ea_list->ea.value.length,
+ 0);
}
}
struct ea_list *ea_list = NULL;
NTSTATUS ntstatus = NT_STATUS_OK;
bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
- TALLOC_CTX *ctx = talloc_tos();
struct dptr_struct *dirptr = NULL;
struct smbd_server_connection *sconn = req->sconn;
uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
}
if (req->posix_pathnames) {
- srvstr_get_path_wcard_posix(ctx,
+ srvstr_get_path_wcard_posix(talloc_tos(),
params,
req->flags2,
&directory,
&ntstatus,
&mask_contains_wcard);
} else {
- srvstr_get_path_wcard(ctx,
+ srvstr_get_path_wcard(talloc_tos(),
params,
req->flags2,
&directory,
if (backup_priv) {
become_root();
as_root = true;
- ntstatus = filename_convert_with_privilege(ctx,
+ ntstatus = filename_convert_with_privilege(talloc_tos(),
conn,
req,
directory,
&mask_contains_wcard,
&smb_dname);
} else {
- ntstatus = filename_convert(ctx, conn,
+ ntstatus = filename_convert(talloc_tos(), conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
ucf_flags,
if(p == NULL) {
/* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
if((directory[0] == '.') && (directory[1] == '\0')) {
- mask = talloc_strdup(ctx,"*");
+ mask = talloc_strdup(talloc_tos(),"*");
if (!mask) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
}
+ /* Ensure smb_dname->base_name matches. */
+ smb_dname->base_name = directory;
}
DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
}
/* Pull out the list of names. */
- ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
+ ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
if (!ea_list) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
goto out;
ntstatus = dptr_create(conn,
req,
NULL, /* fsp */
- directory,
+ smb_dname,
False,
True,
req->smbpid,
a different TRANS2 call. */
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dont_descend(ctx, SNUM(conn))));
- if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
+ directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
+ if (in_list(directory,
+ lp_dont_descend(talloc_tos(), SNUM(conn)),
+ conn->case_sensitive)) {
dont_descend = True;
+ }
p = pdata;
space_remaining = max_data_bytes;
out_of_space = True;
finished = False;
} else {
- ntstatus = get_lanman2_dir_entry(ctx,
+ ntstatus = get_lanman2_dir_entry(talloc_tos(),
conn,
dirptr,
req->flags2,
return NT_STATUS_INVALID_PARAMETER;
}
- status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
- talloc_tos(), &num_streams, &streams);
+ status = vfs_streaminfo(conn,
+ fsp,
+ smb_fname,
+ talloc_tos(),
+ &num_streams,
+ &streams);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("could not get stream info: %s\n",
uint16_t num_file_acls = 0;
uint16_t num_def_acls = 0;
+ status = refuse_symlink(conn,
+ fsp,
+ smb_fname->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
if (fsp && fsp->fh->fd != -1) {
file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
talloc_tos());
uint16_t num_def_acls;
bool valid_file_acls = True;
bool valid_def_acls = True;
+ NTSTATUS status;
if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
return NT_STATUS_INVALID_PARAMETER;
return NT_STATUS_INVALID_PARAMETER;
}
+ status = refuse_symlink(conn, fsp, smb_fname->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
(unsigned int)num_file_acls,
if (fsp && fsp->fh->fd != -1) {
ret = SMB_VFS_FCHMOD(fsp, unixmode);
} else {
- ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
+ ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
}
if (ret != 0) {
return map_nt_error_from_unix(errno);
* UNIX extensions calls must always operate
* on symlinks.
*/
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
+ ret = SMB_VFS_LCHOWN(conn, smb_fname,
set_owner, (gid_t)-1);
}
* UNIX extensions calls must always operate
* on symlinks.
*/
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
+ ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
set_grp);
}
if (ret != 0) {