Fix bug 6496 - libsmbclient: MS-DFS: cannot follow multibyte char link name. A server...
authorSATOH Fumiyasu <fumiyas@osstech.co.jp>
Tue, 8 Sep 2009 23:07:17 +0000 (16:07 -0700)
committerKarolin Seeger <kseeger@samba.org>
Wed, 9 Sep 2009 10:31:47 +0000 (12:31 +0200)
source3/include/proto.h
source3/libsmb/clidfs.c

index 85619eecf793fc13e25a57a0dfae810bc4b553d5..d33a0198e289a19fc068971ad0b47b0bfc0b581d 100644 (file)
@@ -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,
index 98b96cfc566652f34d2ef1e3e5c0a8f546651fb1..5e944f1aaad29d6a3a98ff0780cc54275b5b7fa7 100644 (file)
@@ -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;