~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/libsmb/clitrans.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   Unix SMB/CIFS implementation.
3
 
   client transaction calls
4
 
   Copyright (C) Andrew Tridgell 1994-1998
5
 
   
6
 
   This program is free software; you can redistribute it and/or modify
7
 
   it under the terms of the GNU General Public License as published by
8
 
   the Free Software Foundation; either version 2 of the License, or
9
 
   (at your option) any later version.
10
 
   
11
 
   This program is distributed in the hope that it will be useful,
12
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
   GNU General Public License for more details.
15
 
   
16
 
   You should have received a copy of the GNU General Public License
17
 
   along with this program; if not, write to the Free Software
18
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 
*/
20
 
 
21
 
#include "includes.h"
22
 
 
23
 
 
24
 
/****************************************************************************
25
 
 Send a SMB trans or trans2 request.
26
 
****************************************************************************/
27
 
 
28
 
BOOL cli_send_trans(struct cli_state *cli, int trans, 
29
 
                    const char *pipe_name, 
30
 
                    int fid, int flags,
31
 
                    uint16 *setup, unsigned int lsetup, unsigned int msetup,
32
 
                    const char *param, unsigned int lparam, unsigned int mparam,
33
 
                    const char *data, unsigned int ldata, unsigned int mdata)
34
 
{
35
 
        unsigned int i;
36
 
        unsigned int this_ldata,this_lparam;
37
 
        unsigned int tot_data=0,tot_param=0;
38
 
        char *outdata,*outparam;
39
 
        char *p;
40
 
        int pipe_name_len=0;
41
 
        uint16 mid;
42
 
 
43
 
        this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
44
 
        this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
45
 
 
46
 
        memset(cli->outbuf,'\0',smb_size);
47
 
        set_message(cli->outbuf,14+lsetup,0,True);
48
 
        SCVAL(cli->outbuf,smb_com,trans);
49
 
        SSVAL(cli->outbuf,smb_tid, cli->cnum);
50
 
        cli_setup_packet(cli);
51
 
 
52
 
        /*
53
 
         * Save the mid we're using. We need this for finding
54
 
         * signing replies.
55
 
         */
56
 
 
57
 
        mid = cli->mid;
58
 
 
59
 
        if (pipe_name) {
60
 
                pipe_name_len = clistr_push(cli, smb_buf(cli->outbuf), pipe_name, -1, STR_TERMINATE);
61
 
        }
62
 
 
63
 
        outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len : 3);
64
 
        outdata = outparam+this_lparam;
65
 
 
66
 
        /* primary request */
67
 
        SSVAL(cli->outbuf,smb_tpscnt,lparam);   /* tpscnt */
68
 
        SSVAL(cli->outbuf,smb_tdscnt,ldata);    /* tdscnt */
69
 
        SSVAL(cli->outbuf,smb_mprcnt,mparam);   /* mprcnt */
70
 
        SSVAL(cli->outbuf,smb_mdrcnt,mdata);    /* mdrcnt */
71
 
        SCVAL(cli->outbuf,smb_msrcnt,msetup);   /* msrcnt */
72
 
        SSVAL(cli->outbuf,smb_flags,flags);     /* flags */
73
 
        SIVAL(cli->outbuf,smb_timeout,0);               /* timeout */
74
 
        SSVAL(cli->outbuf,smb_pscnt,this_lparam);       /* pscnt */
75
 
        SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
76
 
        SSVAL(cli->outbuf,smb_dscnt,this_ldata);        /* dscnt */
77
 
        SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
78
 
        SCVAL(cli->outbuf,smb_suwcnt,lsetup);   /* suwcnt */
79
 
        for (i=0;i<lsetup;i++)          /* setup[] */
80
 
                SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
81
 
        p = smb_buf(cli->outbuf);
82
 
        if (trans != SMBtrans) {
83
 
                *p++ = 0;  /* put in a null smb_name */
84
 
                *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
85
 
        }
86
 
        if (this_lparam)                        /* param[] */
87
 
                memcpy(outparam,param,this_lparam);
88
 
        if (this_ldata)                 /* data[] */
89
 
                memcpy(outdata,data,this_ldata);
90
 
        cli_setup_bcc(cli, outdata+this_ldata);
91
 
 
92
 
        show_msg(cli->outbuf);
93
 
 
94
 
        if (!cli_send_smb(cli)) {
95
 
                return False;
96
 
        }
97
 
 
98
 
        if (this_ldata < ldata || this_lparam < lparam) {
99
 
                /* receive interim response */
100
 
                if (!cli_receive_smb(cli) || cli_is_error(cli)) {
101
 
                        return(False);
102
 
                }
103
 
 
104
 
                tot_data = this_ldata;
105
 
                tot_param = this_lparam;
106
 
                
107
 
                while (tot_data < ldata || tot_param < lparam)  {
108
 
                        this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
109
 
                        this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
110
 
 
111
 
                        set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
112
 
                        SCVAL(cli->outbuf,smb_com,(trans==SMBtrans ? SMBtranss : SMBtranss2));
113
 
                        
114
 
                        outparam = smb_buf(cli->outbuf);
115
 
                        outdata = outparam+this_lparam;
116
 
                        
117
 
                        /* secondary request */
118
 
                        SSVAL(cli->outbuf,smb_tpscnt,lparam);   /* tpscnt */
119
 
                        SSVAL(cli->outbuf,smb_tdscnt,ldata);    /* tdscnt */
120
 
                        SSVAL(cli->outbuf,smb_spscnt,this_lparam);      /* pscnt */
121
 
                        SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
122
 
                        SSVAL(cli->outbuf,smb_spsdisp,tot_param);       /* psdisp */
123
 
                        SSVAL(cli->outbuf,smb_sdscnt,this_ldata);       /* dscnt */
124
 
                        SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
125
 
                        SSVAL(cli->outbuf,smb_sdsdisp,tot_data);        /* dsdisp */
126
 
                        if (trans==SMBtrans2)
127
 
                                SSVALS(cli->outbuf,smb_sfid,fid);               /* fid */
128
 
                        if (this_lparam)                        /* param[] */
129
 
                                memcpy(outparam,param+tot_param,this_lparam);
130
 
                        if (this_ldata)                 /* data[] */
131
 
                                memcpy(outdata,data+tot_data,this_ldata);
132
 
                        cli_setup_bcc(cli, outdata+this_ldata);
133
 
                        
134
 
                        /*
135
 
                         * Save the mid we're using. We need this for finding
136
 
                         * signing replies.
137
 
                         */
138
 
                        mid = cli->mid;
139
 
 
140
 
                        show_msg(cli->outbuf);
141
 
                        if (!cli_send_smb(cli)) {
142
 
                                return False;
143
 
                        }
144
 
 
145
 
                        /* Ensure we use the same mid for the secondaries. */
146
 
                        cli->mid = mid;
147
 
                        
148
 
                        tot_data += this_ldata;
149
 
                        tot_param += this_lparam;
150
 
                }
151
 
        }
152
 
 
153
 
        /* Note we're in a trans state. Save the sequence
154
 
         * numbers for replies. */
155
 
 
156
 
        return(True);
157
 
}
158
 
 
159
 
/****************************************************************************
160
 
 Receive a SMB trans or trans2 response allocating the necessary memory.
161
 
****************************************************************************/
162
 
 
163
 
BOOL cli_receive_trans(struct cli_state *cli,int trans,
164
 
                              char **param, unsigned int *param_len,
165
 
                              char **data, unsigned int *data_len)
166
 
{
167
 
        unsigned int total_data=0;
168
 
        unsigned int total_param=0;
169
 
        unsigned int this_data,this_param;
170
 
        NTSTATUS status;
171
 
 
172
 
        *data_len = *param_len = 0;
173
 
 
174
 
        if (!cli_receive_smb(cli)) {
175
 
                return False;
176
 
        }
177
 
 
178
 
        show_msg(cli->inbuf);
179
 
        
180
 
        /* sanity check */
181
 
        if (CVAL(cli->inbuf,smb_com) != trans) {
182
 
                DEBUG(0,("Expected %s response, got command 0x%02x\n",
183
 
                         trans==SMBtrans?"SMBtrans":"SMBtrans2", 
184
 
                         CVAL(cli->inbuf,smb_com)));
185
 
                return(False);
186
 
        }
187
 
 
188
 
        /*
189
 
         * An NT RPC pipe call can return ERRDOS, ERRmoredata
190
 
         * to a trans call. This is not an error and should not
191
 
         * be treated as such. Note that STATUS_NO_MORE_FILES is
192
 
         * returned when a trans2 findfirst/next finishes.
193
 
         */
194
 
        status = cli_nt_error(cli);
195
 
        
196
 
        if (NT_STATUS_IS_ERR(status) || NT_STATUS_EQUAL(status,STATUS_NO_MORE_FILES)) {
197
 
                return False;
198
 
        }
199
 
 
200
 
        /* parse out the lengths */
201
 
        total_data = SVAL(cli->inbuf,smb_tdrcnt);
202
 
        total_param = SVAL(cli->inbuf,smb_tprcnt);
203
 
 
204
 
        /* allocate it */
205
 
        if (total_data!=0) {
206
 
                *data = SMB_REALLOC(*data,total_data);
207
 
                if (!(*data)) {
208
 
                        DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
209
 
                        return False;
210
 
                }
211
 
        }
212
 
 
213
 
        if (total_param!=0) {
214
 
                *param = SMB_REALLOC(*param,total_param);
215
 
                if (!(*param)) {
216
 
                        DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
217
 
                        return False;
218
 
                }
219
 
        }
220
 
 
221
 
        for (;;)  {
222
 
                this_data = SVAL(cli->inbuf,smb_drcnt);
223
 
                this_param = SVAL(cli->inbuf,smb_prcnt);
224
 
 
225
 
                if (this_data + *data_len > total_data ||
226
 
                    this_param + *param_len > total_param) {
227
 
                        DEBUG(1,("Data overflow in cli_receive_trans\n"));
228
 
                        return False;
229
 
                }
230
 
 
231
 
                if (this_data + *data_len < this_data ||
232
 
                                this_data + *data_len < *data_len ||
233
 
                                this_param + *param_len < this_param ||
234
 
                                this_param + *param_len < *param_len) {
235
 
                        DEBUG(1,("Data overflow in cli_receive_trans\n"));
236
 
                        return False;
237
 
                }
238
 
 
239
 
                if (this_data) {
240
 
                        unsigned int data_offset_out = SVAL(cli->inbuf,smb_drdisp);
241
 
                        unsigned int data_offset_in = SVAL(cli->inbuf,smb_droff);
242
 
 
243
 
                        if (data_offset_out > total_data ||
244
 
                                        data_offset_out + this_data > total_data ||
245
 
                                        data_offset_out + this_data < data_offset_out ||
246
 
                                        data_offset_out + this_data < this_data) {
247
 
                                DEBUG(1,("Data overflow in cli_receive_trans\n"));
248
 
                                return False;
249
 
                        }
250
 
                        if (data_offset_in > cli->bufsize ||
251
 
                                        data_offset_in + this_data >  cli->bufsize ||
252
 
                                        data_offset_in + this_data < data_offset_in ||
253
 
                                        data_offset_in + this_data < this_data) {
254
 
                                DEBUG(1,("Data overflow in cli_receive_trans\n"));
255
 
                                return False;
256
 
                        }
257
 
 
258
 
                        memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
259
 
                }
260
 
                if (this_param) {
261
 
                        unsigned int param_offset_out = SVAL(cli->inbuf,smb_prdisp);
262
 
                        unsigned int param_offset_in = SVAL(cli->inbuf,smb_proff);
263
 
 
264
 
                        if (param_offset_out > total_param ||
265
 
                                        param_offset_out + this_param > total_param ||
266
 
                                        param_offset_out + this_param < param_offset_out ||
267
 
                                        param_offset_out + this_param < this_param) {
268
 
                                DEBUG(1,("Param overflow in cli_receive_trans\n"));
269
 
                                return False;
270
 
                        }
271
 
                        if (param_offset_in > cli->bufsize ||
272
 
                                        param_offset_in + this_param >  cli->bufsize ||
273
 
                                        param_offset_in + this_param < param_offset_in ||
274
 
                                        param_offset_in + this_param < this_param) {
275
 
                                DEBUG(1,("Param overflow in cli_receive_trans\n"));
276
 
                                return False;
277
 
                        }
278
 
 
279
 
                        memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
280
 
                }
281
 
                *data_len += this_data;
282
 
                *param_len += this_param;
283
 
 
284
 
                if (total_data <= *data_len && total_param <= *param_len)
285
 
                        break;
286
 
                
287
 
                if (!cli_receive_smb(cli)) {
288
 
                        return False;   
289
 
                }
290
 
 
291
 
                show_msg(cli->inbuf);
292
 
                
293
 
                /* sanity check */
294
 
                if (CVAL(cli->inbuf,smb_com) != trans) {
295
 
                        DEBUG(0,("Expected %s response, got command 0x%02x\n",
296
 
                                 trans==SMBtrans?"SMBtrans":"SMBtrans2", 
297
 
                                 CVAL(cli->inbuf,smb_com)));
298
 
                        return(False);
299
 
                }
300
 
                if (NT_STATUS_IS_ERR(cli_nt_error(cli))) {
301
 
                        return(False);
302
 
                }
303
 
 
304
 
                /* parse out the total lengths again - they can shrink! */
305
 
                if (SVAL(cli->inbuf,smb_tdrcnt) < total_data)
306
 
                        total_data = SVAL(cli->inbuf,smb_tdrcnt);
307
 
                if (SVAL(cli->inbuf,smb_tprcnt) < total_param)
308
 
                        total_param = SVAL(cli->inbuf,smb_tprcnt);
309
 
                
310
 
                if (total_data <= *data_len && total_param <= *param_len)
311
 
                        break;
312
 
                
313
 
        }
314
 
 
315
 
        return(True);
316
 
}
317
 
 
318
 
/****************************************************************************
319
 
 Send a SMB nttrans request.
320
 
****************************************************************************/
321
 
 
322
 
BOOL cli_send_nt_trans(struct cli_state *cli, 
323
 
                       int function, 
324
 
                       int flags,
325
 
                       uint16 *setup, unsigned int lsetup, unsigned int msetup,
326
 
                       char *param, unsigned int lparam, unsigned int mparam,
327
 
                       char *data, unsigned int ldata, unsigned int mdata)
328
 
{
329
 
        unsigned int i;
330
 
        unsigned int this_ldata,this_lparam;
331
 
        unsigned int tot_data=0,tot_param=0;
332
 
        uint16 mid;
333
 
        char *outdata,*outparam;
334
 
 
335
 
        this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
336
 
        this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
337
 
 
338
 
        memset(cli->outbuf,'\0',smb_size);
339
 
        set_message(cli->outbuf,19+lsetup,0,True);
340
 
        SCVAL(cli->outbuf,smb_com,SMBnttrans);
341
 
        SSVAL(cli->outbuf,smb_tid, cli->cnum);
342
 
        cli_setup_packet(cli);
343
 
 
344
 
        /*
345
 
         * Save the mid we're using. We need this for finding
346
 
         * signing replies.
347
 
         */
348
 
 
349
 
        mid = cli->mid;
350
 
 
351
 
        outparam = smb_buf(cli->outbuf)+3;
352
 
        outdata = outparam+this_lparam;
353
 
 
354
 
        /* primary request */
355
 
        SCVAL(cli->outbuf,smb_nt_MaxSetupCount,msetup);
356
 
        SCVAL(cli->outbuf,smb_nt_Flags,flags);
357
 
        SIVAL(cli->outbuf,smb_nt_TotalParameterCount, lparam);
358
 
        SIVAL(cli->outbuf,smb_nt_TotalDataCount, ldata);
359
 
        SIVAL(cli->outbuf,smb_nt_MaxParameterCount, mparam);
360
 
        SIVAL(cli->outbuf,smb_nt_MaxDataCount, mdata);
361
 
        SIVAL(cli->outbuf,smb_nt_ParameterCount, this_lparam);
362
 
        SIVAL(cli->outbuf,smb_nt_ParameterOffset, smb_offset(outparam,cli->outbuf));
363
 
        SIVAL(cli->outbuf,smb_nt_DataCount, this_ldata);
364
 
        SIVAL(cli->outbuf,smb_nt_DataOffset, smb_offset(outdata,cli->outbuf));
365
 
        SIVAL(cli->outbuf,smb_nt_SetupCount, lsetup);
366
 
        SIVAL(cli->outbuf,smb_nt_Function, function);
367
 
        for (i=0;i<lsetup;i++)          /* setup[] */
368
 
                SSVAL(cli->outbuf,smb_nt_SetupStart+i*2,setup[i]);
369
 
        
370
 
        if (this_lparam)                        /* param[] */
371
 
                memcpy(outparam,param,this_lparam);
372
 
        if (this_ldata)                 /* data[] */
373
 
                memcpy(outdata,data,this_ldata);
374
 
 
375
 
        cli_setup_bcc(cli, outdata+this_ldata);
376
 
 
377
 
        show_msg(cli->outbuf);
378
 
        if (!cli_send_smb(cli)) {
379
 
                return False;
380
 
        }       
381
 
 
382
 
        if (this_ldata < ldata || this_lparam < lparam) {
383
 
                /* receive interim response */
384
 
                if (!cli_receive_smb(cli) || cli_is_error(cli)) {
385
 
                        return(False);
386
 
                }
387
 
 
388
 
                tot_data = this_ldata;
389
 
                tot_param = this_lparam;
390
 
                
391
 
                while (tot_data < ldata || tot_param < lparam)  {
392
 
                        this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
393
 
                        this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
394
 
 
395
 
                        set_message(cli->outbuf,18,0,True);
396
 
                        SCVAL(cli->outbuf,smb_com,SMBnttranss);
397
 
 
398
 
                        /* XXX - these should probably be aligned */
399
 
                        outparam = smb_buf(cli->outbuf);
400
 
                        outdata = outparam+this_lparam;
401
 
                        
402
 
                        /* secondary request */
403
 
                        SIVAL(cli->outbuf,smb_nts_TotalParameterCount,lparam);
404
 
                        SIVAL(cli->outbuf,smb_nts_TotalDataCount,ldata);
405
 
                        SIVAL(cli->outbuf,smb_nts_ParameterCount,this_lparam);
406
 
                        SIVAL(cli->outbuf,smb_nts_ParameterOffset,smb_offset(outparam,cli->outbuf));
407
 
                        SIVAL(cli->outbuf,smb_nts_ParameterDisplacement,tot_param);
408
 
                        SIVAL(cli->outbuf,smb_nts_DataCount,this_ldata);
409
 
                        SIVAL(cli->outbuf,smb_nts_DataOffset,smb_offset(outdata,cli->outbuf));
410
 
                        SIVAL(cli->outbuf,smb_nts_DataDisplacement,tot_data);
411
 
                        if (this_lparam)                        /* param[] */
412
 
                                memcpy(outparam,param+tot_param,this_lparam);
413
 
                        if (this_ldata)                 /* data[] */
414
 
                                memcpy(outdata,data+tot_data,this_ldata);
415
 
                        cli_setup_bcc(cli, outdata+this_ldata);
416
 
                        
417
 
                        /*
418
 
                         * Save the mid we're using. We need this for finding
419
 
                         * signing replies.
420
 
                         */
421
 
                        mid = cli->mid;
422
 
 
423
 
                        show_msg(cli->outbuf);
424
 
 
425
 
                        if (!cli_send_smb(cli)) {
426
 
                                return False;
427
 
                        }
428
 
                        
429
 
                        /* Ensure we use the same mid for the secondaries. */
430
 
                        cli->mid = mid;
431
 
                        
432
 
                        tot_data += this_ldata;
433
 
                        tot_param += this_lparam;
434
 
                }
435
 
        }
436
 
 
437
 
        /* Note we're in a trans state. Save the sequence
438
 
         * numbers for replies. */
439
 
 
440
 
        return(True);
441
 
}
442
 
 
443
 
/****************************************************************************
444
 
 Receive a SMB nttrans response allocating the necessary memory.
445
 
****************************************************************************/
446
 
 
447
 
BOOL cli_receive_nt_trans(struct cli_state *cli,
448
 
                          char **param, unsigned int *param_len,
449
 
                          char **data, unsigned int *data_len)
450
 
{
451
 
        unsigned int total_data=0;
452
 
        unsigned int total_param=0;
453
 
        unsigned int this_data,this_param;
454
 
        uint8 eclass;
455
 
        uint32 ecode;
456
 
 
457
 
        *data_len = *param_len = 0;
458
 
 
459
 
        if (!cli_receive_smb(cli)) {
460
 
                return False;
461
 
        }
462
 
 
463
 
        show_msg(cli->inbuf);
464
 
        
465
 
        /* sanity check */
466
 
        if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
467
 
                DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
468
 
                         CVAL(cli->inbuf,smb_com)));
469
 
                return(False);
470
 
        }
471
 
 
472
 
        /*
473
 
         * An NT RPC pipe call can return ERRDOS, ERRmoredata
474
 
         * to a trans call. This is not an error and should not
475
 
         * be treated as such.
476
 
         */
477
 
        if (cli_is_dos_error(cli)) {
478
 
                cli_dos_error(cli, &eclass, &ecode);
479
 
                if (!(eclass == ERRDOS && ecode == ERRmoredata)) {
480
 
                        return(False);
481
 
                }
482
 
        }
483
 
 
484
 
        /*
485
 
         * Likewise for NT_STATUS_BUFFER_TOO_SMALL
486
 
         */
487
 
        if (cli_is_nt_error(cli)) {
488
 
                if (!NT_STATUS_EQUAL(cli_nt_error(cli),
489
 
                                     NT_STATUS_BUFFER_TOO_SMALL)) {
490
 
                        return(False);
491
 
                }
492
 
        }
493
 
 
494
 
        /* parse out the lengths */
495
 
        total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount);
496
 
        total_param = SVAL(cli->inbuf,smb_ntr_TotalParameterCount);
497
 
 
498
 
        /* allocate it */
499
 
        if (total_data) {
500
 
                *data = SMB_REALLOC(*data,total_data);
501
 
                if (!(*data)) {
502
 
                        DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
503
 
                        return False;
504
 
                }
505
 
        }
506
 
 
507
 
        if (total_param) {
508
 
                *param = SMB_REALLOC(*param,total_param);
509
 
                if (!(*param)) {
510
 
                        DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
511
 
                        return False;
512
 
                }
513
 
        }
514
 
 
515
 
        while (1)  {
516
 
                this_data = SVAL(cli->inbuf,smb_ntr_DataCount);
517
 
                this_param = SVAL(cli->inbuf,smb_ntr_ParameterCount);
518
 
 
519
 
                if (this_data + *data_len > total_data ||
520
 
                    this_param + *param_len > total_param) {
521
 
                        DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
522
 
                        return False;
523
 
                }
524
 
 
525
 
                if (this_data + *data_len < this_data ||
526
 
                                this_data + *data_len < *data_len ||
527
 
                                this_param + *param_len < this_param ||
528
 
                                this_param + *param_len < *param_len) {
529
 
                        DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
530
 
                        return False;
531
 
                }
532
 
 
533
 
                if (this_data) {
534
 
                        unsigned int data_offset_out = SVAL(cli->inbuf,smb_ntr_DataDisplacement);
535
 
                        unsigned int data_offset_in = SVAL(cli->inbuf,smb_ntr_DataOffset);
536
 
 
537
 
                        if (data_offset_out > total_data ||
538
 
                                        data_offset_out + this_data > total_data ||
539
 
                                        data_offset_out + this_data < data_offset_out ||
540
 
                                        data_offset_out + this_data < this_data) {
541
 
                                DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
542
 
                                return False;
543
 
                        }
544
 
                        if (data_offset_in > cli->bufsize ||
545
 
                                        data_offset_in + this_data >  cli->bufsize ||
546
 
                                        data_offset_in + this_data < data_offset_in ||
547
 
                                        data_offset_in + this_data < this_data) {
548
 
                                DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
549
 
                                return False;
550
 
                        }
551
 
 
552
 
                        memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
553
 
                }
554
 
 
555
 
                if (this_param) {
556
 
                        unsigned int param_offset_out = SVAL(cli->inbuf,smb_ntr_ParameterDisplacement);
557
 
                        unsigned int param_offset_in = SVAL(cli->inbuf,smb_ntr_ParameterOffset);
558
 
 
559
 
                        if (param_offset_out > total_param ||
560
 
                                        param_offset_out + this_param > total_param ||
561
 
                                        param_offset_out + this_param < param_offset_out ||
562
 
                                        param_offset_out + this_param < this_param) {
563
 
                                DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
564
 
                                return False;
565
 
                        }
566
 
                        if (param_offset_in > cli->bufsize ||
567
 
                                        param_offset_in + this_param >  cli->bufsize ||
568
 
                                        param_offset_in + this_param < param_offset_in ||
569
 
                                        param_offset_in + this_param < this_param) {
570
 
                                DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
571
 
                                return False;
572
 
                        }
573
 
 
574
 
                        memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
575
 
                }
576
 
 
577
 
                *data_len += this_data;
578
 
                *param_len += this_param;
579
 
 
580
 
                if (total_data <= *data_len && total_param <= *param_len)
581
 
                        break;
582
 
                
583
 
                if (!cli_receive_smb(cli)) {
584
 
                        return False;
585
 
                }
586
 
 
587
 
                show_msg(cli->inbuf);
588
 
                
589
 
                /* sanity check */
590
 
                if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
591
 
                        DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
592
 
                                 CVAL(cli->inbuf,smb_com)));
593
 
                        return(False);
594
 
                }
595
 
                if (cli_is_dos_error(cli)) {
596
 
                        cli_dos_error(cli, &eclass, &ecode);
597
 
                        if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
598
 
                                return(False);
599
 
                        }
600
 
                }
601
 
                /*
602
 
                 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
603
 
                 */
604
 
                if (cli_is_nt_error(cli)) {
605
 
                        if (!NT_STATUS_EQUAL(cli_nt_error(cli),
606
 
                                             NT_STATUS_BUFFER_TOO_SMALL)) {
607
 
                                return(False);
608
 
                        }
609
 
                }
610
 
 
611
 
                /* parse out the total lengths again - they can shrink! */
612
 
                if (SVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data)
613
 
                        total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount);
614
 
                if (SVAL(cli->inbuf,smb_ntr_TotalParameterCount) < total_param)
615
 
                        total_param = SVAL(cli->inbuf,smb_ntr_TotalParameterCount);
616
 
                
617
 
                if (total_data <= *data_len && total_param <= *param_len)
618
 
                        break;
619
 
        }
620
 
 
621
 
        return(True);
622
 
}