summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2017-06-09 13:02:49 +0200
committerRalph Boehme <slow@samba.org>2017-07-03 19:59:08 +0200
commit3645f83a3c83fa3e4bf4dbacf885cc4295e7eadd (patch)
tree7b14b55f4f51eb63d786b91f5c0533f4d5df611f
parentd50f307e97ae28b9fbdc2e6cffb1b5493c583a09 (diff)
downloadsamba-3645f83a3c83fa3e4bf4dbacf885cc4295e7eadd.tar.gz
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 <slow@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r--examples/VFS/skel_opaque.c5
-rw-r--r--examples/VFS/skel_transparent.c7
-rw-r--r--selftest/knownfail.d/smb2.ioctl.copy-chunk-across-shares2
-rw-r--r--source3/include/vfs.h10
-rw-r--r--source3/include/vfs_macros.h8
-rw-r--r--source3/modules/offload_token.c90
-rw-r--r--source3/modules/offload_token.h3
-rw-r--r--source3/modules/vfs_btrfs.c46
-rw-r--r--source3/modules/vfs_default.c48
-rw-r--r--source3/modules/vfs_fruit.c29
-rw-r--r--source3/modules/vfs_full_audit.c10
-rw-r--r--source3/modules/vfs_time_audit.c7
-rw-r--r--source3/smbd/smb2_ioctl_filesys.c9
-rw-r--r--source3/smbd/smb2_ioctl_network_fs.c92
-rw-r--r--source3/smbd/vfs.c10
15 files changed, 242 insertions, 134 deletions
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);
}