s3:libsmb: use a talloc_stackframe in cli_dfs_get_referral()
[metze/samba/wip.git] / source3 / libsmb / clidfs.c
index 9c0f1f433f7d5712da21d0eff23b3e9523b5cf46..5d97cd3011a7a013bbfca692c291ecbdae90bf8f 100644 (file)
@@ -608,7 +608,8 @@ NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
-       uint16 setup[1];
+       uint16_t setup[1];
+       uint16_t recv_flags2;
        uint8_t *param = NULL;
        uint8_t *rdata = NULL;
        char *p;
@@ -620,13 +621,14 @@ NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
        uint16 num_referrals;
        struct client_dfs_referral *referrals = NULL;
        NTSTATUS status;
+       TALLOC_CTX *frame = talloc_stackframe();
 
        *num_refs = 0;
        *refs = NULL;
 
        SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL);
 
-       param = SMB_MALLOC_ARRAY(uint8_t, 2+pathlen+2);
+       param = talloc_array(talloc_tos(), uint8_t, 2+pathlen+2);
        if (!param) {
                status = NT_STATUS_NO_MEMORY;
                goto out;
@@ -643,16 +645,13 @@ NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
                           setup, 1, 0,
                           param, param_len, 2,
                           NULL, 0, cli->max_xmit,
-                          NULL,
+                          &recv_flags2,
                           NULL, 0, NULL, /* rsetup */
                           NULL, 0, NULL,
                           &rdata, 4, &data_len);
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
        }
-       if (data_len < 4) {
-               goto out;
-       }
 
        endp = (char *)rdata + data_len;
 
@@ -666,6 +665,7 @@ NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
         * to get the number of bytes consumed from
         * the incoming path. */
 
+       errno = 0;
        if (pull_string_talloc(talloc_tos(),
                        NULL,
                        0,
@@ -673,9 +673,15 @@ NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
                        path_ucs,
                        consumed_ucs,
                        STR_UNICODE) == 0) {
+               if (errno != 0) {
+                       status = map_nt_error_from_unix(errno);
+               } else {
+                       status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               }
                goto out;
        }
        if (consumed_path == NULL) {
+               status = map_nt_error_from_unix(errno);
                goto out;
        }
        *consumed = strlen(consumed_path);
@@ -690,6 +696,7 @@ NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
                                         num_referrals);
 
                if (!referrals) {
+                       status = NT_STATUS_NO_MEMORY;
                        goto out;
                }
                /* start at the referrals array */
@@ -712,21 +719,25 @@ NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
                        referrals[i].ttl       = SVAL(p, 10);
 
                        if (p + node_offset > endp) {
+                               status = NT_STATUS_INVALID_NETWORK_RESPONSE;
                                goto out;
                        }
-                       clistr_pull_talloc(ctx, cli->inbuf,
-                                          SVAL(cli->inbuf, smb_flg2),
+                       clistr_pull_talloc(referrals,
+                                          (const char *)rdata,
+                                          recv_flags2,
                                           &referrals[i].dfspath,
                                           p+node_offset,
-                                          cli->bufsize - ((p+node_offset)-cli->inbuf),
+                                          PTR_DIFF(endp, p+node_offset),
                                           STR_TERMINATE|STR_UNICODE);
 
                        if (!referrals[i].dfspath) {
+                               status = map_nt_error_from_unix(errno);
                                goto out;
                        }
                        p += ref_size;
                }
                if (i < num_referrals) {
+                       status = NT_STATUS_INVALID_NETWORK_RESPONSE;
                        goto out;
                }
        }
@@ -736,9 +747,7 @@ NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
 
   out:
 
-       TALLOC_FREE(consumed_path);
-       SAFE_FREE(param);
-       TALLOC_FREE(rdata);
+       TALLOC_FREE(frame);
        return status;
 }