summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/smbd/reply.c46
-rw-r--r--source3/smbd/smb2_setinfo.c6
2 files changed, 46 insertions, 6 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 124c6109fe..6f2f281d63 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -5960,6 +5960,47 @@ static void notify_rename(connection_struct *conn, bool is_dir,
}
/****************************************************************************
+ Returns an error if the parent directory for a filename is open in an
+ incompatible way.
+****************************************************************************/
+
+static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
+ const struct smb_filename *smb_fname_dst_in)
+{
+ char *parent_dir = NULL;
+ struct smb_filename smb_fname_parent;
+ struct file_id id;
+ files_struct *fsp = NULL;
+ int ret;
+
+ if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
+ &parent_dir, NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ ZERO_STRUCT(smb_fname_parent);
+ smb_fname_parent.base_name = parent_dir;
+
+ ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ /*
+ * We're only checking on this smbd here, mostly good
+ * enough.. and will pass tests.
+ */
+
+ id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
+ for (fsp = file_find_di_first(conn->sconn, id); fsp;
+ fsp = file_find_di_next(fsp)) {
+ if (fsp->access_mask & DELETE_ACCESS) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
Rename an open file - given an fsp.
****************************************************************************/
@@ -5980,6 +6021,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
return status;
}
+ status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* Make a copy of the dst smb_fname structs */
status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c
index e1149408d1..96b44aaf77 100644
--- a/source3/smbd/smb2_setinfo.c
+++ b/source3/smbd/smb2_setinfo.c
@@ -219,12 +219,6 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
if (file_info_level == SMB_FILE_RENAME_INFORMATION) {
/* SMB2_FILE_RENAME_INFORMATION_INTERNAL == 0xFF00 + in_file_info_class */
file_info_level = SMB2_FILE_RENAME_INFORMATION_INTERNAL;
- if (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK &&
- fsp->oplock_type != NO_OPLOCK) {
- /* No break, but error. */
- tevent_req_nterror(req, NT_STATUS_SHARING_VIOLATION);
- return tevent_req_post(req, ev);
- }
}
if (fsp->fh->fd == -1) {