From b689b01422c6fc22c3010dfa29123cdecbc22c51 Mon Sep 17 00:00:00 2001 From: SATOH Fumiyasu Date: Tue, 23 Jun 2009 16:00:29 +0900 Subject: [PATCH] libsmbclient: MS-DFS: cannot follow multibyte char link name A server returns a byte of consumed path in UCS2, not UNIX charset. --- source/libsmb/clidfs.c | 42 ++++++++++++++++++++++++++++-------------- 1 files changed, 28 insertions(+), 14 deletions(-) diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c index 5379ff9..4051e73 100644 --- a/source/libsmb/clidfs.c +++ b/source/libsmb/clidfs.c @@ -713,16 +713,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 consumed_ucs; uint16 num_referrals; CLIENT_DFS_REFERRAL *referrals = NULL; bool ret = false; @@ -732,11 +735,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 = ¶m[2]; + path_ucs = (smb_ucs2_t *)p; p += clistr_push(cli, p, path, pathlen, STR_TERMINATE); param_len = PTR_DIFF(p, param); @@ -747,16 +751,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, ¶m_len, &rdata, &data_len)) { - return false; + goto out; } if (data_len < 4) { @@ -765,9 +766,21 @@ 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); + pull_string_talloc(talloc_tos(), + NULL, + 0, + &consumed_path, + path_ucs, + consumed_ucs, + STR_UNICODE|STR_TERMINATE); + if (consumed_path == NULL) { + goto out; + } + *consumed = strlen(consumed_path); + if (num_referrals != 0) { uint16 ref_version; uint16 ref_size; @@ -823,6 +836,7 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx, out: + SAFE_FREE(param); SAFE_FREE(rdata); SAFE_FREE(rparam); return ret; @@ -840,7 +854,7 @@ bool cli_resolve_path(TALLOC_CTX *ctx, { CLIENT_DFS_REFERRAL *refs = NULL; size_t num_refs = 0; - uint16 consumed; + size_t consumed; struct cli_state *cli_ipc = NULL; char *dfs_path = NULL; char *cleanpath = NULL; @@ -942,13 +956,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. @@ -1060,7 +1074,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; char *fullpath = NULL; bool res; uint16 cnum; -- 1.6.3.1