smbd: remove dead code
[samba.git] / source3 / smbd / smb2_ioctl_network_fs.c
index b90a8b3fe11040bd77c132b5f2bab4fe81d2154f..8154fa3f92ed2ea7986bdf0642b1422743b2724a 100644 (file)
@@ -31,6 +31,9 @@
 #include "smb2_ioctl_private.h"
 #include "../lib/tsocket/tsocket.h"
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_SMB2
+
 static void copychunk_pack_limits(struct srv_copychunk_rsp *cc_rsp)
 {
        cc_rsp->chunks_written = COPYCHUNK_MAX_CHUNKS;
@@ -80,9 +83,10 @@ struct fsctl_srv_copychunk_state {
        struct connection_struct *conn;
        struct srv_copychunk_copy cc_copy;
        uint32_t current_chunk;
-       uint32_t next_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 {
@@ -90,72 +94,9 @@ struct fsctl_srv_copychunk_state {
                COPYCHUNK_OUT_LIMITS,
                COPYCHUNK_OUT_RSP,
        } out_data;
-       bool aapl_copyfile;
 };
 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,
-                                       struct smb_request *smb1req)
-{
-       /*
-        * [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,
@@ -168,8 +109,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;
 
@@ -185,6 +124,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)) {
@@ -205,27 +146,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,
-                                               smb2req->smb1req);
-       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)) {
@@ -246,129 +168,41 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
        return req;
 }
 
-/*
- * Work out the next IO request from the remaining chunks starting with
- * state->current_chunk. Chunks with left to right adjacent ranges can be merged
- * into a single IO request.
- */
-static uint32_t next_merged_io(struct fsctl_srv_copychunk_state *state)
-{
-       struct srv_copychunk *chunk = NULL;
-       uint32_t length;
-       off_t next_src_offset;
-       off_t next_dst_offset;
-
-       /*
-        * We're expected to process at least one chunk and return it's length,
-        * so let's do this first.
-        */
-
-       chunk = &state->cc_copy.chunks[state->current_chunk];
-       length = chunk->length;
-       state->next_chunk++;
-
-       /*
-        * Now process subsequent chunks merging chunks as long as ranges are
-        * adjacent and the source file size is not exceeded (this is needed
-        * for error reporting).
-        */
-
-       next_src_offset = chunk->source_off + chunk->length;
-       next_dst_offset = chunk->target_off + chunk->length;
-
-       while (state->next_chunk < state->cc_copy.chunk_count) {
-               chunk = &state->cc_copy.chunks[state->next_chunk];
-
-               if ((chunk->source_off != next_src_offset) ||
-                   (chunk->target_off != next_dst_offset))
-               {
-                       /* Not adjacent, stop merging */
-                       break;
-               }
-
-               next_src_offset += chunk->length;
-               next_dst_offset += chunk->length;
-
-               if (next_src_offset > state->src_fsp->fsp_name->st.st_ex_size) {
-                       /* Source filesize exceeded, stop merging */
-                       break;
-               }
-
-               /*
-                * Found a mergable chunk, merge it and continue searching.
-                * Note: this can't wrap, limits were already checked in
-                * copychunk_check_limits().
-                */
-               length += chunk->length;
-
-               state->next_chunk++;
-       }
-
-       return length;
-}
-
 static NTSTATUS fsctl_srv_copychunk_loop(struct tevent_req *req)
 {
        struct fsctl_srv_copychunk_state *state = tevent_req_data(
                req, struct fsctl_srv_copychunk_state);
        struct tevent_req *subreq = NULL;
-       struct srv_copychunk *chunk = NULL;
-       uint32_t length;
+       uint32_t length = 0;
+       off_t source_off = 0;
+       off_t target_off = 0;
 
-       if (state->next_chunk > state->cc_copy.chunk_count) {
-               DBG_ERR("Copy-chunk loop next_chunk [%d] chunk_count [%d]\n",
-                       state->next_chunk, state->cc_copy.chunk_count);
-               return NT_STATUS_INTERNAL_ERROR;
-       }
+       /*
+        * chunk_count can be 0 which must either just do nothing returning
+        * success saying number of copied chunks is 0 (verified against
+        * Windows).
+        *
+        * Or it can be a special macOS copyfile request, so we send this into
+        * the VFS, vfs_fruit if loaded implements the macOS copyile semantics.
+        */
+       if (state->cc_copy.chunk_count > 0) {
+               struct srv_copychunk *chunk = NULL;
 
-       if (state->cc_copy.chunk_count == 0) {
-               /*
-                * Process as OS X copyfile request. This is currently
-                * the only copychunk request with a chunk count of 0
-                * we will process.
-                */
-               if (!state->src_fsp->aapl_copyfile_supported ||
-                   !state->dst_fsp->aapl_copyfile_supported)
-               {
-                       /*
-                        * This must not produce an error but just return a
-                        * chunk count of 0 in the response.
-                        */
-                       tevent_req_done(req);
-                       tevent_req_post(req, state->ev);
-                       return NT_STATUS_OK;
-               }
-               state->aapl_copyfile = true;
-
-               subreq = SMB_VFS_OFFLOAD_WRITE_SEND(state->dst_fsp->conn,
-                                                state,
-                                                state->ev,
-                                                state->src_fsp,
-                                                0,
-                                                state->dst_fsp,
-                                                0,
-                                                0,
-                                                0);
-               if (subreq == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-               tevent_req_set_callback(subreq,
-                                       fsctl_srv_copychunk_vfs_done, req);
-               return NT_STATUS_OK;
+               chunk = &state->cc_copy.chunks[state->current_chunk];
+               length = chunk->length;
+               source_off = chunk->source_off;
+               target_off = chunk->target_off;
        }
 
-       chunk = &state->cc_copy.chunks[state->current_chunk];
-       length = next_merged_io(state);
-
        subreq = SMB_VFS_OFFLOAD_WRITE_SEND(state->dst_fsp->conn,
                                         state,
                                         state->ev,
-                                        state->src_fsp,
-                                        chunk->source_off,
+                                        state->ctl_code,
+                                        &state->token,
+                                        source_off,
                                         state->dst_fsp,
-                                        chunk->target_off,
-                                        length,
-                                        0);
+                                        target_off,
+                                        length);
        if (tevent_req_nomem(subreq, req)) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -392,18 +226,27 @@ static void fsctl_srv_copychunk_vfs_done(struct tevent_req *subreq)
        if (!NT_STATUS_IS_OK(status)) {
                DBG_ERR("copy chunk failed [%s] chunk [%u] of [%u]\n",
                        nt_errstr(status),
-                       (unsigned int)state->next_chunk,
+                       (unsigned int)state->current_chunk,
                        (unsigned int)state->cc_copy.chunk_count);
                tevent_req_nterror(req, status);
                return;
        }
 
        DBG_DEBUG("good copy chunk [%u] of [%u]\n",
-                 (unsigned int)state->next_chunk,
+                 (unsigned int)state->current_chunk,
                  (unsigned int)state->cc_copy.chunk_count);
        state->total_written += chunk_nwritten;
 
-       state->current_chunk = state->next_chunk;
+       if (state->cc_copy.chunk_count == 0) {
+               /*
+                * This must not produce an error but just return a chunk count
+                * of 0 in the response.
+                */
+               tevent_req_done(req);
+               return;
+       }
+
+       state->current_chunk++;
        if (state->current_chunk == state->cc_copy.chunk_count) {
                tevent_req_done(req);
                return;
@@ -433,11 +276,7 @@ static NTSTATUS fsctl_srv_copychunk_recv(struct tevent_req *req,
                *pack_rsp = true;
                break;
        case COPYCHUNK_OUT_RSP:
-               if (state->aapl_copyfile == true) {
-                       cc_rsp->chunks_written = 0;
-               } else {
-                       cc_rsp->chunks_written = state->current_chunk;
-               }
+               cc_rsp->chunks_written = state->current_chunk;
                cc_rsp->chunk_bytes_written = 0;
                cc_rsp->total_bytes_written = state->total_written;
                *pack_rsp = true;