From 7f7ebfaecbe3458a4c3e8fc79b68dd247ef4e31e Mon Sep 17 00:00:00 2001 From: SATOH Fumiyasu Date: Tue, 30 Jun 2009 15:29:08 -0700 Subject: [PATCH] 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. --- 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 49afd8c46681..a3ae1ddad708 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2260,7 +2260,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 98b96cfc5666..5e944f1aaad2 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; -- 2.34.1