From 7f61ff777b1dafb757794e256fb9d3a52dfb7e24 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Dec 2021 12:24:07 -0800 Subject: [PATCH] s3: smbd: Remove support for SMBcopy SMB_COM_COPY (0x29) It's not used in our client code or tested. From MS-CIFS. This command was introduced in the LAN Manager 1.0 dialect It was rendered obsolete in the NT LAN Manager dialect. This command was used to perform server-side file copies, but is no longer used. Clients SHOULD NOT send requests using this command code. Servers receiving requests with this command code SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc). Signed-off-by: Jeremy Allison Reviewed-by: Ralph Boehme --- source3/smbd/reply.c | 419 ++------------------------------------------------- 1 file changed, 11 insertions(+), 408 deletions(-) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b0101f667a8..8ee17643200 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -8782,419 +8782,22 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, /**************************************************************************** Reply to a file copy. + + From MS-CIFS. + + This command was introduced in the LAN Manager 1.0 dialect + It was rendered obsolete in the NT LAN Manager dialect. + This command was used to perform server-side file copies, but + is no longer used. Clients SHOULD + NOT send requests using this command code. + Servers receiving requests with this command code + SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc). ****************************************************************************/ void reply_copy(struct smb_request *req) { - connection_struct *conn = req->conn; - struct smb_filename *smb_fname_src = NULL; - struct smb_filename *smb_fname_src_dir = NULL; - struct smb_filename *smb_fname_dst = NULL; - char *fname_src = NULL; - char *fname_dst = NULL; - char *fname_src_mask = NULL; - char *fname_src_dir = NULL; - const char *p; - int count=0; - int error = ERRnoaccess; - int tid2; - int ofun; - int flags; - bool target_is_directory=False; - bool source_has_wild = False; - bool dest_has_wild = False; - NTSTATUS status; - uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP | - ucf_flags_from_smb_request(req); - uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP | - ucf_flags_from_smb_request(req); - bool posix_pathnames = req->posix_pathnames; - TALLOC_CTX *ctx = talloc_tos(); - START_PROFILE(SMBcopy); - - if (req->wct < 3) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - goto out; - } - - tid2 = SVAL(req->vwv+0, 0); - ofun = SVAL(req->vwv+1, 0); - flags = SVAL(req->vwv+2, 0); - - p = (const char *)req->buf; - p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - - DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst)); - - if (tid2 != conn->cnum) { - /* can't currently handle inter share copies XXXX */ - DEBUG(3,("Rejecting inter-share copy\n")); - reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE); - goto out; - } - - status = filename_convert(ctx, conn, - fname_src, - ucf_flags_src, - 0, - &smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - goto out; - } - reply_nterror(req, status); - goto out; - } - - status = filename_convert(ctx, conn, - fname_dst, - ucf_flags_dst, - 0, - &smb_fname_dst); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - goto out; - } - reply_nterror(req, status); - goto out; - } - - target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st); - - if ((flags&1) && target_is_directory) { - reply_nterror(req, NT_STATUS_NO_SUCH_FILE); - goto out; - } - - if ((flags&2) && !target_is_directory) { - reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); - goto out; - } - - if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) { - /* wants a tree copy! XXXX */ - DEBUG(3,("Rejecting tree copy\n")); - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - goto out; - } - - /* Split up the directory from the filename/mask. */ - status = split_fname_dir_mask(ctx, smb_fname_src->base_name, - &fname_src_dir, &fname_src_mask); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - if (!posix_pathnames) { - char *orig_src_lcomp = NULL; - char *orig_dst_lcomp = NULL; - /* - * Check the wildcard mask *before* - * unmangling. As mangling is done - * for names that can't be returned - * to Windows the unmangled name may - * contain Windows wildcard characters. - */ - orig_src_lcomp = get_original_lcomp(ctx, - conn, - fname_src, - ucf_flags_src); - if (orig_src_lcomp == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - orig_dst_lcomp = get_original_lcomp(ctx, - conn, - fname_dst, - ucf_flags_dst); - if (orig_dst_lcomp == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - source_has_wild = ms_has_wild(orig_src_lcomp); - dest_has_wild = ms_has_wild(orig_dst_lcomp); - TALLOC_FREE(orig_src_lcomp); - TALLOC_FREE(orig_dst_lcomp); - } - - /* - * We should only check the mangled cache - * here if unix_convert failed. This means - * that the path in 'mask' doesn't exist - * on the file system and so we need to look - * for a possible mangle. This patch from - * Tine Smukavec . - */ - if (!VALID_STAT(smb_fname_src->st) && - !posix_pathnames && - mangle_is_mangled(fname_src_mask, conn->params)) { - char *new_mask = NULL; - mangle_lookup_name_from_8_3(ctx, fname_src_mask, - &new_mask, conn->params); - - /* Use demangled name if one was successfully found. */ - if (new_mask) { - TALLOC_FREE(fname_src_mask); - fname_src_mask = new_mask; - } - } - - if (!source_has_wild) { - - /* - * Only one file needs to be copied. Append the mask back onto - * the directory. - */ - TALLOC_FREE(smb_fname_src->base_name); - if (ISDOT(fname_src_dir)) { - /* Ensure we use canonical names on open. */ - smb_fname_src->base_name = talloc_asprintf(smb_fname_src, - "%s", - fname_src_mask); - } else { - smb_fname_src->base_name = talloc_asprintf(smb_fname_src, - "%s/%s", - fname_src_dir, - fname_src_mask); - } - if (!smb_fname_src->base_name) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - if (dest_has_wild) { - char *fname_dst_mod = NULL; - if (!resolve_wildcards(smb_fname_dst, - smb_fname_src->base_name, - smb_fname_dst->base_name, - &fname_dst_mod)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - TALLOC_FREE(smb_fname_dst->base_name); - smb_fname_dst->base_name = fname_dst_mod; - } - - status = check_name(conn, smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - - status = check_name(conn, smb_fname_dst); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - - status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst, - ofun, count, target_is_directory); - - if(!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } else { - count++; - } - } else { - struct smb_Dir *dir_hnd = NULL; - const char *dname = NULL; - char *talloced = NULL; - long offset = 0; - - /* - * There is a wildcard that requires us to actually read the - * src dir and copy each file matching the mask to the dst. - * Right now streams won't be copied, but this could - * presumably be added with a nested loop for reach dir entry. - */ - SMB_ASSERT(!smb_fname_src->stream_name); - SMB_ASSERT(!smb_fname_dst->stream_name); - - smb_fname_src->stream_name = NULL; - smb_fname_dst->stream_name = NULL; - - if (strequal(fname_src_mask,"????????.???")) { - TALLOC_FREE(fname_src_mask); - fname_src_mask = talloc_strdup(ctx, "*"); - if (!fname_src_mask) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - } - - smb_fname_src_dir = synthetic_smb_fname(talloc_tos(), - fname_src_dir, - NULL, - NULL, - smb_fname_src->twrp, - smb_fname_src->flags); - if (smb_fname_src_dir == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - status = check_name(conn, smb_fname_src_dir); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - - dir_hnd = OpenDir(ctx, - conn, - smb_fname_src_dir, - fname_src_mask, - 0); - if (dir_hnd == NULL) { - status = map_nt_error_from_unix(errno); - reply_nterror(req, status); - goto out; - } - - error = ERRbadfile; - - /* Iterate over the src dir copying each entry to the dst. */ - while ((dname = ReadDirName(dir_hnd, &offset, - &smb_fname_src->st, &talloced))) { - char *destname = NULL; - - if (ISDOT(dname) || ISDOTDOT(dname)) { - TALLOC_FREE(talloced); - continue; - } - - if (IS_VETO_PATH(conn, dname)) { - TALLOC_FREE(talloced); - continue; - } - - if(!mask_match(dname, fname_src_mask, - posix_pathnames ? - true : conn->case_sensitive)) { - TALLOC_FREE(talloced); - continue; - } - - error = ERRnoaccess; - - /* Get the src smb_fname struct setup. */ - TALLOC_FREE(smb_fname_src->base_name); - if (ISDOT(fname_src_dir)) { - /* Ensure we use canonical names on open. */ - smb_fname_src->base_name = - talloc_asprintf(smb_fname_src, "%s", - dname); - } else { - smb_fname_src->base_name = - talloc_asprintf(smb_fname_src, "%s/%s", - fname_src_dir, dname); - } - - if (!smb_fname_src->base_name) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - if (!resolve_wildcards(ctx, smb_fname_src->base_name, - smb_fname_dst->base_name, - &destname)) { - TALLOC_FREE(talloced); - continue; - } - if (!destname) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - TALLOC_FREE(smb_fname_dst->base_name); - smb_fname_dst->base_name = destname; - - ZERO_STRUCT(smb_fname_src->st); - vfs_stat(conn, smb_fname_src); - - status = openat_pathref_fsp(conn->cwd_fsp, - smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - DBG_INFO("openat_pathref_fsp [%s] failed: %s\n", - smb_fname_str_dbg(smb_fname_src), - nt_errstr(status)); - break; - } - - if (!is_visible_fsp(smb_fname_src->fsp)) { - TALLOC_FREE(talloced); - continue; - } - - status = check_name(conn, smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - reply_nterror(req, status); - goto out; - } - - status = check_name(conn, smb_fname_dst); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - reply_nterror(req, status); - goto out; - } - - DEBUG(3,("reply_copy : doing copy on %s -> %s\n", - smb_fname_src->base_name, - smb_fname_dst->base_name)); - - status = copy_file(ctx, conn, smb_fname_src, - smb_fname_dst, ofun, count, - target_is_directory); - if (NT_STATUS_IS_OK(status)) { - count++; - } - - TALLOC_FREE(talloced); - } - TALLOC_FREE(dir_hnd); - } - - if (count == 0) { - reply_nterror(req, dos_to_ntstatus(ERRDOS, error)); - goto out; - } - - reply_outbuf(req, 1, 0); - SSVAL(req->outbuf,smb_vwv0,count); - out: - TALLOC_FREE(smb_fname_src); - TALLOC_FREE(smb_fname_src_dir); - TALLOC_FREE(smb_fname_dst); - TALLOC_FREE(fname_src); - TALLOC_FREE(fname_dst); - TALLOC_FREE(fname_src_mask); - TALLOC_FREE(fname_src_dir); - + reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED); END_PROFILE(SMBcopy); return; } -- 2.11.4.GIT