s3:torture/test_smb2: also try PROTOCOL_SMB2_24
[mat/samba.git] / libcli / smb / smb1cli_trans.c
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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "system/network.h"
22 #include "../lib/util/tevent_ntstatus.h"
23 #include "../libcli/smb/smb_common.h"
24 #include "../libcli/smb/smbXcli_base.h"
25
26 struct trans_recvblob {
27         uint8_t *data;
28         uint32_t max, total, received;
29 };
30
31 struct smb1cli_trans_state {
32         struct smbXcli_conn *conn;
33         struct tevent_context *ev;
34         uint8_t cmd;
35         uint8_t additional_flags;
36         uint8_t clear_flags;
37         uint16_t additional_flags2;
38         uint16_t clear_flags2;
39         uint32_t timeout_msec;
40         uint16_t mid;
41         uint32_t pid;
42         uint16_t tid;
43         uint16_t uid;
44         const char *pipe_name;
45         uint8_t *pipe_name_conv;
46         size_t pipe_name_conv_len;
47         uint16_t fid;
48         uint16_t function;
49         int flags;
50         uint16_t *setup;
51         uint8_t num_setup, max_setup;
52         uint8_t *param;
53         uint32_t num_param, param_sent;
54         uint8_t *data;
55         uint32_t num_data, data_sent;
56
57         uint8_t num_rsetup;
58         uint16_t *rsetup;
59         struct trans_recvblob rparam;
60         struct trans_recvblob rdata;
61         uint16_t recv_flags2;
62
63         struct iovec iov[6];
64         uint8_t pad[4];
65         uint8_t zero_pad[4];
66         uint16_t vwv[32];
67
68         NTSTATUS status;
69
70         struct tevent_req *primary_subreq;
71 };
72
73 static void smb1cli_trans_cleanup_primary(struct smb1cli_trans_state *state)
74 {
75         if (state->primary_subreq) {
76                 smb1cli_req_set_mid(state->primary_subreq, 0);
77                 smbXcli_req_unset_pending(state->primary_subreq);
78                 TALLOC_FREE(state->primary_subreq);
79         }
80 }
81
82 static int smb1cli_trans_state_destructor(struct smb1cli_trans_state *state)
83 {
84         smb1cli_trans_cleanup_primary(state);
85         return 0;
86 }
87
88 static NTSTATUS smb1cli_pull_trans(uint8_t *inhdr,
89                                    uint8_t wct,
90                                    uint16_t *vwv,
91                                    uint32_t vwv_ofs,
92                                    uint32_t num_bytes,
93                                    uint8_t *bytes,
94                                    uint32_t bytes_ofs,
95                                    uint8_t smb_cmd, bool expect_first_reply,
96                                    uint8_t *pnum_setup, uint16_t **psetup,
97                                    uint32_t *ptotal_param, uint32_t *pnum_param,
98                                    uint32_t *pparam_disp, uint8_t **pparam,
99                                    uint32_t *ptotal_data, uint32_t *pnum_data,
100                                    uint32_t *pdata_disp, uint8_t **pdata)
101 {
102         uint32_t param_ofs, data_ofs;
103         uint8_t expected_num_setup;
104         uint32_t max_bytes = UINT32_MAX - bytes_ofs;
105         uint32_t bytes_end;
106
107         if (num_bytes > max_bytes) {
108                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
109         }
110
111         bytes_end = bytes_ofs + num_bytes;
112
113         if (expect_first_reply) {
114                 if ((wct != 0) || (num_bytes != 0)) {
115                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
116                 }
117                 return NT_STATUS_OK;
118         }
119
120         switch (smb_cmd) {
121         case SMBtrans:
122         case SMBtrans2:
123                 if (wct < 10) {
124                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
125                 }
126                 expected_num_setup = wct - 10;
127                 *ptotal_param   = SVAL(vwv + 0, 0);
128                 *ptotal_data    = SVAL(vwv + 1, 0);
129                 *pnum_param     = SVAL(vwv + 3, 0);
130                 param_ofs       = SVAL(vwv + 4, 0);
131                 *pparam_disp    = SVAL(vwv + 5, 0);
132                 *pnum_data      = SVAL(vwv + 6, 0);
133                 data_ofs        = SVAL(vwv + 7, 0);
134                 *pdata_disp     = SVAL(vwv + 8, 0);
135                 *pnum_setup     = CVAL(vwv + 9, 0);
136                 if (expected_num_setup < (*pnum_setup)) {
137                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
138                 }
139                 *psetup = vwv + 10;
140
141                 break;
142         case SMBnttrans:
143                 if (wct < 18) {
144                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
145                 }
146                 expected_num_setup = wct - 18;
147                 *ptotal_param   = IVAL(vwv, 3);
148                 *ptotal_data    = IVAL(vwv, 7);
149                 *pnum_param     = IVAL(vwv, 11);
150                 param_ofs       = IVAL(vwv, 15);
151                 *pparam_disp    = IVAL(vwv, 19);
152                 *pnum_data      = IVAL(vwv, 23);
153                 data_ofs        = IVAL(vwv, 27);
154                 *pdata_disp     = IVAL(vwv, 31);
155                 *pnum_setup     = CVAL(vwv, 35);
156                 if (expected_num_setup < (*pnum_setup)) {
157                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
158                 }
159                 *psetup         = vwv + 18;
160                 break;
161
162         default:
163                 return NT_STATUS_INTERNAL_ERROR;
164         }
165
166         /*
167          * Check for buffer overflows. data_ofs needs to be checked against
168          * the incoming buffer length, data_disp against the total
169          * length. Likewise for param_ofs/param_disp.
170          */
171
172         if (smb_buffer_oob(bytes_end, param_ofs, *pnum_param)
173             || smb_buffer_oob(*ptotal_param, *pparam_disp, *pnum_param)
174             || smb_buffer_oob(bytes_end, data_ofs, *pnum_data)
175             || smb_buffer_oob(*ptotal_data, *pdata_disp, *pnum_data)) {
176                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
177         }
178
179         *pparam = (uint8_t *)inhdr + param_ofs;
180         *pdata = (uint8_t *)inhdr + data_ofs;
181
182         return NT_STATUS_OK;
183 }
184
185 static NTSTATUS smb1cli_trans_pull_blob(TALLOC_CTX *mem_ctx,
186                                         struct trans_recvblob *blob,
187                                         uint32_t total, uint32_t thistime,
188                                         uint8_t *buf, uint32_t displacement)
189 {
190         if (blob->data == NULL) {
191                 if (total > blob->max) {
192                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
193                 }
194                 blob->total = total;
195                 blob->data = talloc_array(mem_ctx, uint8_t, total);
196                 if (blob->data == NULL) {
197                         return NT_STATUS_NO_MEMORY;
198                 }
199         }
200
201         if (total > blob->total) {
202                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
203         }
204
205         if (thistime) {
206                 memcpy(blob->data + displacement, buf, thistime);
207                 blob->received += thistime;
208         }
209
210         return NT_STATUS_OK;
211 }
212
213 static void smb1cli_trans_format(struct smb1cli_trans_state *state,
214                                  uint8_t *pwct,
215                                  int *piov_count)
216 {
217         uint8_t wct = 0;
218         struct iovec *iov = state->iov;
219         uint8_t *pad = state->pad;
220         uint16_t *vwv = state->vwv;
221         uint32_t param_offset;
222         uint32_t this_param = 0;
223         uint32_t param_pad;
224         uint32_t data_offset;
225         uint32_t this_data = 0;
226         uint32_t data_pad;
227         uint32_t useable_space;
228         uint8_t cmd;
229         uint32_t max_trans = smb1cli_conn_max_xmit(state->conn);
230
231         cmd = state->cmd;
232
233         if ((state->param_sent != 0) || (state->data_sent != 0)) {
234                 /* The secondary commands are one after the primary ones */
235                 cmd += 1;
236         }
237
238         param_offset = MIN_SMB_SIZE;
239
240         switch (cmd) {
241         case SMBtrans:
242                 if (smbXcli_conn_use_unicode(state->conn)) {
243                         pad[0] = 0;
244                         iov[0].iov_base = (void *)pad;
245                         iov[0].iov_len = 1;
246                         param_offset += 1;
247                         iov += 1;
248                 }
249                 iov[0].iov_base = (void *)state->pipe_name_conv;
250                 iov[0].iov_len = state->pipe_name_conv_len;
251                 wct = 14 + state->num_setup;
252                 param_offset += iov[0].iov_len;
253                 iov += 1;
254                 break;
255         case SMBtrans2:
256                 pad[0] = 0;
257                 pad[1] = 'D'; /* Copy this from "old" 3.0 behaviour */
258                 pad[2] = ' ';
259                 iov[0].iov_base = (void *)pad;
260                 iov[0].iov_len = 3;
261                 wct = 14 + state->num_setup;
262                 param_offset += 3;
263                 iov += 1;
264                 break;
265         case SMBtranss:
266                 wct = 8;
267                 break;
268         case SMBtranss2:
269                 wct = 9;
270                 break;
271         case SMBnttrans:
272                 wct = 19 + state->num_setup;
273                 break;
274         case SMBnttranss:
275                 wct = 18;
276                 break;
277         }
278
279         param_offset += wct * sizeof(uint16_t);
280         useable_space = max_trans - param_offset;
281
282         param_pad = param_offset % 4;
283         if (param_pad > 0) {
284                 param_pad = MIN(param_pad, useable_space);
285                 iov[0].iov_base = (void *)state->zero_pad;
286                 iov[0].iov_len = param_pad;
287                 iov += 1;
288                 param_offset += param_pad;
289         }
290         useable_space = max_trans - param_offset;
291
292         if (state->param_sent < state->num_param) {
293                 this_param = MIN(state->num_param - state->param_sent,
294                                  useable_space);
295                 iov[0].iov_base = (void *)(state->param + state->param_sent);
296                 iov[0].iov_len = this_param;
297                 iov += 1;
298         }
299
300         data_offset = param_offset + this_param;
301         useable_space = max_trans - data_offset;
302
303         data_pad = data_offset % 4;
304         if (data_pad > 0) {
305                 data_pad = MIN(data_pad, useable_space);
306                 iov[0].iov_base = (void *)state->zero_pad;
307                 iov[0].iov_len = data_pad;
308                 iov += 1;
309                 data_offset += data_pad;
310         }
311         useable_space = max_trans - data_offset;
312
313         if (state->data_sent < state->num_data) {
314                 this_data = MIN(state->num_data - state->data_sent,
315                                 useable_space);
316                 iov[0].iov_base = (void *)(state->data + state->data_sent);
317                 iov[0].iov_len = this_data;
318                 iov += 1;
319         }
320
321         DEBUG(10, ("num_setup=%u, max_setup=%u, "
322                    "param_total=%u, this_param=%u, max_param=%u, "
323                    "data_total=%u, this_data=%u, max_data=%u, "
324                    "param_offset=%u, param_pad=%u, param_disp=%u, "
325                    "data_offset=%u, data_pad=%u, data_disp=%u\n",
326                    (unsigned)state->num_setup, (unsigned)state->max_setup,
327                    (unsigned)state->num_param, (unsigned)this_param,
328                    (unsigned)state->rparam.max,
329                    (unsigned)state->num_data, (unsigned)this_data,
330                    (unsigned)state->rdata.max,
331                    (unsigned)param_offset, (unsigned)param_pad,
332                    (unsigned)state->param_sent,
333                    (unsigned)data_offset, (unsigned)data_pad,
334                    (unsigned)state->data_sent));
335
336         switch (cmd) {
337         case SMBtrans:
338         case SMBtrans2:
339                 SSVAL(vwv + 0, 0, state->num_param);
340                 SSVAL(vwv + 1, 0, state->num_data);
341                 SSVAL(vwv + 2, 0, state->rparam.max);
342                 SSVAL(vwv + 3, 0, state->rdata.max);
343                 SCVAL(vwv + 4, 0, state->max_setup);
344                 SCVAL(vwv + 4, 1, 0);   /* reserved */
345                 SSVAL(vwv + 5, 0, state->flags);
346                 SIVAL(vwv + 6, 0, 0);   /* timeout */
347                 SSVAL(vwv + 8, 0, 0);   /* reserved */
348                 SSVAL(vwv + 9, 0, this_param);
349                 SSVAL(vwv +10, 0, param_offset);
350                 SSVAL(vwv +11, 0, this_data);
351                 SSVAL(vwv +12, 0, data_offset);
352                 SCVAL(vwv +13, 0, state->num_setup);
353                 SCVAL(vwv +13, 1, 0);   /* reserved */
354                 memcpy(vwv + 14, state->setup,
355                        sizeof(uint16_t) * state->num_setup);
356                 break;
357         case SMBtranss:
358         case SMBtranss2:
359                 SSVAL(vwv + 0, 0, state->num_param);
360                 SSVAL(vwv + 1, 0, state->num_data);
361                 SSVAL(vwv + 2, 0, this_param);
362                 SSVAL(vwv + 3, 0, param_offset);
363                 SSVAL(vwv + 4, 0, state->param_sent);
364                 SSVAL(vwv + 5, 0, this_data);
365                 SSVAL(vwv + 6, 0, data_offset);
366                 SSVAL(vwv + 7, 0, state->data_sent);
367                 if (cmd == SMBtranss2) {
368                         SSVAL(vwv + 8, 0, state->fid);
369                 }
370                 break;
371         case SMBnttrans:
372                 SCVAL(vwv + 0, 0, state->max_setup);
373                 SSVAL(vwv + 0, 1, 0); /* reserved */
374                 SIVAL(vwv + 1, 1, state->num_param);
375                 SIVAL(vwv + 3, 1, state->num_data);
376                 SIVAL(vwv + 5, 1, state->rparam.max);
377                 SIVAL(vwv + 7, 1, state->rdata.max);
378                 SIVAL(vwv + 9, 1, this_param);
379                 SIVAL(vwv +11, 1, param_offset);
380                 SIVAL(vwv +13, 1, this_data);
381                 SIVAL(vwv +15, 1, data_offset);
382                 SCVAL(vwv +17, 1, state->num_setup);
383                 SSVAL(vwv +18, 0, state->function);
384                 memcpy(vwv + 19, state->setup,
385                        sizeof(uint16_t) * state->num_setup);
386                 break;
387         case SMBnttranss:
388                 SSVAL(vwv + 0, 0, 0); /* reserved */
389                 SCVAL(vwv + 1, 0, 0); /* reserved */
390                 SIVAL(vwv + 1, 1, state->num_param);
391                 SIVAL(vwv + 3, 1, state->num_data);
392                 SIVAL(vwv + 5, 1, this_param);
393                 SIVAL(vwv + 7, 1, param_offset);
394                 SIVAL(vwv + 9, 1, state->param_sent);
395                 SIVAL(vwv +11, 1, this_data);
396                 SIVAL(vwv +13, 1, data_offset);
397                 SIVAL(vwv +15, 1, state->data_sent);
398                 SCVAL(vwv +17, 1, 0); /* reserved */
399                 break;
400         }
401
402         state->param_sent += this_param;
403         state->data_sent += this_data;
404
405         *pwct = wct;
406         *piov_count = iov - state->iov;
407 }
408
409 static bool smb1cli_trans_cancel(struct tevent_req *req);
410 static void smb1cli_trans_done(struct tevent_req *subreq);
411
412 struct tevent_req *smb1cli_trans_send(
413         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
414         struct smbXcli_conn *conn, uint8_t cmd,
415         uint8_t additional_flags, uint8_t clear_flags,
416         uint16_t additional_flags2, uint16_t clear_flags2,
417         uint32_t timeout_msec,
418         uint32_t pid, uint16_t tid, uint16_t uid,
419         const char *pipe_name, uint16_t fid, uint16_t function, int flags,
420         uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
421         uint8_t *param, uint32_t num_param, uint32_t max_param,
422         uint8_t *data, uint32_t num_data, uint32_t max_data)
423 {
424         struct tevent_req *req, *subreq;
425         struct smb1cli_trans_state *state;
426         int iov_count;
427         uint8_t wct;
428         NTSTATUS status;
429         charset_t charset;
430
431         req = tevent_req_create(mem_ctx, &state,
432                                 struct smb1cli_trans_state);
433         if (req == NULL) {
434                 return NULL;
435         }
436
437         if ((cmd == SMBtrans) || (cmd == SMBtrans2)) {
438                 if ((num_param > 0xffff) || (max_param > 0xffff)
439                     || (num_data > 0xffff) || (max_data > 0xffff)) {
440                         DEBUG(3, ("Attempt to send invalid trans2 request "
441                                   "(setup %u, params %u/%u, data %u/%u)\n",
442                                   (unsigned)num_setup,
443                                   (unsigned)num_param, (unsigned)max_param,
444                                   (unsigned)num_data, (unsigned)max_data));
445                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
446                         return tevent_req_post(req, ev);
447                 }
448         }
449
450         /*
451          * The largest wct will be for nttrans (19+num_setup). Make sure we
452          * don't overflow state->vwv in smb1cli_trans_format.
453          */
454
455         if ((num_setup + 19) > ARRAY_SIZE(state->vwv)) {
456                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
457                 return tevent_req_post(req, ev);
458         }
459
460         state->conn = conn;
461         state->ev = ev;
462         state->cmd = cmd;
463         state->additional_flags = additional_flags;
464         state->clear_flags = clear_flags;
465         state->additional_flags2 = additional_flags2;
466         state->clear_flags2 = clear_flags2;
467         state->timeout_msec = timeout_msec;
468         state->flags = flags;
469         state->num_rsetup = 0;
470         state->rsetup = NULL;
471         state->pid = pid;
472         state->tid = tid;
473         state->uid = uid;
474         ZERO_STRUCT(state->rparam);
475         ZERO_STRUCT(state->rdata);
476
477         if (smbXcli_conn_use_unicode(conn)) {
478                 charset = CH_UTF16LE;
479         } else {
480                 charset = CH_DOS;
481         }
482
483         if ((pipe_name != NULL)
484             && (!convert_string_talloc(state, CH_UNIX, charset,
485                                        pipe_name, strlen(pipe_name) + 1,
486                                        &state->pipe_name_conv,
487                                        &state->pipe_name_conv_len))) {
488                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
489                 return tevent_req_post(req, ev);
490         }
491         state->fid = fid;       /* trans2 */
492         state->function = function; /* nttrans */
493
494         state->setup = setup;
495         state->num_setup = num_setup;
496         state->max_setup = max_setup;
497
498         state->param = param;
499         state->num_param = num_param;
500         state->param_sent = 0;
501         state->rparam.max = max_param;
502
503         state->data = data;
504         state->num_data = num_data;
505         state->data_sent = 0;
506         state->rdata.max = max_data;
507
508         smb1cli_trans_format(state, &wct, &iov_count);
509
510         subreq = smb1cli_req_create(state, ev, conn, cmd,
511                                     state->additional_flags,
512                                     state->clear_flags,
513                                     state->additional_flags2,
514                                     state->clear_flags2,
515                                     state->timeout_msec,
516                                     state->pid, state->tid, state->uid,
517                                     wct, state->vwv,
518                                     iov_count, state->iov);
519         if (tevent_req_nomem(subreq, req)) {
520                 return tevent_req_post(req, ev);
521         }
522         status = smb1cli_req_chain_submit(&subreq, 1);
523         if (tevent_req_nterror(req, status)) {
524                 return tevent_req_post(req, state->ev);
525         }
526         tevent_req_set_callback(subreq, smb1cli_trans_done, req);
527
528         /*
529          * Now get the MID of the primary request
530          * and mark it as persistent. This means
531          * we will able to send and receive multiple
532          * SMB pdus using this MID in both directions
533          * (including correct SMB signing).
534          */
535         state->mid = smb1cli_req_mid(subreq);
536         smb1cli_req_set_mid(subreq, state->mid);
537         state->primary_subreq = subreq;
538         talloc_set_destructor(state, smb1cli_trans_state_destructor);
539
540         tevent_req_set_cancel_fn(req, smb1cli_trans_cancel);
541
542         return req;
543 }
544
545 static bool smb1cli_trans_cancel(struct tevent_req *req)
546 {
547         struct smb1cli_trans_state *state =
548                 tevent_req_data(req,
549                 struct smb1cli_trans_state);
550
551         if (state->primary_subreq == NULL) {
552                 return false;
553         }
554
555         return tevent_req_cancel(state->primary_subreq);
556 }
557
558 static void smb1cli_trans_done2(struct tevent_req *subreq);
559
560 static void smb1cli_trans_done(struct tevent_req *subreq)
561 {
562         struct tevent_req *req =
563                 tevent_req_callback_data(subreq,
564                 struct tevent_req);
565         struct smb1cli_trans_state *state =
566                 tevent_req_data(req,
567                 struct smb1cli_trans_state);
568         NTSTATUS status;
569         bool sent_all;
570         struct iovec *recv_iov = NULL;
571         uint8_t *inhdr;
572         uint8_t wct;
573         uint16_t *vwv;
574         uint32_t vwv_ofs;
575         uint32_t num_bytes;
576         uint8_t *bytes;
577         uint32_t bytes_ofs;
578         uint8_t num_setup       = 0;
579         uint16_t *setup         = NULL;
580         uint32_t total_param    = 0;
581         uint32_t num_param      = 0;
582         uint32_t param_disp     = 0;
583         uint32_t total_data     = 0;
584         uint32_t num_data       = 0;
585         uint32_t data_disp      = 0;
586         uint8_t *param          = NULL;
587         uint8_t *data           = NULL;
588
589         status = smb1cli_req_recv(subreq, state,
590                                   &recv_iov,
591                                   &inhdr,
592                                   &wct,
593                                   &vwv,
594                                   &vwv_ofs,
595                                   &num_bytes,
596                                   &bytes,
597                                   &bytes_ofs,
598                                   NULL, /* pinbuf */
599                                   NULL, 0); /* expected */
600         /*
601          * Do not TALLOC_FREE(subreq) here, we might receive more than
602          * one response for the same mid.
603          */
604
605         /*
606          * We can receive something like STATUS_MORE_ENTRIES, so don't use
607          * !NT_STATUS_IS_OK(status) here.
608          */
609
610         if (NT_STATUS_IS_ERR(status)) {
611                 goto fail;
612         }
613
614         if (recv_iov == NULL) {
615                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
616                 goto fail;
617         }
618         state->status = status;
619
620         sent_all = ((state->param_sent == state->num_param)
621                     && (state->data_sent == state->num_data));
622
623         status = smb1cli_pull_trans(
624                 inhdr, wct, vwv, vwv_ofs,
625                 num_bytes, bytes, bytes_ofs,
626                 state->cmd, !sent_all, &num_setup, &setup,
627                 &total_param, &num_param, &param_disp, &param,
628                 &total_data, &num_data, &data_disp, &data);
629
630         if (!NT_STATUS_IS_OK(status)) {
631                 goto fail;
632         }
633
634         if (!sent_all) {
635                 int iov_count;
636                 struct tevent_req *subreq2;
637
638                 smb1cli_trans_format(state, &wct, &iov_count);
639
640                 subreq2 = smb1cli_req_create(state, state->ev, state->conn,
641                                              state->cmd + 1,
642                                              state->additional_flags,
643                                              state->clear_flags,
644                                              state->additional_flags2,
645                                              state->clear_flags2,
646                                              state->timeout_msec,
647                                              state->pid, state->tid, state->uid,
648                                              wct, state->vwv,
649                                              iov_count, state->iov);
650                 if (tevent_req_nomem(subreq2, req)) {
651                         return;
652                 }
653                 smb1cli_req_set_mid(subreq2, state->mid);
654
655                 status = smb1cli_req_chain_submit(&subreq2, 1);
656
657                 if (!NT_STATUS_IS_OK(status)) {
658                         goto fail;
659                 }
660                 tevent_req_set_callback(subreq2, smb1cli_trans_done2, req);
661
662                 return;
663         }
664
665         status = smb1cli_trans_pull_blob(
666                 state, &state->rparam, total_param, num_param, param,
667                 param_disp);
668
669         if (!NT_STATUS_IS_OK(status)) {
670                 DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status)));
671                 goto fail;
672         }
673
674         status = smb1cli_trans_pull_blob(
675                 state, &state->rdata, total_data, num_data, data,
676                 data_disp);
677
678         if (!NT_STATUS_IS_OK(status)) {
679                 DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status)));
680                 goto fail;
681         }
682
683         if ((state->rparam.total == state->rparam.received)
684             && (state->rdata.total == state->rdata.received)) {
685                 state->recv_flags2 = SVAL(inhdr, HDR_FLG2);
686                 smb1cli_trans_cleanup_primary(state);
687                 tevent_req_done(req);
688                 return;
689         }
690
691         TALLOC_FREE(recv_iov);
692
693         return;
694
695  fail:
696         smb1cli_trans_cleanup_primary(state);
697         tevent_req_nterror(req, status);
698 }
699
700 static void smb1cli_trans_done2(struct tevent_req *subreq2)
701 {
702         struct tevent_req *req =
703                 tevent_req_callback_data(subreq2,
704                 struct tevent_req);
705         struct smb1cli_trans_state *state =
706                 tevent_req_data(req,
707                 struct smb1cli_trans_state);
708         NTSTATUS status;
709         bool sent_all;
710         uint32_t seqnum;
711
712         /*
713          * First backup the seqnum of the secondary request
714          * and attach it to the primary request.
715          */
716         seqnum = smb1cli_req_seqnum(subreq2);
717         smb1cli_req_set_seqnum(state->primary_subreq, seqnum);
718
719         /* This was a one way request */
720         status = smb1cli_req_recv(subreq2, state,
721                                   NULL, /* recv_iov */
722                                   NULL, /* phdr */
723                                   NULL, /* pwct */
724                                   NULL, /* pvwv */
725                                   NULL, /* pvwv_offset */
726                                   NULL, /* pnum_bytes */
727                                   NULL, /* pbytes */
728                                   NULL, /* pbytes_offset */
729                                   NULL, /* pinbuf */
730                                   NULL, 0); /* expected */
731         TALLOC_FREE(subreq2);
732
733         if (!NT_STATUS_IS_OK(status)) {
734                 goto fail;
735         }
736
737         sent_all = ((state->param_sent == state->num_param)
738                     && (state->data_sent == state->num_data));
739
740         if (!sent_all) {
741                 uint8_t wct;
742                 int iov_count;
743
744                 smb1cli_trans_format(state, &wct, &iov_count);
745
746                 subreq2 = smb1cli_req_create(state, state->ev, state->conn,
747                                              state->cmd + 1,
748                                              state->additional_flags,
749                                              state->clear_flags,
750                                              state->additional_flags2,
751                                              state->clear_flags2,
752                                              state->timeout_msec,
753                                              state->pid, state->tid, state->uid,
754                                              wct, state->vwv,
755                                              iov_count, state->iov);
756                 if (tevent_req_nomem(subreq2, req)) {
757                         return;
758                 }
759                 smb1cli_req_set_mid(subreq2, state->mid);
760
761                 status = smb1cli_req_chain_submit(&subreq2, 1);
762
763                 if (!NT_STATUS_IS_OK(status)) {
764                         goto fail;
765                 }
766                 tevent_req_set_callback(subreq2, smb1cli_trans_done2, req);
767                 return;
768         }
769
770         return;
771
772  fail:
773         smb1cli_trans_cleanup_primary(state);
774         tevent_req_nterror(req, status);
775 }
776
777 NTSTATUS smb1cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
778                             uint16_t *recv_flags2,
779                             uint16_t **setup, uint8_t min_setup,
780                             uint8_t *num_setup,
781                             uint8_t **param, uint32_t min_param,
782                             uint32_t *num_param,
783                             uint8_t **data, uint32_t min_data,
784                             uint32_t *num_data)
785 {
786         struct smb1cli_trans_state *state =
787                 tevent_req_data(req,
788                 struct smb1cli_trans_state);
789         NTSTATUS status;
790
791         smb1cli_trans_cleanup_primary(state);
792
793         if (tevent_req_is_nterror(req, &status)) {
794                 if (!NT_STATUS_IS_ERR(status)) {
795                         status = NT_STATUS_INVALID_NETWORK_RESPONSE;
796                 }
797                 tevent_req_received(req);
798                 return status;
799         }
800
801         if ((state->num_rsetup < min_setup)
802             || (state->rparam.total < min_param)
803             || (state->rdata.total < min_data)) {
804                 tevent_req_received(req);
805                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
806         }
807
808         if (recv_flags2 != NULL) {
809                 *recv_flags2 = state->recv_flags2;
810         }
811
812         if (setup != NULL) {
813                 *setup = talloc_move(mem_ctx, &state->rsetup);
814                 *num_setup = state->num_rsetup;
815         } else {
816                 TALLOC_FREE(state->rsetup);
817         }
818
819         if (param != NULL) {
820                 *param = talloc_move(mem_ctx, &state->rparam.data);
821                 *num_param = state->rparam.total;
822         } else {
823                 TALLOC_FREE(state->rparam.data);
824         }
825
826         if (data != NULL) {
827                 *data = talloc_move(mem_ctx, &state->rdata.data);
828                 *num_data = state->rdata.total;
829         } else {
830                 TALLOC_FREE(state->rdata.data);
831         }
832
833         status = state->status;
834         tevent_req_received(req);
835         return status;
836 }
837
838 NTSTATUS smb1cli_trans(TALLOC_CTX *mem_ctx, struct smbXcli_conn *conn,
839                 uint8_t trans_cmd,
840                 uint8_t additional_flags, uint8_t clear_flags,
841                 uint16_t additional_flags2, uint16_t clear_flags2,
842                 uint32_t timeout_msec,
843                 uint32_t pid, uint16_t tid, uint16_t uid,
844                 const char *pipe_name, uint16_t fid, uint16_t function,
845                 int flags,
846                 uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
847                 uint8_t *param, uint32_t num_param, uint32_t max_param,
848                 uint8_t *data, uint32_t num_data, uint32_t max_data,
849                 uint16_t *recv_flags2,
850                 uint16_t **rsetup, uint8_t min_rsetup, uint8_t *num_rsetup,
851                 uint8_t **rparam, uint32_t min_rparam, uint32_t *num_rparam,
852                 uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata)
853 {
854         TALLOC_CTX *frame = talloc_stackframe();
855         struct tevent_context *ev;
856         struct tevent_req *req;
857         NTSTATUS status = NT_STATUS_OK;
858
859         if (smbXcli_conn_has_async_calls(conn)) {
860                 /*
861                  * Can't use sync call while an async call is in flight
862                  */
863                 status = NT_STATUS_INVALID_PARAMETER_MIX;
864                 goto fail;
865         }
866
867         ev = tevent_context_init(frame);
868         if (ev == NULL) {
869                 status = NT_STATUS_NO_MEMORY;
870                 goto fail;
871         }
872
873         req = smb1cli_trans_send(frame, ev, conn, trans_cmd,
874                                  additional_flags, clear_flags,
875                                  additional_flags2, clear_flags2,
876                                  timeout_msec,
877                                  pid, tid, uid,
878                                  pipe_name, fid, function, flags,
879                                  setup, num_setup, max_setup,
880                                  param, num_param, max_param,
881                                  data, num_data, max_data);
882         if (req == NULL) {
883                 status = NT_STATUS_NO_MEMORY;
884                 goto fail;
885         }
886
887         if (!tevent_req_poll(req, ev)) {
888                 status = map_nt_error_from_unix_common(errno);
889                 goto fail;
890         }
891
892         status = smb1cli_trans_recv(req, mem_ctx, recv_flags2,
893                                     rsetup, min_rsetup, num_rsetup,
894                                     rparam, min_rparam, num_rparam,
895                                     rdata, min_rdata, num_rdata);
896  fail:
897         TALLOC_FREE(frame);
898         return status;
899 }