summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h4
-rw-r--r--source3/smbd/nttrans.c121
-rw-r--r--source3/smbd/reply.c88
-rw-r--r--source3/smbd/trans2.c71
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;
}