s3/vfs: make SMB_VFS_OFFLOAD_WRITE_SEND offload token based
authorRalph Boehme <slow@samba.org>
Fri, 9 Jun 2017 11:02:49 +0000 (13:02 +0200)
committerRalph Boehme <slow@samba.org>
Mon, 3 Jul 2017 17:59:08 +0000 (19:59 +0200)
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>
15 files changed:
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
selftest/knownfail.d/smb2.ioctl.copy-chunk-across-shares [deleted file]
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/offload_token.c
source3/modules/offload_token.h
source3/modules/vfs_btrfs.c
source3/modules/vfs_default.c
source3/modules/vfs_fruit.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_time_audit.c
source3/smbd/smb2_ioctl_filesys.c
source3/smbd/smb2_ioctl_network_fs.c
source3/smbd/vfs.c

index d416bf6ef5365b28eb299f96ba4cb7f299165499..831d0f14fce52592c5ff63479853d679b7e8005a 100644 (file)
@@ -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,
 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,
                                               struct files_struct *dest_fsp,
                                               off_t dest_off,
                                               off_t num,
index 58fd77a9d51b2026bb719e481dfbd6c4aea49256..f813926141bf3c4287ab1bae11f23d9eb9d0f0a8 100644 (file)
@@ -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,
 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,
                                               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,
 
        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);
                                              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 (file)
index 4a1f859..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-^samba3.smb2.ioctl.copy_chunk_across_shares
-^samba3.smb2.ioctl fs_specific.copy_chunk_across_shares
index c11ce51f6706ede4652b83ae9eb34f6a9c5d543a..1308cc2da51b159f22457487a5b55805516e4068 100644 (file)
@@ -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 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,
                                                    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 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,
                                                   struct files_struct *dest_fsp,
                                                   off_t dest_off,
                                                   off_t num,
index 2d810d0aa8045e6364658c7d4fec1cd64cc2550a..77a2a8d37a225dccd450bebc8c72be7bb7d004ec 100644 (file)
 #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_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))
 
 #define SMB_VFS_OFFLOAD_WRITE_RECV(conn, req, copied) \
        smb_vfs_call_offload_write_recv((conn)->vfs_handles, (req), (copied))
index 2969262f48e1eb179c02f7f9d81df0f16f3e2d34..05528da46b5c4a5c8c5b908bcadffd79d4b5c9dd 100644 (file)
@@ -20,6 +20,7 @@
 #include "includes.h"
 #include "smbd/smbd.h"
 #include "smbd/globals.h"
 #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"
 #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;
 }
 
        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;
+}
index 569edcfdd170cfa8e0248f349b44f7dccbee2132..1e8e26d476ffa6e9ec627b31c402a16745e7a97d 100644 (file)
@@ -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);
                                       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
 #endif
index 79175378efcd4d5be394715f4fa70ef26d9156c3..f310a3dfd658808dddf303187b156a9f5ac94e04 100644 (file)
@@ -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,
 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,
                                                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;
        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;
        int ret;
+       bool handle_offload_write = true;
        NTSTATUS status;
 
        req = tevent_req_create(mem_ctx, &cc_state, struct btrfs_cc_state);
        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;
 
 
        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.
                 */
        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,
                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);
                                                                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;
        }
 
                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);
        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,
                          (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);
                                                                dest_fsp,
                                                                dest_off,
                                                                num, flags);
index 9b86a905203aba8133f215e0b96af398869dc632..9add9155f12aaa55021bd2aa7db52d16bb648098 100644 (file)
@@ -1689,6 +1689,7 @@ struct vfswrap_offload_write_state {
        struct lock_struct read_lck;
        bool write_lck_locked;
        struct lock_struct write_lck;
        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;
        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 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,
        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);
        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;
 
        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) {
        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,
 
        *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,
                .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,
        };
 
                .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);
        }
 
        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);
        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);
        }
 
                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
                /*
                 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
                 *   If the SourceOffset or SourceOffset + Length extends beyond
index 279366ca08c75644fa0e411cbcc43a7c68f2a192..db6324a357467c40d44e53c34cd03c3b97ba6160 100644 (file)
@@ -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,
 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,
                                                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;
        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",
        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;
                return NULL;
        }
        state->handle = handle;
-       state->src_fsp = src_fsp;
        state->dst_fsp = dest_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
        /*
         * 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) &&
         * = 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);
            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,
        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,
                                              dest_fsp,
                                              dest_off,
                                              to_copy,
index f9d14a8e845e481ae816f637fe6f3e5023e4b4cf..892cf5d73786ab315e4d814496b89df79d264969 100644 (file)
@@ -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,
 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,
                                                         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;
 
 {
        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, "");
                                           flags);
 
        do_log(SMB_VFS_OP_OFFLOAD_WRITE_SEND, req, handle, "");
index 6dc03fb7a04070f65191736662717502ddb01a7c..cc21a47624511424d66b2c8ed6f80923159a89cf 100644 (file)
@@ -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,
 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,
                                                         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,
        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);
                                              dest_fsp, dest_off, num, flags);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
index 5bbeadabcb9255b0bbd8492771b2b7331eb0c536..fa1cb93c43970fdf5e10cecd518f01ec77dd9ace 100644 (file)
@@ -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 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;
 };
        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);
        }
                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);
 
        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);
                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,
        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;
        }
        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,
        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,
                                            state->dup_extents.source_off,
                                            state->dst_fsp,
                                            state->dup_extents.target_off,
index b528ff2346d293c0c36ba8f906f1f8e7e5500847..993f6f8d61944432acbce3af0ad4a38346a9ad6a 100644 (file)
@@ -82,6 +82,8 @@ struct fsctl_srv_copychunk_state {
        uint32_t current_chunk;
        NTSTATUS status;
        off_t total_written;
        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 {
        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 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,
 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;
 {
        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;
 
        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,
        *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)) {
        };
 
        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);
        }
 
                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)) {
 
        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,
        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,
                                         source_off,
                                         state->dst_fsp,
                                         target_off,
index 7bd94ab22b1fd368bc280a61c0dc97ca3709c1c5..c82496b94a459392bf888ce6a3ba89d8e5581fef 100644 (file)
@@ -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 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);
                                                   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);
 }
 
                                               flags);
 }