From 21c8ad06b327f6d7a9063dfcd8ce20530b9d5853 Mon Sep 17 00:00:00 2001 From: SATOH Fumiyasu Date: Tue, 8 Sep 2009 16:07:17 -0700 Subject: [PATCH] Fix bug 6496 - libsmbclient: MS-DFS: cannot follow multibyte char link name. A server returns a byte of consumed path in UCS2, not UNIX charset. --- source3/include/proto.h | 2 +- source3/libsmb/clidfs.c | 52 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 18555bc..aea32f9 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2371,7 +2371,7 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx, const char *path, CLIENT_DFS_REFERRAL**refs, size_t *num_refs, - uint16 *consumed); + size_t *consumed); bool cli_resolve_path(TALLOC_CTX *ctx, const char *mountpt, const struct user_auth_info *dfs_auth_info, diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 98b96cf..5e944f1 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 = ¶m[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, ¶m_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; -- 1.5.4.3