From dcb6ebc83d7b1b3bbeed323a61aeceef5b3ed4c9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Dec 2011 15:35:55 -0800 Subject: [PATCH 1/3] First part of fix for bug #8663 - deleting a symlink fails if the symlink target is outside of the share. Remove two unneeded check_name() calls. They have already been done in order to get here. --- source3/smbd/open.c | 12 ------------ 1 files changed, 0 insertions(+), 12 deletions(-) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 09716d9..ab54f28 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1624,11 +1624,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, } } - status = check_name(conn, smb_fname->base_name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (!posix_open) { new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; if (file_existed) { @@ -3649,13 +3644,6 @@ NTSTATUS create_file_default(connection_struct *conn, } } - /* All file access must go through check_name() */ - - status = check_name(conn, smb_fname->base_name); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - if (stream_name && is_ntfs_default_stream_smb_fname(smb_fname)) { int ret; smb_fname->stream_name = NULL; -- 1.7.3.1 From 9b38f665618ff11139c5695b336da93e8f500be2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Dec 2011 15:37:07 -0800 Subject: [PATCH 2/3] Second part of fix for bug #8663 - deleting a symlink fails if the symlink target is outside of the share. Ensure we use UCF_UNIX_NAME_LOOKUP flags on filename_convert() when doing a restricted set of infolevels in trans2setfilepathinfo(). --- source3/smbd/trans2.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 129ab01..6f933dd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7984,6 +7984,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } } else { char *fname = NULL; + uint32_t ucf_flags = 0; /* set path info */ if (total_params < 7) { @@ -8000,10 +8001,17 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } + if (info_level == SMB_SET_FILE_UNIX_BASIC || + info_level == SMB_SET_FILE_UNIX_INFO2 || + info_level == SMB_FILE_RENAME_INFORMATION || + info_level == SMB_POSIX_PATH_UNLINK) { + ucf_flags |= UCF_UNIX_NAME_LOOKUP; + } + status = filename_convert(req, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - 0, + ucf_flags, NULL, &smb_fname); if (!NT_STATUS_IS_OK(status)) { -- 1.7.3.1 From 68c4379d44d9c243c69783da568f58d909290d24 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 16 Dec 2011 15:50:58 -0800 Subject: [PATCH 3/3] Third part of fix for bug #8663 - deleting a symlink fails if the symlink target is outside of the share. can_access_file_acl() - we can always delete a symlink. can_delete_file_in_directory() - We don't need to do another STAT call here, we know smb_fname->st is in a valid state. smbd_check_open_rights() - we can always delete a symlink. --- source3/smbd/file_access.c | 23 +++++++++++------------ source3/smbd/open.c | 10 ++++++++++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 7485564..9f95d68 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -44,6 +44,13 @@ bool can_access_file_acl(struct connection_struct *conn, return true; } + if (access_mask == DELETE_ACCESS && + VALID_STAT(smb_fname->st) && + S_ISLNK(smb_fname->st.st_ex_mode)) { + /* We can always delete a symlink. */ + return true; + } + status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name, (SECINFO_OWNER | SECINFO_GROUP | @@ -130,18 +137,10 @@ bool can_delete_file_in_directory(connection_struct *conn, /* sticky bit means delete only by owner of file or by root or * by owner of directory. */ if (smb_fname_parent->st.st_ex_mode & S_ISVTX) { - if(SMB_VFS_STAT(conn, smb_fname) != 0) { - if (errno == ENOENT) { - /* If the file doesn't already exist then - * yes we'll be able to delete it. */ - ret = true; - goto out; - } - DEBUG(10,("can_delete_file_in_directory: can't " - "stat file %s (%s)", - smb_fname_str_dbg(smb_fname), - strerror(errno) )); - ret = false; + if (!VALID_STAT(smb_fname->st)) { + /* If the file doesn't already exist then + * yes we'll be able to delete it. */ + ret = true; goto out; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ab54f28..ce86b4c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -95,6 +95,16 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn, return NT_STATUS_OK; } + if (access_mask == DELETE_ACCESS && + VALID_STAT(smb_fname->st) && + S_ISLNK(smb_fname->st.st_ex_mode)) { + /* We can always delete a symlink. */ + DEBUG(10,("smbd_check_open_rights: not checking ACL " + "on DELETE_ACCESS on symlink %s.\n", + smb_fname_str_dbg(smb_fname) )); + return NT_STATUS_OK; + } + status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name, (SECINFO_OWNER | SECINFO_GROUP | -- 1.7.3.1