From 3645f83a3c83fa3e4bf4dbacf885cc4295e7eadd Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 9 Jun 2017 13:02:49 +0200 Subject: [PATCH] s3/vfs: make SMB_VFS_OFFLOAD_WRITE_SEND offload token based Remove the source fsp argument and instead pass the offload token generated with SMB_VFS_OFFLOAD_READ_SEND/RECV. An actual offload fsctl is not implemented yet, neither in the VFS nor at the SMB ioctl layer, and returns NT_STATUS_NOT_IMPLEMENTED With these changes we now pass the copy-chunk-across-shares test. Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher --- examples/VFS/skel_opaque.c | 5 +- examples/VFS/skel_transparent.c | 7 +- .../smb2.ioctl.copy-chunk-across-shares | 2 - source3/include/vfs.h | 10 +- source3/include/vfs_macros.h | 8 +- source3/modules/offload_token.c | 90 ++++++++++++++++++ source3/modules/offload_token.h | 3 + source3/modules/vfs_btrfs.c | 46 ++++++++-- source3/modules/vfs_default.c | 48 ++++++++-- source3/modules/vfs_fruit.c | 29 ++++-- source3/modules/vfs_full_audit.c | 10 +- source3/modules/vfs_time_audit.c | 7 +- source3/smbd/smb2_ioctl_filesys.c | 9 +- source3/smbd/smb2_ioctl_network_fs.c | 92 ++----------------- source3/smbd/vfs.c | 10 +- 15 files changed, 242 insertions(+), 134 deletions(-) delete mode 100644 selftest/knownfail.d/smb2.ioctl.copy-chunk-across-shares diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index d416bf6ef53..831d0f14fce 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -585,8 +585,9 @@ struct skel_cc_state { static struct tevent_req *skel_offload_write_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t num, diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 58fd77a9d51..f813926141b 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -719,8 +719,9 @@ static void skel_offload_write_done(struct tevent_req *subreq); static struct tevent_req *skel_offload_write_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t num, @@ -737,7 +738,7 @@ static struct tevent_req *skel_offload_write_send(struct vfs_handle_struct *hand state->handle = handle; subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, state, ev, - src_fsp, src_off, + fsctl, token, transfer_offset, dest_fsp, dest_off, num, flags); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); diff --git a/selftest/knownfail.d/smb2.ioctl.copy-chunk-across-shares b/selftest/knownfail.d/smb2.ioctl.copy-chunk-across-shares deleted file mode 100644 index 4a1f859f5c3..00000000000 --- a/selftest/knownfail.d/smb2.ioctl.copy-chunk-across-shares +++ /dev/null @@ -1,2 +0,0 @@ -^samba3.smb2.ioctl.copy_chunk_across_shares -^samba3.smb2.ioctl fs_specific.copy_chunk_across_shares diff --git a/source3/include/vfs.h b/source3/include/vfs.h index c11ce51f670..1308cc2da51 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -799,8 +799,9 @@ struct vfs_fn_pointers { struct tevent_req *(*offload_write_send_fn)(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t to_copy, @@ -1379,8 +1380,9 @@ NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req, struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t num, diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 2d810d0aa80..77a2a8d37a2 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -425,10 +425,10 @@ #define SMB_VFS_NEXT_OFFLOAD_READ_RECV(req, handle, mem_ctx, token_blob) \ smb_vfs_call_offload_read_recv((req), (handle)->next, (mem_ctx), (token_blob)) -#define SMB_VFS_OFFLOAD_WRITE_SEND(conn, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num, flags) \ - smb_vfs_call_offload_write_send((conn)->vfs_handles, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num), (flags)) -#define SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num, flags) \ - smb_vfs_call_offload_write_send((handle)->next, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num), (flags)) +#define SMB_VFS_OFFLOAD_WRITE_SEND(conn, mem_ctx, ev, fsctl, token, transfer_offset, dest_fsp, dest_off, num, flags) \ + smb_vfs_call_offload_write_send((conn)->vfs_handles, (mem_ctx), (ev), (fsctl), (token), (transfer_offset), (dest_fsp), (dest_off), (num), (flags)) +#define SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev, fsctl, token, transfer_offset, dest_fsp, dest_off, num, flags) \ + smb_vfs_call_offload_write_send((handle)->next, (mem_ctx), (ev), (fsctl), (token), (transfer_offset), (dest_fsp), (dest_off), (num), (flags)) #define SMB_VFS_OFFLOAD_WRITE_RECV(conn, req, copied) \ smb_vfs_call_offload_write_recv((conn)->vfs_handles, (req), (copied)) diff --git a/source3/modules/offload_token.c b/source3/modules/offload_token.c index 2969262f48e..05528da46b5 100644 --- a/source3/modules/offload_token.c +++ b/source3/modules/offload_token.c @@ -20,6 +20,7 @@ #include "includes.h" #include "smbd/smbd.h" #include "smbd/globals.h" +#include "../libcli/security/security.h" #include "dbwrap/dbwrap.h" #include "dbwrap/dbwrap_rbt.h" #include "dbwrap/dbwrap_open.h" @@ -220,3 +221,92 @@ NTSTATUS vfs_offload_token_create_blob(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } + +NTSTATUS vfs_offload_token_check_handles(uint32_t fsctl, + files_struct *src_fsp, + files_struct *dst_fsp) +{ + if (src_fsp->vuid != dst_fsp->vuid) { + DBG_INFO("copy chunk handles not in the same session.\n"); + return NT_STATUS_ACCESS_DENIED; + } + + if (!NT_STATUS_IS_OK(src_fsp->op->status)) { + DBG_INFO("copy chunk source handle invalid: %s\n", + nt_errstr(src_fsp->op->status)); + return NT_STATUS_ACCESS_DENIED; + } + + if (!NT_STATUS_IS_OK(dst_fsp->op->status)) { + DBG_INFO("copy chunk destination handle invalid: %s\n", + nt_errstr(dst_fsp->op->status)); + return NT_STATUS_ACCESS_DENIED; + } + + if (src_fsp->deferred_close != NULL) { + DBG_INFO("copy chunk src handle with deferred close.\n"); + return NT_STATUS_ACCESS_DENIED; + } + + if (dst_fsp->deferred_close != NULL) { + DBG_INFO("copy chunk dst handle with deferred close.\n"); + return NT_STATUS_ACCESS_DENIED; + } + + if (src_fsp->is_directory) { + DBG_INFO("copy chunk no read on src directory handle (%s).\n", + smb_fname_str_dbg(src_fsp->fsp_name)); + return NT_STATUS_ACCESS_DENIED; + } + + if (dst_fsp->is_directory) { + DBG_INFO("copy chunk no read on dst directory handle (%s).\n", + smb_fname_str_dbg(dst_fsp->fsp_name)); + return NT_STATUS_ACCESS_DENIED; + } + + if (IS_IPC(src_fsp->conn) || IS_IPC(dst_fsp->conn)) { + DBG_INFO("copy chunk no access on IPC$ handle.\n"); + return NT_STATUS_ACCESS_DENIED; + } + + if (IS_PRINT(src_fsp->conn) || IS_PRINT(dst_fsp->conn)) { + DBG_INFO("copy chunk no access on PRINT handle.\n"); + return NT_STATUS_ACCESS_DENIED; + } + + /* + * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request + * The server MUST fail the request with STATUS_ACCESS_DENIED if any of + * the following are true: + * - The Open.GrantedAccess of the destination file does not include + * FILE_WRITE_DATA or FILE_APPEND_DATA. + * + * A non writable dst handle also doesn't make sense for other fsctls. + */ + if (!CHECK_WRITE(dst_fsp)) { + DBG_INFO("dest handle not writable (%s).\n", + smb_fname_str_dbg(dst_fsp->fsp_name)); + return NT_STATUS_ACCESS_DENIED; + } + /* + * - The Open.GrantedAccess of the destination file does not include + * FILE_READ_DATA, and the CtlCode is FSCTL_SRV_COPYCHUNK. + */ + if ((fsctl == FSCTL_SRV_COPYCHUNK) && !CHECK_READ_IOCTL(dst_fsp)) { + DBG_INFO("copy chunk no read on dest handle (%s).\n", + smb_fname_str_dbg(dst_fsp->fsp_name)); + return NT_STATUS_ACCESS_DENIED; + } + /* + * - The Open.GrantedAccess of the source file does not include + * FILE_READ_DATA access. + */ + if (!CHECK_READ_SMB2(src_fsp)) { + DBG_INFO("src handle not readable (%s).\n", + smb_fname_str_dbg(src_fsp->fsp_name)); + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_OK; +} diff --git a/source3/modules/offload_token.h b/source3/modules/offload_token.h index 569edcfdd17..1e8e26d476f 100644 --- a/source3/modules/offload_token.h +++ b/source3/modules/offload_token.h @@ -34,4 +34,7 @@ NTSTATUS vfs_offload_token_create_blob(TALLOC_CTX *mem_ctx, const files_struct *fsp, uint32_t fsctl, DATA_BLOB *token_blob); +NTSTATUS vfs_offload_token_check_handles(uint32_t fsctl, + files_struct *src_fsp, + files_struct *dst_fsp); #endif diff --git a/source3/modules/vfs_btrfs.c b/source3/modules/vfs_btrfs.c index 79175378efc..f310a3dfd65 100644 --- a/source3/modules/vfs_btrfs.c +++ b/source3/modules/vfs_btrfs.c @@ -206,8 +206,9 @@ static void btrfs_offload_write_done(struct tevent_req *subreq); static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t num, @@ -218,7 +219,10 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han struct btrfs_ioctl_clone_range_args cr_args; struct lock_struct src_lck; struct lock_struct dest_lck; + off_t src_off = transfer_offset; + files_struct *src_fsp = NULL; int ret; + bool handle_offload_write = true; NTSTATUS status; req = tevent_req_create(mem_ctx, &cc_state, struct btrfs_cc_state); @@ -233,16 +237,38 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han cc_state->handle = handle; + status = vfs_offload_token_db_fetch_fsp(btrfs_offload_ctx, + token, &src_fsp); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + switch (fsctl) { + case FSCTL_SRV_COPYCHUNK: + case FSCTL_SRV_COPYCHUNK_WRITE: + case FSCTL_DUP_EXTENTS_TO_FILE: + break; + + default: + handle_offload_write = false; + break; + } + if (num == 0) { /* * With a @src_length of zero, BTRFS_IOC_CLONE_RANGE clones * all data from @src_offset->EOF! This is certainly not what * the caller expects, and not what vfs_default does. */ + handle_offload_write = false; + } + + if (!handle_offload_write) { cc_state->subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, cc_state, ev, - src_fsp, - src_off, + fsctl, + token, + transfer_offset, dest_fsp, dest_off, num, flags); @@ -255,6 +281,13 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han return req; } + status = vfs_offload_token_check_handles( + fsctl, src_fsp, dest_fsp); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + status = vfs_stat_fsp(src_fsp); if (tevent_req_nterror(req, status)) { return tevent_req_post(req, ev); @@ -323,8 +356,9 @@ static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *han (unsigned long long)cr_args.dest_offset)); cc_state->subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, cc_state, ev, - src_fsp, - src_off, + fsctl, + token, + transfer_offset, dest_fsp, dest_off, num, flags); diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 9b86a905203..9add9155f12 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -1689,6 +1689,7 @@ struct vfswrap_offload_write_state { struct lock_struct read_lck; bool write_lck_locked; struct lock_struct write_lck; + DATA_BLOB *token; struct files_struct *src_fsp; off_t src_off; struct files_struct *dst_fsp; @@ -1705,8 +1706,9 @@ static struct tevent_req *vfswrap_offload_write_send( struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t to_copy, @@ -1715,10 +1717,9 @@ static struct tevent_req *vfswrap_offload_write_send( struct tevent_req *req; struct vfswrap_offload_write_state *state = NULL; size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN); + files_struct *src_fsp = NULL; NTSTATUS status; - DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy); - req = tevent_req_create(mem_ctx, &state, struct vfswrap_offload_write_state); if (req == NULL) { @@ -1738,8 +1739,8 @@ static struct tevent_req *vfswrap_offload_write_send( *state = (struct vfswrap_offload_write_state) { .ev = ev, - .src_fsp = src_fsp, - .src_off = src_off, + .token = token, + .src_off = transfer_offset, .dst_fsp = dest_fsp, .dst_off = dest_off, .to_copy = to_copy, @@ -1747,11 +1748,44 @@ static struct tevent_req *vfswrap_offload_write_send( .flags = flags, }; + switch (fsctl) { + case FSCTL_SRV_COPYCHUNK: + case FSCTL_SRV_COPYCHUNK_WRITE: + break; + + case FSCTL_OFFLOAD_WRITE: + tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED); + return tevent_req_post(req, ev); + + default: + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return tevent_req_post(req, ev); + } + + /* + * From here on we assume a copy-chunk fsctl + */ + if (to_copy == 0) { tevent_req_done(req); return tevent_req_post(req, ev); } + status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx, + token, &src_fsp); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + state->src_fsp = src_fsp; + + DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy); + + status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + state->buf = talloc_array(state, uint8_t, num); if (tevent_req_nomem(state->buf, req)) { return tevent_req_post(req, ev); @@ -1762,7 +1796,7 @@ static struct tevent_req *vfswrap_offload_write_send( return tevent_req_post(req, ev); } - if (src_fsp->fsp_name->st.st_ex_size < src_off + num) { + if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) { /* * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request * If the SourceOffset or SourceOffset + Length extends beyond diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 279366ca08c..db6324a3574 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -5485,8 +5485,9 @@ static void fruit_offload_write_done(struct tevent_req *subreq); static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t num, @@ -5496,6 +5497,8 @@ static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *han struct fruit_offload_write_state *state; NTSTATUS status; struct fruit_config_data *config; + off_t src_off = transfer_offset; + files_struct *src_fsp = NULL; off_t to_copy = num; DEBUG(10,("soff: %ju, doff: %ju, len: %ju\n", @@ -5511,9 +5514,22 @@ static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *han return NULL; } state->handle = handle; - state->src_fsp = src_fsp; state->dst_fsp = dest_fsp; + switch (fsctl) { + case FSCTL_SRV_COPYCHUNK: + case FSCTL_SRV_COPYCHUNK_WRITE: + status = vfs_offload_token_db_fetch_fsp(fruit_offload_ctx, + token, &src_fsp); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + state->src_fsp = src_fsp; + break; + default: + break; + } + /* * Check if this a OS X copyfile style copychunk request with * a requested chunk count of 0 that was translated to a @@ -5521,7 +5537,7 @@ static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *han * = dest_off = num = 0. */ if ((src_off == 0) && (dest_off == 0) && (num == 0) && - src_fsp->aapl_copyfile_supported && + src_fsp != NULL && src_fsp->aapl_copyfile_supported && dest_fsp->aapl_copyfile_supported) { status = vfs_stat_fsp(src_fsp); @@ -5536,8 +5552,9 @@ static struct tevent_req *fruit_offload_write_send(struct vfs_handle_struct *han subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev, - src_fsp, - src_off, + fsctl, + token, + transfer_offset, dest_fsp, dest_off, to_copy, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index f9d14a8e845..892cf5d7378 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -1944,8 +1944,9 @@ static NTSTATUS smb_full_audit_offload_read_recv( static struct tevent_req *smb_full_audit_offload_write_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t num, @@ -1953,8 +1954,9 @@ static struct tevent_req *smb_full_audit_offload_write_send(struct vfs_handle_st { struct tevent_req *req; - req = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev, src_fsp, - src_off, dest_fsp, dest_off, num, + req = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, mem_ctx, ev, + fsctl, token, transfer_offset, + dest_fsp, dest_off, num, flags); do_log(SMB_VFS_OP_OFFLOAD_WRITE_SEND, req, handle, ""); diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 6dc03fb7a04..cc21a476245 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -2005,8 +2005,9 @@ static void smb_time_audit_offload_write_done(struct tevent_req *subreq); static struct tevent_req *smb_time_audit_offload_write_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t num, @@ -2025,7 +2026,7 @@ static struct tevent_req *smb_time_audit_offload_write_send(struct vfs_handle_st state->handle = handle; clock_gettime_mono(&state->ts_send); subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, state, ev, - src_fsp, src_off, + fsctl, token, transfer_offset, dest_fsp, dest_off, num, flags); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); diff --git a/source3/smbd/smb2_ioctl_filesys.c b/source3/smbd/smb2_ioctl_filesys.c index 5bbeadabcb9..fa1cb93c439 100644 --- a/source3/smbd/smb2_ioctl_filesys.c +++ b/source3/smbd/smb2_ioctl_filesys.c @@ -161,7 +161,6 @@ static NTSTATUS fsctl_dup_extents_check_sparse(struct files_struct *src_fsp, struct fsctl_dup_extents_state { struct tevent_context *ev; struct connection_struct *conn; - struct files_struct *src_fsp; struct files_struct *dst_fsp; struct fsctl_dup_extents_to_file dup_extents; }; @@ -234,7 +233,6 @@ static struct tevent_req *fsctl_dup_extents_send(TALLOC_CTX *mem_ctx, tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE); return tevent_req_post(req, ev); } - state->src_fsp = src_fsp; status = fsctl_dup_extents_check_lengths(src_fsp, dst_fsp, &state->dup_extents); @@ -279,11 +277,11 @@ static void fsctl_dup_extents_offload_read_done(struct tevent_req *subreq) subreq, struct tevent_req); struct fsctl_dup_extents_state *state = tevent_req_data( req, struct fsctl_dup_extents_state); - DATA_BLOB token_blob; + DATA_BLOB token; NTSTATUS status; status = SMB_VFS_OFFLOAD_READ_RECV(subreq, state->dst_fsp->conn, - state, &token_blob); + state, &token); if (tevent_req_nterror(req, status)) { return; } @@ -292,7 +290,8 @@ static void fsctl_dup_extents_offload_read_done(struct tevent_req *subreq) subreq = SMB_VFS_OFFLOAD_WRITE_SEND(state->dst_fsp->conn, state, state->ev, - state->src_fsp, + FSCTL_DUP_EXTENTS_TO_FILE, + &token, state->dup_extents.source_off, state->dst_fsp, state->dup_extents.target_off, diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c index b528ff2346d..993f6f8d619 100644 --- a/source3/smbd/smb2_ioctl_network_fs.c +++ b/source3/smbd/smb2_ioctl_network_fs.c @@ -82,6 +82,8 @@ struct fsctl_srv_copychunk_state { uint32_t current_chunk; NTSTATUS status; off_t total_written; + uint32_t ctl_code; + DATA_BLOB token; struct files_struct *src_fsp; struct files_struct *dst_fsp; enum { @@ -93,67 +95,6 @@ struct fsctl_srv_copychunk_state { }; static void fsctl_srv_copychunk_vfs_done(struct tevent_req *subreq); -static NTSTATUS copychunk_check_handles(uint32_t ctl_code, - struct files_struct *src_fsp, - struct files_struct *dst_fsp) -{ - /* - * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request - * The server MUST fail the request with STATUS_ACCESS_DENIED if any of - * the following are true: - * - The Open.GrantedAccess of the destination file does not include - * FILE_WRITE_DATA or FILE_APPEND_DATA. - */ - if (!CHECK_WRITE(dst_fsp)) { - DEBUG(5, ("copy chunk no write on dest handle (%s).\n", - smb_fname_str_dbg(dst_fsp->fsp_name) )); - return NT_STATUS_ACCESS_DENIED; - } - /* - * - The Open.GrantedAccess of the destination file does not include - * FILE_READ_DATA, and the CtlCode is FSCTL_SRV_COPYCHUNK. - */ - if ((ctl_code == FSCTL_SRV_COPYCHUNK) && - !CHECK_READ_IOCTL(dst_fsp)) { - DEBUG(5, ("copy chunk no read on dest handle (%s).\n", - smb_fname_str_dbg(dst_fsp->fsp_name) )); - return NT_STATUS_ACCESS_DENIED; - } - /* - * - The Open.GrantedAccess of the source file does not include - * FILE_READ_DATA access. - */ - if (!CHECK_READ_SMB2(src_fsp)) { - DEBUG(5, ("copy chunk no read on src handle (%s).\n", - smb_fname_str_dbg(src_fsp->fsp_name) )); - return NT_STATUS_ACCESS_DENIED; - } - - if (src_fsp->is_directory) { - DEBUG(5, ("copy chunk no read on src directory handle (%s).\n", - smb_fname_str_dbg(src_fsp->fsp_name) )); - return NT_STATUS_ACCESS_DENIED; - } - - if (dst_fsp->is_directory) { - DEBUG(5, ("copy chunk no read on dst directory handle (%s).\n", - smb_fname_str_dbg(dst_fsp->fsp_name) )); - return NT_STATUS_ACCESS_DENIED; - } - - if (IS_IPC(src_fsp->conn) || IS_IPC(dst_fsp->conn)) { - DEBUG(5, ("copy chunk no access on IPC$ handle.\n")); - return NT_STATUS_ACCESS_DENIED; - } - - if (IS_PRINT(src_fsp->conn) || IS_PRINT(dst_fsp->conn)) { - DEBUG(5, ("copy chunk no access on PRINT handle.\n")); - return NT_STATUS_ACCESS_DENIED; - } - - return NT_STATUS_OK; -} - static NTSTATUS fsctl_srv_copychunk_loop(struct tevent_req *req); static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx, @@ -166,8 +107,6 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req = NULL; struct fsctl_srv_copychunk_state *state = NULL; - uint64_t src_persistent_h; - uint64_t src_volatile_h; enum ndr_err_code ndr_ret; NTSTATUS status; @@ -183,6 +122,8 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx, *state = (struct fsctl_srv_copychunk_state) { .conn = dst_fsp->conn, .ev = ev, + .ctl_code = ctl_code, + .dst_fsp = dst_fsp, }; if (in_max_output < sizeof(struct srv_copychunk_rsp)) { @@ -203,26 +144,8 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - /* persistent/volatile keys sent as the resume key */ - src_persistent_h = BVAL(state->cc_copy.source_key, 0); - src_volatile_h = BVAL(state->cc_copy.source_key, 8); - state->src_fsp = file_fsp_get(smb2req, src_persistent_h, src_volatile_h); - if (state->src_fsp == NULL) { - DEBUG(3, ("invalid resume key in copy chunk req\n")); - state->status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - tevent_req_nterror(req, state->status); - return tevent_req_post(req, ev); - } - - state->dst_fsp = dst_fsp; - - state->status = copychunk_check_handles(ctl_code, - state->src_fsp, - state->dst_fsp); - if (!NT_STATUS_IS_OK(state->status)) { - tevent_req_nterror(req, state->status); - return tevent_req_post(req, ev); - } + state->token = data_blob_const(state->cc_copy.source_key, + sizeof(state->cc_copy.source_key)); state->status = copychunk_check_limits(&state->cc_copy); if (!NT_STATUS_IS_OK(state->status)) { @@ -272,7 +195,8 @@ static NTSTATUS fsctl_srv_copychunk_loop(struct tevent_req *req) subreq = SMB_VFS_OFFLOAD_WRITE_SEND(state->dst_fsp->conn, state, state->ev, - state->src_fsp, + state->ctl_code, + &state->token, source_off, state->dst_fsp, target_off, diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 7bd94ab22b1..c82496b94a4 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -2377,16 +2377,18 @@ NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req, struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct files_struct *src_fsp, - off_t src_off, + uint32_t fsctl, + DATA_BLOB *token, + off_t transfer_offset, struct files_struct *dest_fsp, off_t dest_off, off_t num, uint32_t flags) { VFS_FIND(offload_write_send); - return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, src_fsp, - src_off, dest_fsp, dest_off, num, + return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl, + token, transfer_offset, + dest_fsp, dest_off, num, flags); } -- 2.34.1