diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/proto.h | 4 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 121 | ||||
-rw-r--r-- | source3/smbd/reply.c | 88 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 71 |
4 files changed, 127 insertions, 157 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 5d0fa18192..a79c7eb7e8 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6884,8 +6884,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, NTSTATUS rename_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, - const char *name_in, - const char *newname_in, + struct smb_filename *smb_fname_src, + struct smb_filename *smb_fname_dst, uint32 attrs, bool replace_if_exists, bool src_has_wild, diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 89fc9dc4a8..dd4ef97874 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1312,6 +1312,8 @@ void reply_ntrename(struct smb_request *req) bool src_has_wcard = False; bool dest_has_wcard = False; uint32 attrs; + uint32_t ucf_flags_src = 0; + uint32_t ucf_flags_dst = 0; uint16 rename_type; TALLOC_CTX *ctx = talloc_tos(); @@ -1352,91 +1354,72 @@ void reply_ntrename(struct smb_request *req) goto out; } + /* + * If this is a rename operation, allow wildcards and save the + * destination's last component. + */ + if (rename_type == RENAME_FLAG_RENAME) { + ucf_flags_src = UCF_ALLOW_WCARD_LCOMP; + ucf_flags_dst = UCF_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP; + } + /* rename_internals() calls unix_convert(), so don't call it here. */ - if (rename_type != RENAME_FLAG_RENAME) { - status = filename_convert(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - oldname, - 0, - NULL, - &smb_fname_old); - 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); + status = filename_convert(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + oldname, + ucf_flags_src, + NULL, + &smb_fname_old); + 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, - req->flags2 & FLAGS2_DFS_PATHNAMES, - newname, - 0, - NULL, - &smb_fname_new); - 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); + status = filename_convert(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + newname, + ucf_flags_dst, + &dest_has_wcard, + &smb_fname_new); + 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; } - - DEBUG(3,("reply_ntrename: %s -> %s\n", - smb_fname_str_dbg(smb_fname_old), - smb_fname_str_dbg(smb_fname_new))); + reply_nterror(req, status); + goto out; } + DEBUG(3,("reply_ntrename: %s -> %s\n", + smb_fname_str_dbg(smb_fname_old), + smb_fname_str_dbg(smb_fname_new))); + switch(rename_type) { case RENAME_FLAG_RENAME: - status = resolve_dfspath(ctx, conn, - (req->flags2 & - FLAGS2_DFS_PATHNAMES), - oldname, &oldname); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10,("resolve_dfspath failed for name %s " - "with %s\n", oldname, - nt_errstr(status))); - reply_nterror(req, status); - goto out; - } - - status = resolve_dfspath(ctx, conn, - (req->flags2 & - FLAGS2_DFS_PATHNAMES), - newname, &newname); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10,("resolve_dfspath failed for name %s " - "with %s\n", newname, - nt_errstr(status))); - reply_nterror(req, status); - goto out; - } - - DEBUG(3,("reply_ntrename: %s -> %s\n", oldname, - newname)); - - status = rename_internals(ctx, conn, req, oldname, - newname, attrs, False, src_has_wcard, - dest_has_wcard, DELETE_ACCESS); + status = rename_internals(ctx, conn, req, + smb_fname_old, smb_fname_new, + attrs, False, src_has_wcard, + dest_has_wcard, + DELETE_ACCESS); break; case RENAME_FLAG_HARD_LINK: if (src_has_wcard || dest_has_wcard) { /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { - status = hardlink_internals(ctx, - conn, - smb_fname_old, - smb_fname_new); + status = hardlink_internals(ctx, conn, + smb_fname_old, + smb_fname_new); } break; case RENAME_FLAG_COPY: diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b43d3d304c..03bca827d1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -6137,16 +6137,14 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, NTSTATUS rename_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, - const char *name_in, - const char *newname_in, + struct smb_filename *smb_fname_src, + struct smb_filename *smb_fname_dst, uint32 attrs, bool replace_if_exists, bool src_has_wild, bool dest_has_wild, uint32_t access_mask) { - struct smb_filename *smb_fname_src = NULL; - struct smb_filename *smb_fname_dst = NULL; char *fname_src_dir = NULL; char *fname_src_mask = NULL; int count=0; @@ -6157,19 +6155,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, int create_options = 0; bool posix_pathnames = lp_posix_pathnames(); - status = unix_convert(ctx, conn, name_in, &smb_fname_src, - src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - - status = unix_convert(ctx, conn, newname_in, &smb_fname_dst, - (UCF_SAVE_LCOMP | - (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0))); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - /* * Split the old name into directory and last component * strings. Note that unix_convert may have stripped off a @@ -6470,8 +6455,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, } out: - TALLOC_FREE(smb_fname_src); - TALLOC_FREE(smb_fname_dst); TALLOC_FREE(fname_src_dir); TALLOC_FREE(fname_src_mask); return status; @@ -6492,13 +6475,14 @@ void reply_mv(struct smb_request *req) bool src_has_wcard = False; bool dest_has_wcard = False; TALLOC_CTX *ctx = talloc_tos(); + struct smb_filename *smb_fname_src = NULL; + struct smb_filename *smb_fname_dst = NULL; START_PROFILE(SMBmv); if (req->wct < 1) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBmv); - return; + goto out; } attrs = SVAL(req->vwv+0, 0); @@ -6508,69 +6492,71 @@ void reply_mv(struct smb_request *req) &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - END_PROFILE(SMBmv); - return; + goto out; } p++; p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE, &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - END_PROFILE(SMBmv); - return; + goto out; } - status = resolve_dfspath_wcard(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - name, - &name, - &src_has_wcard); + status = filename_convert(ctx, + conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + name, + UCF_ALLOW_WCARD_LCOMP, + &src_has_wcard, + &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); - END_PROFILE(SMBmv); - return; + goto out; } reply_nterror(req, status); - END_PROFILE(SMBmv); - return; + goto out; } - status = resolve_dfspath_wcard(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - newname, - &newname, - &dest_has_wcard); + status = filename_convert(ctx, + conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + newname, + UCF_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP, + &dest_has_wcard, + &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); - END_PROFILE(SMBmv); - return; + goto out; } reply_nterror(req, status); - END_PROFILE(SMBmv); - return; + goto out; } - DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); + DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src), + smb_fname_str_dbg(smb_fname_dst))); - status = rename_internals(ctx, conn, req, name, newname, attrs, False, - src_has_wcard, dest_has_wcard, DELETE_ACCESS); + status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst, + attrs, False, src_has_wcard, dest_has_wcard, + DELETE_ACCESS); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - END_PROFILE(SMBmv); - return; + goto out; } reply_nterror(req, status); - END_PROFILE(SMBmv); - return; + goto out; } reply_outbuf(req, 0, 0); - + out: + TALLOC_FREE(smb_fname_src); + TALLOC_FREE(smb_fname_dst); END_PROFILE(SMBmv); return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6a7b1f8b32..6fde8d240c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5683,14 +5683,13 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const char *fname) + struct smb_filename *smb_fname_src) { bool overwrite; uint32 root_fid; uint32 len; char *newname = NULL; - char *base_name = NULL; - struct smb_filename *smb_fname = NULL; + struct smb_filename *smb_fname_dst = NULL; bool dest_has_wcard = False; NTSTATUS status = NT_STATUS_OK; char *p; @@ -5741,7 +5740,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, /* Create an smb_fname to call rename_internals_fsp() with. */ status = create_synthetic_smb_fname(talloc_tos(), fsp->base_fsp->fsp_name->base_name, newname, NULL, - &smb_fname); + &smb_fname_dst); if (!NT_STATUS_IS_OK(status)) { goto out; } @@ -5750,28 +5749,31 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, * Set the original last component, since * rename_internals_fsp() requires it. */ - smb_fname->original_lcomp = talloc_strdup(smb_fname, newname); - if (smb_fname->original_lcomp == NULL) { + smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst, + newname); + if (smb_fname_dst->original_lcomp == NULL) { status = NT_STATUS_NO_MEMORY; goto out; } - /* Create a char * to call rename_internals() with. */ - base_name = talloc_asprintf(ctx, "%s%s", - fsp->base_fsp->fsp_name->base_name, - newname); - if (!base_name) { - status = NT_STATUS_NO_MEMORY; - goto out; - } } else { + /* + * Build up an smb_fname_dst based on the filename passed in. + * We basically just strip off the last component, and put on + * the newname instead. + */ + char *base_name = NULL; + /* newname must *not* be a stream name. */ if (newname[0] == ':') { return NT_STATUS_NOT_SUPPORTED; } - /* Create the base directory. */ - base_name = talloc_strdup(ctx, fname); + /* + * Strip off the last component (filename) of the path passed + * in. + */ + base_name = talloc_strdup(ctx, smb_fname_src->base_name); if (!base_name) { return NT_STATUS_NO_MEMORY; } @@ -5792,8 +5794,10 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, return NT_STATUS_NO_MEMORY; } - status = unix_convert(ctx, conn, base_name, &smb_fname, - UCF_SAVE_LCOMP); + status = unix_convert(ctx, conn, base_name, &smb_fname_dst, + (UCF_SAVE_LCOMP | + (dest_has_wcard ? + UCF_ALLOW_WCARD_LCOMP : 0))); /* If an error we expect this to be * NT_STATUS_OBJECT_PATH_NOT_FOUND */ @@ -5804,32 +5808,35 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, goto out; } /* Create an smb_fname to call rename_internals_fsp() */ - status = create_synthetic_smb_fname(talloc_tos(), + status = create_synthetic_smb_fname(ctx, base_name, NULL, - NULL, &smb_fname); + NULL, + &smb_fname_dst); if (!NT_STATUS_IS_OK(status)) { goto out; } } - } if (fsp) { DEBUG(10,("smb_file_rename_information: " "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", - fsp->fnum, fsp_str_dbg(fsp), base_name)); - status = rename_internals_fsp(conn, fsp, smb_fname, 0, + fsp->fnum, fsp_str_dbg(fsp), + smb_fname_str_dbg(smb_fname_dst))); + status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0, overwrite); } else { DEBUG(10,("smb_file_rename_information: " "SMB_FILE_RENAME_INFORMATION %s -> %s\n", - fname, base_name)); - status = rename_internals(ctx, conn, req, fname, base_name, 0, - overwrite, False, dest_has_wcard, - FILE_WRITE_ATTRIBUTES); + smb_fname_str_dbg(smb_fname_src), + smb_fname_str_dbg(smb_fname_dst))); + status = rename_internals(ctx, conn, req, smb_fname_src, + smb_fname_dst, 0, overwrite, false, + dest_has_wcard, + FILE_WRITE_ATTRIBUTES); } out: - TALLOC_FREE(smb_fname); + TALLOC_FREE(smb_fname_dst); return status; } @@ -7072,7 +7079,6 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, int *ret_data_size) { char *pdata = *ppdata; - char *fname = NULL; NTSTATUS status = NT_STATUS_OK; int data_return_size = 0; @@ -7090,11 +7096,6 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, } } - status = get_full_smb_filename(mem_ctx, smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d " "totdata=%d\n", smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1, info_level, total_data)); @@ -7248,7 +7249,7 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, { status = smb_file_rename_information(conn, req, pdata, total_data, - fsp, fname); + fsp, smb_fname); break; } |