summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2008-02-14 12:30:31 +1100
committerAndrew Tridgell <tridge@samba.org>2008-02-14 12:30:31 +1100
commit839ab724dc2d204bfbb0693aeed64f6f83a4266b (patch)
treeec1db35884c7601a58a7cbeaddb94c75fd6668ec
parente870cfec9f3512b0f1bd3110d7b975652525e28a (diff)
downloadsamba-839ab724dc2d204bfbb0693aeed64f6f83a4266b.tar.gz
samba-839ab724dc2d204bfbb0693aeed64f6f83a4266b.tar.bz2
samba-839ab724dc2d204bfbb0693aeed64f6f83a4266b.zip
Fixed SMB2 rename operations from Vista clients
We needed a flag in bufinfo to mark packets as SMB2, as it seems that SMB2 uses a different format for the RenameInformation buffer than SMB does Also handle the fact that SMB2 clients give the full path to the target file in the rename, not a relative path (This used to be commit 52d7972d95ddc19d22a4187b4d4428a6c3ed32d5)
-rw-r--r--source4/libcli/raw/interfaces.h2
-rw-r--r--source4/libcli/raw/rawrequest.c7
-rw-r--r--source4/libcli/raw/request.h5
-rw-r--r--source4/libcli/smb2/request.c2
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c37
-rw-r--r--source4/smb_server/blob.c27
-rw-r--r--source4/smb_server/smb/request.c7
-rw-r--r--source4/smb_server/smb2/receive.c2
8 files changed, 59 insertions, 30 deletions
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index ce6323f2e5..16db17d7ab 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -1000,7 +1000,7 @@ union smb_setfileinfo {
struct {
union smb_handle_or_path file;
uint8_t overwrite;
- uint32_t root_fid;
+ uint64_t root_fid;
const char *new_name;
} in;
} rename_information;
diff --git a/source4/libcli/raw/rawrequest.c b/source4/libcli/raw/rawrequest.c
index dd60cc7f62..355d092583 100644
--- a/source4/libcli/raw/rawrequest.c
+++ b/source4/libcli/raw/rawrequest.c
@@ -38,7 +38,10 @@
void smb_setup_bufinfo(struct smbcli_request *req)
{
req->in.bufinfo.mem_ctx = req;
- req->in.bufinfo.unicode = (req->flags2 & FLAGS2_UNICODE_STRINGS)?true:false;
+ req->in.bufinfo.flags = 0;
+ if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
+ req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE;
+ }
req->in.bufinfo.align_base = req->in.buffer;
req->in.bufinfo.data = req->in.data;
req->in.bufinfo.data_size = req->in.data_size;
@@ -658,7 +661,7 @@ size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_c
char **dest, const uint8_t *src, int byte_len, uint_t flags)
{
if (!(flags & STR_ASCII) &&
- (((flags & STR_UNICODE) || bufinfo->unicode))) {
+ (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
}
diff --git a/source4/libcli/raw/request.h b/source4/libcli/raw/request.h
index 6776d3c349..2a572e58ee 100644
--- a/source4/libcli/raw/request.h
+++ b/source4/libcli/raw/request.h
@@ -22,12 +22,15 @@
#include "libcli/raw/signing.h"
+#define BUFINFO_FLAG_UNICODE 0x0001
+#define BUFINFO_FLAG_SMB2 0x0002
+
/*
buffer limit structure used by both SMB and SMB2
*/
struct request_bufinfo {
TALLOC_CTX *mem_ctx;
- bool unicode;
+ uint32_t flags;
const uint8_t *align_base;
const uint8_t *data;
size_t data_size;
diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c
index 0b680fb166..35229dc45f 100644
--- a/source4/libcli/smb2/request.c
+++ b/source4/libcli/smb2/request.c
@@ -32,7 +32,7 @@
void smb2_setup_bufinfo(struct smb2_request *req)
{
req->in.bufinfo.mem_ctx = req;
- req->in.bufinfo.unicode = true;
+ req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE | BUFINFO_FLAG_SMB2;
req->in.bufinfo.align_base = req->in.buffer;
if (req->in.dynamic) {
req->in.bufinfo.data = req->in.dynamic;
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index 340913cd4d..2a936ad8a7 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -63,6 +63,10 @@ static uint32_t pvfs_setfileinfo_access(union smb_setfileinfo *info)
}
break;
+ case RAW_SFILEINFO_RENAME_INFORMATION:
+ needed = SEC_STD_DELETE;
+ break;
+
default:
needed = SEC_FILE_WRITE_ATTRIBUTE;
break;
@@ -84,7 +88,8 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
char *new_name, *p;
/* renames are only allowed within a directory */
- if (strchr_m(info->rename_information.in.new_name, '\\')) {
+ if (strchr_m(info->rename_information.in.new_name, '\\') &&
+ (req->ctx->protocol != PROTOCOL_SMB2)) {
return NT_STATUS_NOT_SUPPORTED;
}
@@ -100,22 +105,28 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
/* w2k3 does not appear to allow relative rename */
if (info->rename_information.in.root_fid != 0) {
- return NT_STATUS_INVALID_PARAMETER;
+ DEBUG(1,("WARNING: got invalid root_fid in rename_information.\n"));
}
/* construct the fully qualified windows name for the new file name */
- new_name = talloc_strdup(req, name->original_name);
- if (new_name == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- p = strrchr_m(new_name, '\\');
- if (p == NULL) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
- *p = 0;
+ if (req->ctx->protocol == PROTOCOL_SMB2) {
+ /* SMB2 sends the full path of the new name */
+ new_name = talloc_asprintf(req, "\\%s", info->rename_information.in.new_name);
+ } else {
+ new_name = talloc_strdup(req, name->original_name);
+ if (new_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ p = strrchr_m(new_name, '\\');
+ if (p == NULL) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ } else {
+ *p = 0;
+ }
- new_name = talloc_asprintf(req, "%s\\%s", new_name,
- info->rename_information.in.new_name);
+ new_name = talloc_asprintf(req, "%s\\%s", new_name,
+ info->rename_information.in.new_name);
+ }
if (new_name == NULL) {
return NT_STATUS_NO_MEMORY;
}
diff --git a/source4/smb_server/blob.c b/source4/smb_server/blob.c
index caf6fb447d..795e7ce585 100644
--- a/source4/smb_server/blob.c
+++ b/source4/smb_server/blob.c
@@ -523,7 +523,7 @@ NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
int default_str_flags,
struct request_bufinfo *bufinfo)
{
- uint32_t len;
+ uint32_t len, ofs;
DATA_BLOB str_blob;
switch (level) {
@@ -563,14 +563,23 @@ NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
if (!bufinfo) {
return NT_STATUS_INTERNAL_ERROR;
}
- BLOB_CHECK_MIN_SIZE(blob, 12);
-
- st->rename_information.in.overwrite = CVAL(blob->data, 0);
- st->rename_information.in.root_fid = IVAL(blob->data, 4);
- len = IVAL(blob->data, 8);
- str_blob.data = blob->data+12;
- str_blob.length = MIN(blob->length, len);
- smbsrv_blob_pull_string(bufinfo, &str_blob, 0,
+ if (bufinfo->flags & BUFINFO_FLAG_SMB2) {
+ /* SMB2 uses a different format for rename information */
+ BLOB_CHECK_MIN_SIZE(blob, 20);
+ st->rename_information.in.overwrite = CVAL(blob->data, 0);
+ st->rename_information.in.root_fid = BVAL(blob->data, 4);
+ len = IVAL(blob->data,16);
+ ofs = 20;
+ } else {
+ BLOB_CHECK_MIN_SIZE(blob, 12);
+ st->rename_information.in.overwrite = CVAL(blob->data, 0);
+ st->rename_information.in.root_fid = IVAL(blob->data, 4);
+ len = IVAL(blob->data, 8);
+ ofs = 12;
+ }
+ str_blob = *blob;
+ str_blob.length = MIN(str_blob.length, ofs+len);
+ smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
&st->rename_information.in.new_name,
STR_UNICODE);
if (st->rename_information.in.new_name == NULL) {
diff --git a/source4/smb_server/smb/request.c b/source4/smb_server/smb/request.c
index 724055499b..d7f3793f23 100644
--- a/source4/smb_server/smb/request.c
+++ b/source4/smb_server/smb/request.c
@@ -37,7 +37,10 @@
void smbsrv_setup_bufinfo(struct smbsrv_request *req)
{
req->in.bufinfo.mem_ctx = req;
- req->in.bufinfo.unicode = (req->flags2 & FLAGS2_UNICODE_STRINGS)?true:false;
+ req->in.bufinfo.flags = 0;
+ if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
+ req->in.bufinfo.flags |= BUFINFO_FLAG_UNICODE;
+ }
req->in.bufinfo.align_base = req->in.buffer;
req->in.bufinfo.data = req->in.data;
req->in.bufinfo.data_size = req->in.data_size;
@@ -582,7 +585,7 @@ static size_t req_pull_ascii(struct request_bufinfo *bufinfo, const char **dest,
size_t req_pull_string(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
{
if (!(flags & STR_ASCII) &&
- (((flags & STR_UNICODE) || bufinfo->unicode))) {
+ (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
return req_pull_ucs2(bufinfo, dest, src, byte_len, flags);
}
diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c
index 58070065fc..dea7c9e79e 100644
--- a/source4/smb_server/smb2/receive.c
+++ b/source4/smb_server/smb2/receive.c
@@ -35,7 +35,7 @@
void smb2srv_setup_bufinfo(struct smb2srv_request *req)
{
req->in.bufinfo.mem_ctx = req;
- req->in.bufinfo.unicode = true;
+ req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE | BUFINFO_FLAG_SMB2;
req->in.bufinfo.align_base = req->in.buffer;
if (req->in.dynamic) {
req->in.bufinfo.data = req->in.dynamic;