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