summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorSATOH Fumiyasu <fumiyas@osstech.co.jp>2009-06-30 15:29:08 -0700
committerJeremy Allison <jra@samba.org>2009-06-30 15:29:08 -0700
commit7f7ebfaecbe3458a4c3e8fc79b68dd247ef4e31e (patch)
treedabfe401e85a0ca20b327b0fb2dbb2f1f02ffe61 /source3/libsmb
parent78519b65007d87870ea406315b7f233eba69e155 (diff)
downloadsamba-7f7ebfaecbe3458a4c3e8fc79b68dd247ef4e31e.tar.gz
samba-7f7ebfaecbe3458a4c3e8fc79b68dd247ef4e31e.tar.bz2
samba-7f7ebfaecbe3458a4c3e8fc79b68dd247ef4e31e.zip
Fix bug #6496 - MS-DFS: cannot follow multibyte char link name.
consumed_ucs is the number of bytes of the UCS2 path consumed not counting any terminating null. We need to convert back to unix charset and count again to get the number of bytes consumed from the incoming path.
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/clidfs.c52
1 files changed, 38 insertions, 14 deletions
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index 98b96cfc56..5e944f1aaa 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -603,16 +603,19 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
const char *path,
CLIENT_DFS_REFERRAL**refs,
size_t *num_refs,
- uint16 *consumed)
+ size_t *consumed)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
uint16 setup = TRANSACT2_GET_DFS_REFERRAL;
- char *param;
+ char *param = NULL;
char *rparam=NULL, *rdata=NULL;
char *p;
char *endp;
size_t pathlen = 2*(strlen(path)+1);
+ smb_ucs2_t *path_ucs;
+ char *consumed_path = NULL;
+ uint16_t consumed_ucs;
uint16 num_referrals;
CLIENT_DFS_REFERRAL *referrals = NULL;
bool ret = false;
@@ -622,11 +625,12 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
param = SMB_MALLOC_ARRAY(char, 2+pathlen+2);
if (!param) {
- return false;
+ goto out;
}
SSVAL(param, 0, 0x03); /* max referral level */
p = &param[2];
+ path_ucs = (smb_ucs2_t *)p;
p += clistr_push(cli, p, path, pathlen, STR_TERMINATE);
param_len = PTR_DIFF(p, param);
@@ -637,16 +641,13 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
param, param_len, 2, /* param, length, max */
NULL, 0, cli->max_xmit /* data, length, max */
)) {
- SAFE_FREE(param);
- return false;
+ goto out;
}
- SAFE_FREE(param);
-
if (!cli_receive_trans(cli, SMBtrans2,
&rparam, &param_len,
&rdata, &data_len)) {
- return false;
+ goto out;
}
if (data_len < 4) {
@@ -655,9 +656,30 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
endp = rdata + data_len;
- *consumed = SVAL(rdata, 0);
+ consumed_ucs = SVAL(rdata, 0);
num_referrals = SVAL(rdata, 2);
+ /* consumed_ucs is the number of bytes
+ * of the UCS2 path consumed not counting any
+ * terminating null. We need to convert
+ * back to unix charset and count again
+ * to get the number of bytes consumed from
+ * the incoming path. */
+
+ if (pull_string_talloc(talloc_tos(),
+ NULL,
+ 0,
+ &consumed_path,
+ path_ucs,
+ consumed_ucs,
+ STR_UNICODE) == 0) {
+ goto out;
+ }
+ if (consumed_path == NULL) {
+ goto out;
+ }
+ *consumed = strlen(consumed_path);
+
if (num_referrals != 0) {
uint16 ref_version;
uint16 ref_size;
@@ -714,6 +736,8 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
out:
+ TALLOC_FREE(consumed_path);
+ SAFE_FREE(param);
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return ret;
@@ -732,7 +756,7 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
{
CLIENT_DFS_REFERRAL *refs = NULL;
size_t num_refs = 0;
- uint16 consumed;
+ size_t consumed = 0;
struct cli_state *cli_ipc = NULL;
char *dfs_path = NULL;
char *cleanpath = NULL;
@@ -840,13 +864,13 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
if (!dfs_path) {
return false;
}
- pathlen = strlen(dfs_path)*2;
+ pathlen = strlen(dfs_path);
consumed = MIN(pathlen, consumed);
- *pp_targetpath = talloc_strdup(ctx, &dfs_path[consumed/2]);
+ *pp_targetpath = talloc_strdup(ctx, &dfs_path[consumed]);
if (!*pp_targetpath) {
return false;
}
- dfs_path[consumed/2] = '\0';
+ dfs_path[consumed] = '\0';
/*
* *pp_targetpath is now the unconsumed part of the path.
@@ -963,7 +987,7 @@ static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
{
CLIENT_DFS_REFERRAL *refs = NULL;
size_t num_refs = 0;
- uint16 consumed;
+ size_t consumed = 0;
char *fullpath = NULL;
bool res;
uint16 cnum;