smbXcli: pass hdr to smb1cli_pull_raw_error()
[metze/samba/wip.git] / libcli / smb / smbXcli_base.c
1 /*
2    Unix SMB/CIFS implementation.
3    Infrastructure for async SMB client requests
4    Copyright (C) Volker Lendecke 2008
5    Copyright (C) Stefan Metzmacher 2011
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/network.h"
23 #include "../lib/async_req/async_sock.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "../lib/util/tevent_unix.h"
26 #include "lib/util/util_net.h"
27 #include "../libcli/smb/smb_common.h"
28 #include "../libcli/smb/smb_seal.h"
29 #include "../libcli/smb/smb_signing.h"
30 #include "../libcli/smb/read_smb.h"
31 #include "smbXcli_base.h"
32 #include "librpc/ndr/libndr.h"
33
34 struct smbXcli_conn {
35         int fd;
36         struct sockaddr_storage local_ss;
37         struct sockaddr_storage remote_ss;
38         const char *remote_name;
39
40         struct tevent_queue *outgoing;
41         struct tevent_req **pending;
42         struct tevent_req *read_smb_req;
43
44         enum protocol_types protocol;
45         bool allow_signing;
46         bool desire_signing;
47         bool mandatory_signing;
48
49         /*
50          * The incoming dispatch function should return:
51          * - NT_STATUS_RETRY, if more incoming PDUs are expected.
52          * - NT_STATUS_OK, if no more processing is desired, e.g.
53          *                 the dispatch function called
54          *                 tevent_req_done().
55          * - All other return values disconnect the connection.
56          */
57         NTSTATUS (*dispatch_incoming)(struct smbXcli_conn *conn,
58                                       TALLOC_CTX *tmp_mem,
59                                       uint8_t *inbuf);
60
61         struct {
62                 struct {
63                         uint32_t capabilities;
64                         uint32_t max_xmit;
65                 } client;
66
67                 struct {
68                         uint32_t capabilities;
69                         uint32_t max_xmit;
70                         uint16_t max_mux;
71                         uint16_t security_mode;
72                         bool readbraw;
73                         bool writebraw;
74                         bool lockread;
75                         bool writeunlock;
76                         uint32_t session_key;
77                         struct GUID guid;
78                         DATA_BLOB gss_blob;
79                         uint8_t challenge[8];
80                         const char *workgroup;
81                         int time_zone;
82                         NTTIME system_time;
83                 } server;
84
85                 uint32_t capabilities;
86                 uint32_t max_xmit;
87
88                 uint16_t mid;
89
90                 struct smb_signing_state *signing;
91                 struct smb_trans_enc_state *trans_enc;
92         } smb1;
93
94         struct {
95                 struct {
96                         uint16_t security_mode;
97                 } client;
98
99                 struct {
100                         uint32_t capabilities;
101                         uint16_t security_mode;
102                         struct GUID guid;
103                         uint32_t max_trans_size;
104                         uint32_t max_read_size;
105                         uint32_t max_write_size;
106                         NTTIME system_time;
107                         NTTIME start_time;
108                         DATA_BLOB gss_blob;
109                 } server;
110
111                 uint64_t mid;
112         } smb2;
113 };
114
115 struct smbXcli_req_state {
116         struct tevent_context *ev;
117         struct smbXcli_conn *conn;
118
119         uint8_t length_hdr[4];
120
121         bool one_way;
122
123         uint8_t *inbuf;
124
125         struct {
126                 /* Space for the header including the wct */
127                 uint8_t hdr[HDR_VWV];
128
129                 /*
130                  * For normal requests, smb1cli_req_send chooses a mid.
131                  * SecondaryV trans requests need to use the mid of the primary
132                  * request, so we need a place to store it.
133                  * Assume it is set if != 0.
134                  */
135                 uint16_t mid;
136
137                 uint16_t *vwv;
138                 uint8_t bytecount_buf[2];
139
140 #define MAX_SMB_IOV 5
141                 /* length_hdr, hdr, words, byte_count, buffers */
142                 struct iovec iov[1 + 3 + MAX_SMB_IOV];
143                 int iov_count;
144
145                 uint32_t seqnum;
146                 int chain_num;
147                 int chain_length;
148                 struct tevent_req **chained_requests;
149
150                 uint8_t recv_cmd;
151                 NTSTATUS recv_status;
152                 /* always an array of 3 talloc elements */
153                 struct iovec *recv_iov;
154         } smb1;
155
156         struct {
157                 const uint8_t *fixed;
158                 uint16_t fixed_len;
159                 const uint8_t *dyn;
160                 uint32_t dyn_len;
161
162                 uint8_t hdr[64];
163                 uint8_t pad[7]; /* padding space for compounding */
164
165                 /* always an array of 3 talloc elements */
166                 struct iovec *recv_iov;
167         } smb2;
168 };
169
170 static int smbXcli_conn_destructor(struct smbXcli_conn *conn)
171 {
172         /*
173          * NT_STATUS_OK, means we do not notify the callers
174          */
175         smbXcli_conn_disconnect(conn, NT_STATUS_OK);
176
177         if (conn->smb1.trans_enc) {
178                 common_free_encryption_state(&conn->smb1.trans_enc);
179         }
180
181         return 0;
182 }
183
184 struct smbXcli_conn *smbXcli_conn_create(TALLOC_CTX *mem_ctx,
185                                          int fd,
186                                          const char *remote_name,
187                                          enum smb_signing_setting signing_state,
188                                          uint32_t smb1_capabilities)
189 {
190         struct smbXcli_conn *conn = NULL;
191         void *ss = NULL;
192         struct sockaddr *sa = NULL;
193         socklen_t sa_length;
194         int ret;
195
196         conn = talloc_zero(mem_ctx, struct smbXcli_conn);
197         if (!conn) {
198                 return NULL;
199         }
200
201         conn->remote_name = talloc_strdup(conn, remote_name);
202         if (conn->remote_name == NULL) {
203                 goto error;
204         }
205
206         conn->fd = fd;
207
208         ss = (void *)&conn->local_ss;
209         sa = (struct sockaddr *)ss;
210         sa_length = sizeof(conn->local_ss);
211         ret = getsockname(fd, sa, &sa_length);
212         if (ret == -1) {
213                 goto error;
214         }
215         ss = (void *)&conn->remote_ss;
216         sa = (struct sockaddr *)ss;
217         sa_length = sizeof(conn->remote_ss);
218         ret = getpeername(fd, sa, &sa_length);
219         if (ret == -1) {
220                 goto error;
221         }
222
223         conn->outgoing = tevent_queue_create(conn, "smbXcli_outgoing");
224         if (conn->outgoing == NULL) {
225                 goto error;
226         }
227         conn->pending = NULL;
228
229         conn->protocol = PROTOCOL_NONE;
230
231         switch (signing_state) {
232         case SMB_SIGNING_OFF:
233                 /* never */
234                 conn->allow_signing = false;
235                 conn->desire_signing = false;
236                 conn->mandatory_signing = false;
237                 break;
238         case SMB_SIGNING_DEFAULT:
239         case SMB_SIGNING_IF_REQUIRED:
240                 /* if the server requires it */
241                 conn->allow_signing = true;
242                 conn->desire_signing = false;
243                 conn->mandatory_signing = false;
244                 break;
245         case SMB_SIGNING_REQUIRED:
246                 /* always */
247                 conn->allow_signing = true;
248                 conn->desire_signing = true;
249                 conn->mandatory_signing = true;
250                 break;
251         }
252
253         conn->smb1.client.capabilities = smb1_capabilities;
254         conn->smb1.client.max_xmit = UINT16_MAX;
255
256         conn->smb1.capabilities = conn->smb1.client.capabilities;
257         conn->smb1.max_xmit = 1024;
258
259         conn->smb1.mid = 1;
260
261         /* initialise signing */
262         conn->smb1.signing = smb_signing_init(conn,
263                                               conn->allow_signing,
264                                               conn->desire_signing,
265                                               conn->mandatory_signing);
266         if (!conn->smb1.signing) {
267                 goto error;
268         }
269
270         conn->smb2.client.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
271         if (conn->mandatory_signing) {
272                 conn->smb2.client.security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
273         }
274
275         talloc_set_destructor(conn, smbXcli_conn_destructor);
276         return conn;
277
278  error:
279         TALLOC_FREE(conn);
280         return NULL;
281 }
282
283 bool smbXcli_conn_is_connected(struct smbXcli_conn *conn)
284 {
285         if (conn == NULL) {
286                 return false;
287         }
288
289         if (conn->fd == -1) {
290                 return false;
291         }
292
293         return true;
294 }
295
296 enum protocol_types smbXcli_conn_protocol(struct smbXcli_conn *conn)
297 {
298         return conn->protocol;
299 }
300
301 bool smbXcli_conn_use_unicode(struct smbXcli_conn *conn)
302 {
303         if (conn->protocol >= PROTOCOL_SMB2_02) {
304                 return true;
305         }
306
307         if (conn->smb1.capabilities & CAP_UNICODE) {
308                 return true;
309         }
310
311         return false;
312 }
313
314 void smbXcli_conn_set_sockopt(struct smbXcli_conn *conn, const char *options)
315 {
316         set_socket_options(conn->fd, options);
317 }
318
319 const struct sockaddr_storage *smbXcli_conn_local_sockaddr(struct smbXcli_conn *conn)
320 {
321         return &conn->local_ss;
322 }
323
324 const struct sockaddr_storage *smbXcli_conn_remote_sockaddr(struct smbXcli_conn *conn)
325 {
326         return &conn->remote_ss;
327 }
328
329 const char *smbXcli_conn_remote_name(struct smbXcli_conn *conn)
330 {
331         return conn->remote_name;
332 }
333
334 bool smb1cli_conn_activate_signing(struct smbXcli_conn *conn,
335                                    const DATA_BLOB user_session_key,
336                                    const DATA_BLOB response)
337 {
338         return smb_signing_activate(conn->smb1.signing,
339                                     user_session_key,
340                                     response);
341 }
342
343 bool smb1cli_conn_check_signing(struct smbXcli_conn *conn,
344                                 const uint8_t *buf, uint32_t seqnum)
345 {
346         return smb_signing_check_pdu(conn->smb1.signing, buf, seqnum);
347 }
348
349 bool smb1cli_conn_signing_is_active(struct smbXcli_conn *conn)
350 {
351         return smb_signing_is_active(conn->smb1.signing);
352 }
353
354 void smb1cli_conn_set_encryption(struct smbXcli_conn *conn,
355                                  struct smb_trans_enc_state *es)
356 {
357         /* Replace the old state, if any. */
358         if (conn->smb1.trans_enc) {
359                 common_free_encryption_state(&conn->smb1.trans_enc);
360         }
361         conn->smb1.trans_enc = es;
362 }
363
364 bool smb1cli_conn_encryption_on(struct smbXcli_conn *conn)
365 {
366         return common_encryption_on(conn->smb1.trans_enc);
367 }
368
369
370 static NTSTATUS smb1cli_pull_raw_error(const uint8_t *hdr)
371 {
372         uint32_t flags2 = SVAL(hdr, HDR_FLG2);
373         NTSTATUS status = NT_STATUS(IVAL(hdr, HDR_RCLS));
374
375         if (NT_STATUS_IS_OK(status)) {
376                 return NT_STATUS_OK;
377         }
378
379         if (flags2 & FLAGS2_32_BIT_ERROR_CODES) {
380                 return status;
381         }
382
383         return NT_STATUS_DOS(CVAL(hdr, HDR_RCLS), SVAL(hdr, HDR_ERR));
384 }
385
386 /**
387  * Figure out if there is an andx command behind the current one
388  * @param[in] buf       The smb buffer to look at
389  * @param[in] ofs       The offset to the wct field that is followed by the cmd
390  * @retval Is there a command following?
391  */
392
393 static bool smb1cli_have_andx_command(const uint8_t *buf,
394                                       uint16_t ofs,
395                                       uint8_t cmd)
396 {
397         uint8_t wct;
398         size_t buflen = talloc_get_size(buf);
399
400         if (!smb1cli_is_andx_req(cmd)) {
401                 return false;
402         }
403
404         if ((ofs == buflen-1) || (ofs == buflen)) {
405                 return false;
406         }
407
408         wct = CVAL(buf, ofs);
409         if (wct < 2) {
410                 /*
411                  * Not enough space for the command and a following pointer
412                  */
413                 return false;
414         }
415         return (CVAL(buf, ofs+1) != 0xff);
416 }
417
418 /**
419  * Is the SMB command able to hold an AND_X successor
420  * @param[in] cmd       The SMB command in question
421  * @retval Can we add a chained request after "cmd"?
422  */
423 bool smb1cli_is_andx_req(uint8_t cmd)
424 {
425         switch (cmd) {
426         case SMBtconX:
427         case SMBlockingX:
428         case SMBopenX:
429         case SMBreadX:
430         case SMBwriteX:
431         case SMBsesssetupX:
432         case SMBulogoffX:
433         case SMBntcreateX:
434                 return true;
435                 break;
436         default:
437                 break;
438         }
439
440         return false;
441 }
442
443 static uint16_t smb1cli_alloc_mid(struct smbXcli_conn *conn)
444 {
445         size_t num_pending = talloc_array_length(conn->pending);
446         uint16_t result;
447
448         while (true) {
449                 size_t i;
450
451                 result = conn->smb1.mid++;
452                 if ((result == 0) || (result == 0xffff)) {
453                         continue;
454                 }
455
456                 for (i=0; i<num_pending; i++) {
457                         if (result == smb1cli_req_mid(conn->pending[i])) {
458                                 break;
459                         }
460                 }
461
462                 if (i == num_pending) {
463                         return result;
464                 }
465         }
466 }
467
468 void smbXcli_req_unset_pending(struct tevent_req *req)
469 {
470         struct smbXcli_req_state *state =
471                 tevent_req_data(req,
472                 struct smbXcli_req_state);
473         struct smbXcli_conn *conn = state->conn;
474         size_t num_pending = talloc_array_length(conn->pending);
475         size_t i;
476
477         if (state->smb1.mid != 0) {
478                 /*
479                  * This is a [nt]trans[2] request which waits
480                  * for more than one reply.
481                  */
482                 return;
483         }
484
485         talloc_set_destructor(req, NULL);
486
487         if (num_pending == 1) {
488                 /*
489                  * The pending read_smb tevent_req is a child of
490                  * conn->pending. So if nothing is pending anymore, we need to
491                  * delete the socket read fde.
492                  */
493                 TALLOC_FREE(conn->pending);
494                 conn->read_smb_req = NULL;
495                 return;
496         }
497
498         for (i=0; i<num_pending; i++) {
499                 if (req == conn->pending[i]) {
500                         break;
501                 }
502         }
503         if (i == num_pending) {
504                 /*
505                  * Something's seriously broken. Just returning here is the
506                  * right thing nevertheless, the point of this routine is to
507                  * remove ourselves from conn->pending.
508                  */
509                 return;
510         }
511
512         /*
513          * Remove ourselves from the conn->pending array
514          */
515         for (; i < (num_pending - 1); i++) {
516                 conn->pending[i] = conn->pending[i+1];
517         }
518
519         /*
520          * No NULL check here, we're shrinking by sizeof(void *), and
521          * talloc_realloc just adjusts the size for this.
522          */
523         conn->pending = talloc_realloc(NULL, conn->pending, struct tevent_req *,
524                                        num_pending - 1);
525         return;
526 }
527
528 static int smbXcli_req_destructor(struct tevent_req *req)
529 {
530         struct smbXcli_req_state *state =
531                 tevent_req_data(req,
532                 struct smbXcli_req_state);
533
534         /*
535          * Make sure we really remove it from
536          * the pending array on destruction.
537          */
538         state->smb1.mid = 0;
539         smbXcli_req_unset_pending(req);
540         return 0;
541 }
542
543 static bool smbXcli_conn_receive_next(struct smbXcli_conn *conn);
544
545 bool smbXcli_req_set_pending(struct tevent_req *req)
546 {
547         struct smbXcli_req_state *state =
548                 tevent_req_data(req,
549                 struct smbXcli_req_state);
550         struct smbXcli_conn *conn;
551         struct tevent_req **pending;
552         size_t num_pending;
553
554         conn = state->conn;
555
556         if (!smbXcli_conn_is_connected(conn)) {
557                 return false;
558         }
559
560         num_pending = talloc_array_length(conn->pending);
561
562         pending = talloc_realloc(conn, conn->pending, struct tevent_req *,
563                                  num_pending+1);
564         if (pending == NULL) {
565                 return false;
566         }
567         pending[num_pending] = req;
568         conn->pending = pending;
569         talloc_set_destructor(req, smbXcli_req_destructor);
570
571         if (!smbXcli_conn_receive_next(conn)) {
572                 /*
573                  * the caller should notify the current request
574                  *
575                  * And all other pending requests get notified
576                  * by smbXcli_conn_disconnect().
577                  */
578                 smbXcli_req_unset_pending(req);
579                 smbXcli_conn_disconnect(conn, NT_STATUS_NO_MEMORY);
580                 return false;
581         }
582
583         return true;
584 }
585
586 static void smbXcli_conn_received(struct tevent_req *subreq);
587
588 static bool smbXcli_conn_receive_next(struct smbXcli_conn *conn)
589 {
590         size_t num_pending = talloc_array_length(conn->pending);
591         struct tevent_req *req;
592         struct smbXcli_req_state *state;
593
594         if (conn->read_smb_req != NULL) {
595                 return true;
596         }
597
598         if (num_pending == 0) {
599                 if (conn->smb2.mid < UINT64_MAX) {
600                         /* no more pending requests, so we are done for now */
601                         return true;
602                 }
603
604                 /*
605                  * If there are no more SMB2 requests possible,
606                  * because we are out of message ids,
607                  * we need to disconnect.
608                  */
609                 smbXcli_conn_disconnect(conn, NT_STATUS_CONNECTION_ABORTED);
610                 return true;
611         }
612
613         req = conn->pending[0];
614         state = tevent_req_data(req, struct smbXcli_req_state);
615
616         /*
617          * We're the first ones, add the read_smb request that waits for the
618          * answer from the server
619          */
620         conn->read_smb_req = read_smb_send(conn->pending, state->ev, conn->fd);
621         if (conn->read_smb_req == NULL) {
622                 return false;
623         }
624         tevent_req_set_callback(conn->read_smb_req, smbXcli_conn_received, conn);
625         return true;
626 }
627
628 void smbXcli_conn_disconnect(struct smbXcli_conn *conn, NTSTATUS status)
629 {
630         if (conn->fd != -1) {
631                 close(conn->fd);
632         }
633         conn->fd = -1;
634
635         /*
636          * Cancel all pending requests. We do not do a for-loop walking
637          * conn->pending because that array changes in
638          * smbXcli_req_unset_pending.
639          */
640         while (talloc_array_length(conn->pending) > 0) {
641                 struct tevent_req *req;
642                 struct smbXcli_req_state *state;
643
644                 req = conn->pending[0];
645                 state = tevent_req_data(req, struct smbXcli_req_state);
646
647                 /*
648                  * We're dead. No point waiting for trans2
649                  * replies.
650                  */
651                 state->smb1.mid = 0;
652
653                 smbXcli_req_unset_pending(req);
654
655                 if (NT_STATUS_IS_OK(status)) {
656                         /* do not notify the callers */
657                         continue;
658                 }
659
660                 /*
661                  * we need to defer the callback, because we may notify more
662                  * then one caller.
663                  */
664                 tevent_req_defer_callback(req, state->ev);
665                 tevent_req_nterror(req, status);
666         }
667 }
668
669 /*
670  * Fetch a smb request's mid. Only valid after the request has been sent by
671  * smb1cli_req_send().
672  */
673 uint16_t smb1cli_req_mid(struct tevent_req *req)
674 {
675         struct smbXcli_req_state *state =
676                 tevent_req_data(req,
677                 struct smbXcli_req_state);
678
679         if (state->smb1.mid != 0) {
680                 return state->smb1.mid;
681         }
682
683         return SVAL(state->smb1.hdr, HDR_MID);
684 }
685
686 void smb1cli_req_set_mid(struct tevent_req *req, uint16_t mid)
687 {
688         struct smbXcli_req_state *state =
689                 tevent_req_data(req,
690                 struct smbXcli_req_state);
691
692         state->smb1.mid = mid;
693 }
694
695 uint32_t smb1cli_req_seqnum(struct tevent_req *req)
696 {
697         struct smbXcli_req_state *state =
698                 tevent_req_data(req,
699                 struct smbXcli_req_state);
700
701         return state->smb1.seqnum;
702 }
703
704 void smb1cli_req_set_seqnum(struct tevent_req *req, uint32_t seqnum)
705 {
706         struct smbXcli_req_state *state =
707                 tevent_req_data(req,
708                 struct smbXcli_req_state);
709
710         state->smb1.seqnum = seqnum;
711 }
712
713 static size_t smbXcli_iov_len(const struct iovec *iov, int count)
714 {
715         size_t result = 0;
716         int i;
717         for (i=0; i<count; i++) {
718                 result += iov[i].iov_len;
719         }
720         return result;
721 }
722
723 static uint8_t *smbXcli_iov_concat(TALLOC_CTX *mem_ctx,
724                                    const struct iovec *iov,
725                                    int count)
726 {
727         size_t len = smbXcli_iov_len(iov, count);
728         size_t copied;
729         uint8_t *buf;
730         int i;
731
732         buf = talloc_array(mem_ctx, uint8_t, len);
733         if (buf == NULL) {
734                 return NULL;
735         }
736         copied = 0;
737         for (i=0; i<count; i++) {
738                 memcpy(buf+copied, iov[i].iov_base, iov[i].iov_len);
739                 copied += iov[i].iov_len;
740         }
741         return buf;
742 }
743
744 static void smb1cli_req_flags(enum protocol_types protocol,
745                               uint32_t smb1_capabilities,
746                               uint8_t smb_command,
747                               uint8_t additional_flags,
748                               uint8_t clear_flags,
749                               uint8_t *_flags,
750                               uint16_t additional_flags2,
751                               uint16_t clear_flags2,
752                               uint16_t *_flags2)
753 {
754         uint8_t flags = 0;
755         uint16_t flags2 = 0;
756
757         if (protocol >= PROTOCOL_LANMAN1) {
758                 flags |= FLAG_CASELESS_PATHNAMES;
759                 flags |= FLAG_CANONICAL_PATHNAMES;
760         }
761
762         if (protocol >= PROTOCOL_LANMAN2) {
763                 flags2 |= FLAGS2_LONG_PATH_COMPONENTS;
764                 flags2 |= FLAGS2_EXTENDED_ATTRIBUTES;
765         }
766
767         if (protocol >= PROTOCOL_NT1) {
768                 flags2 |= FLAGS2_IS_LONG_NAME;
769
770                 if (smb1_capabilities & CAP_UNICODE) {
771                         flags2 |= FLAGS2_UNICODE_STRINGS;
772                 }
773                 if (smb1_capabilities & CAP_STATUS32) {
774                         flags2 |= FLAGS2_32_BIT_ERROR_CODES;
775                 }
776                 if (smb1_capabilities & CAP_EXTENDED_SECURITY) {
777                         flags2 |= FLAGS2_EXTENDED_SECURITY;
778                 }
779         }
780
781         flags |= additional_flags;
782         flags &= ~clear_flags;
783         flags2 |= additional_flags2;
784         flags2 &= ~clear_flags2;
785
786         *_flags = flags;
787         *_flags2 = flags2;
788 }
789
790 struct tevent_req *smb1cli_req_create(TALLOC_CTX *mem_ctx,
791                                       struct tevent_context *ev,
792                                       struct smbXcli_conn *conn,
793                                       uint8_t smb_command,
794                                       uint8_t additional_flags,
795                                       uint8_t clear_flags,
796                                       uint16_t additional_flags2,
797                                       uint16_t clear_flags2,
798                                       uint32_t timeout_msec,
799                                       uint32_t pid,
800                                       uint16_t tid,
801                                       uint16_t uid,
802                                       uint8_t wct, uint16_t *vwv,
803                                       int iov_count,
804                                       struct iovec *bytes_iov)
805 {
806         struct tevent_req *req;
807         struct smbXcli_req_state *state;
808         uint8_t flags = 0;
809         uint16_t flags2 = 0;
810
811         if (iov_count > MAX_SMB_IOV) {
812                 /*
813                  * Should not happen :-)
814                  */
815                 return NULL;
816         }
817
818         req = tevent_req_create(mem_ctx, &state,
819                                 struct smbXcli_req_state);
820         if (req == NULL) {
821                 return NULL;
822         }
823         state->ev = ev;
824         state->conn = conn;
825
826         state->smb1.recv_cmd = 0xFF;
827         state->smb1.recv_status = NT_STATUS_INTERNAL_ERROR;
828         state->smb1.recv_iov = talloc_zero_array(state, struct iovec, 3);
829         if (state->smb1.recv_iov == NULL) {
830                 TALLOC_FREE(req);
831                 return NULL;
832         }
833
834         smb1cli_req_flags(conn->protocol,
835                           conn->smb1.capabilities,
836                           smb_command,
837                           additional_flags,
838                           clear_flags,
839                           &flags,
840                           additional_flags2,
841                           clear_flags2,
842                           &flags2);
843
844         SIVAL(state->smb1.hdr, 0,           SMB_MAGIC);
845         SCVAL(state->smb1.hdr, HDR_COM,     smb_command);
846         SIVAL(state->smb1.hdr, HDR_RCLS,    NT_STATUS_V(NT_STATUS_OK));
847         SCVAL(state->smb1.hdr, HDR_FLG,     flags);
848         SSVAL(state->smb1.hdr, HDR_FLG2,    flags2);
849         SSVAL(state->smb1.hdr, HDR_PIDHIGH, pid >> 16);
850         SSVAL(state->smb1.hdr, HDR_TID,     tid);
851         SSVAL(state->smb1.hdr, HDR_PID,     pid);
852         SSVAL(state->smb1.hdr, HDR_UID,     uid);
853         SSVAL(state->smb1.hdr, HDR_MID,     0); /* this comes later */
854         SSVAL(state->smb1.hdr, HDR_WCT,     wct);
855
856         state->smb1.vwv = vwv;
857
858         SSVAL(state->smb1.bytecount_buf, 0, smbXcli_iov_len(bytes_iov, iov_count));
859
860         state->smb1.iov[0].iov_base = (void *)state->length_hdr;
861         state->smb1.iov[0].iov_len  = sizeof(state->length_hdr);
862         state->smb1.iov[1].iov_base = (void *)state->smb1.hdr;
863         state->smb1.iov[1].iov_len  = sizeof(state->smb1.hdr);
864         state->smb1.iov[2].iov_base = (void *)state->smb1.vwv;
865         state->smb1.iov[2].iov_len  = wct * sizeof(uint16_t);
866         state->smb1.iov[3].iov_base = (void *)state->smb1.bytecount_buf;
867         state->smb1.iov[3].iov_len  = sizeof(uint16_t);
868
869         if (iov_count != 0) {
870                 memcpy(&state->smb1.iov[4], bytes_iov,
871                        iov_count * sizeof(*bytes_iov));
872         }
873         state->smb1.iov_count = iov_count + 4;
874
875         if (timeout_msec > 0) {
876                 struct timeval endtime;
877
878                 endtime = timeval_current_ofs_msec(timeout_msec);
879                 if (!tevent_req_set_endtime(req, ev, endtime)) {
880                         return req;
881                 }
882         }
883
884         switch (smb_command) {
885         case SMBtranss:
886         case SMBtranss2:
887         case SMBnttranss:
888         case SMBntcancel:
889                 state->one_way = true;
890                 break;
891         case SMBlockingX:
892                 if ((wct == 8) &&
893                     (CVAL(vwv+3, 0) == LOCKING_ANDX_OPLOCK_RELEASE)) {
894                         state->one_way = true;
895                 }
896                 break;
897         }
898
899         return req;
900 }
901
902 static NTSTATUS smb1cli_conn_signv(struct smbXcli_conn *conn,
903                                    struct iovec *iov, int iov_count,
904                                    uint32_t *seqnum)
905 {
906         uint8_t *buf;
907
908         /*
909          * Obvious optimization: Make cli_calculate_sign_mac work with struct
910          * iovec directly. MD5Update would do that just fine.
911          */
912
913         if (iov_count < 4) {
914                 return NT_STATUS_INVALID_PARAMETER_MIX;
915         }
916         if (iov[0].iov_len != NBT_HDR_SIZE) {
917                 return NT_STATUS_INVALID_PARAMETER_MIX;
918         }
919         if (iov[1].iov_len != (MIN_SMB_SIZE-sizeof(uint16_t))) {
920                 return NT_STATUS_INVALID_PARAMETER_MIX;
921         }
922         if (iov[2].iov_len > (0xFF * sizeof(uint16_t))) {
923                 return NT_STATUS_INVALID_PARAMETER_MIX;
924         }
925         if (iov[3].iov_len != sizeof(uint16_t)) {
926                 return NT_STATUS_INVALID_PARAMETER_MIX;
927         }
928
929         buf = smbXcli_iov_concat(talloc_tos(), iov, iov_count);
930         if (buf == NULL) {
931                 return NT_STATUS_NO_MEMORY;
932         }
933
934         *seqnum = smb_signing_next_seqnum(conn->smb1.signing, false);
935         smb_signing_sign_pdu(conn->smb1.signing, buf, *seqnum);
936         memcpy(iov[1].iov_base, buf+4, iov[1].iov_len);
937
938         TALLOC_FREE(buf);
939         return NT_STATUS_OK;
940 }
941
942 static void smb1cli_req_writev_done(struct tevent_req *subreq);
943 static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
944                                                TALLOC_CTX *tmp_mem,
945                                                uint8_t *inbuf);
946
947 static NTSTATUS smb1cli_req_writev_submit(struct tevent_req *req,
948                                           struct smbXcli_req_state *state,
949                                           struct iovec *iov, int iov_count)
950 {
951         struct tevent_req *subreq;
952         NTSTATUS status;
953         uint16_t mid;
954
955         if (!smbXcli_conn_is_connected(state->conn)) {
956                 return NT_STATUS_CONNECTION_DISCONNECTED;
957         }
958
959         if (state->conn->protocol > PROTOCOL_NT1) {
960                 return NT_STATUS_REVISION_MISMATCH;
961         }
962
963         if (iov_count < 4) {
964                 return NT_STATUS_INVALID_PARAMETER_MIX;
965         }
966         if (iov[0].iov_len != NBT_HDR_SIZE) {
967                 return NT_STATUS_INVALID_PARAMETER_MIX;
968         }
969         if (iov[1].iov_len != (MIN_SMB_SIZE-sizeof(uint16_t))) {
970                 return NT_STATUS_INVALID_PARAMETER_MIX;
971         }
972         if (iov[2].iov_len > (0xFF * sizeof(uint16_t))) {
973                 return NT_STATUS_INVALID_PARAMETER_MIX;
974         }
975         if (iov[3].iov_len != sizeof(uint16_t)) {
976                 return NT_STATUS_INVALID_PARAMETER_MIX;
977         }
978
979         if (state->smb1.mid != 0) {
980                 mid = state->smb1.mid;
981         } else {
982                 mid = smb1cli_alloc_mid(state->conn);
983         }
984         SSVAL(iov[1].iov_base, HDR_MID, mid);
985
986         _smb_setlen_nbt(iov[0].iov_base, smbXcli_iov_len(&iov[1], iov_count-1));
987
988         status = smb1cli_conn_signv(state->conn, iov, iov_count,
989                                     &state->smb1.seqnum);
990
991         if (!NT_STATUS_IS_OK(status)) {
992                 return status;
993         }
994
995         /*
996          * If we supported multiple encrytion contexts
997          * here we'd look up based on tid.
998          */
999         if (common_encryption_on(state->conn->smb1.trans_enc)) {
1000                 char *buf, *enc_buf;
1001
1002                 buf = (char *)smbXcli_iov_concat(talloc_tos(), iov, iov_count);
1003                 if (buf == NULL) {
1004                         return NT_STATUS_NO_MEMORY;
1005                 }
1006                 status = common_encrypt_buffer(state->conn->smb1.trans_enc,
1007                                                (char *)buf, &enc_buf);
1008                 TALLOC_FREE(buf);
1009                 if (!NT_STATUS_IS_OK(status)) {
1010                         DEBUG(0, ("Error in encrypting client message: %s\n",
1011                                   nt_errstr(status)));
1012                         return status;
1013                 }
1014                 buf = (char *)talloc_memdup(state, enc_buf,
1015                                             smb_len_nbt(enc_buf)+4);
1016                 SAFE_FREE(enc_buf);
1017                 if (buf == NULL) {
1018                         return NT_STATUS_NO_MEMORY;
1019                 }
1020                 iov[0].iov_base = (void *)buf;
1021                 iov[0].iov_len = talloc_get_size(buf);
1022                 iov_count = 1;
1023         }
1024
1025         if (state->conn->dispatch_incoming == NULL) {
1026                 state->conn->dispatch_incoming = smb1cli_conn_dispatch_incoming;
1027         }
1028
1029         subreq = writev_send(state, state->ev, state->conn->outgoing,
1030                              state->conn->fd, false, iov, iov_count);
1031         if (subreq == NULL) {
1032                 return NT_STATUS_NO_MEMORY;
1033         }
1034         tevent_req_set_callback(subreq, smb1cli_req_writev_done, req);
1035         return NT_STATUS_OK;
1036 }
1037
1038 struct tevent_req *smb1cli_req_send(TALLOC_CTX *mem_ctx,
1039                                     struct tevent_context *ev,
1040                                     struct smbXcli_conn *conn,
1041                                     uint8_t smb_command,
1042                                     uint8_t additional_flags,
1043                                     uint8_t clear_flags,
1044                                     uint16_t additional_flags2,
1045                                     uint16_t clear_flags2,
1046                                     uint32_t timeout_msec,
1047                                     uint32_t pid,
1048                                     uint16_t tid,
1049                                     uint16_t uid,
1050                                     uint8_t wct, uint16_t *vwv,
1051                                     uint32_t num_bytes,
1052                                     const uint8_t *bytes)
1053 {
1054         struct tevent_req *req;
1055         struct iovec iov;
1056         NTSTATUS status;
1057
1058         iov.iov_base = discard_const_p(void, bytes);
1059         iov.iov_len = num_bytes;
1060
1061         req = smb1cli_req_create(mem_ctx, ev, conn, smb_command,
1062                                  additional_flags, clear_flags,
1063                                  additional_flags2, clear_flags2,
1064                                  timeout_msec,
1065                                  pid, tid, uid,
1066                                  wct, vwv, 1, &iov);
1067         if (req == NULL) {
1068                 return NULL;
1069         }
1070         if (!tevent_req_is_in_progress(req)) {
1071                 return tevent_req_post(req, ev);
1072         }
1073         status = smb1cli_req_chain_submit(&req, 1);
1074         if (tevent_req_nterror(req, status)) {
1075                 return tevent_req_post(req, ev);
1076         }
1077         return req;
1078 }
1079
1080 static void smb1cli_req_writev_done(struct tevent_req *subreq)
1081 {
1082         struct tevent_req *req =
1083                 tevent_req_callback_data(subreq,
1084                 struct tevent_req);
1085         struct smbXcli_req_state *state =
1086                 tevent_req_data(req,
1087                 struct smbXcli_req_state);
1088         ssize_t nwritten;
1089         int err;
1090
1091         nwritten = writev_recv(subreq, &err);
1092         TALLOC_FREE(subreq);
1093         if (nwritten == -1) {
1094                 NTSTATUS status = map_nt_error_from_unix_common(err);
1095                 smbXcli_conn_disconnect(state->conn, status);
1096                 return;
1097         }
1098
1099         if (state->one_way) {
1100                 state->inbuf = NULL;
1101                 tevent_req_done(req);
1102                 return;
1103         }
1104
1105         if (!smbXcli_req_set_pending(req)) {
1106                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1107                 return;
1108         }
1109 }
1110
1111 static void smbXcli_conn_received(struct tevent_req *subreq)
1112 {
1113         struct smbXcli_conn *conn =
1114                 tevent_req_callback_data(subreq,
1115                 struct smbXcli_conn);
1116         TALLOC_CTX *frame = talloc_stackframe();
1117         NTSTATUS status;
1118         uint8_t *inbuf;
1119         ssize_t received;
1120         int err;
1121
1122         if (subreq != conn->read_smb_req) {
1123                 DEBUG(1, ("Internal error: cli_smb_received called with "
1124                           "unexpected subreq\n"));
1125                 status = NT_STATUS_INTERNAL_ERROR;
1126                 smbXcli_conn_disconnect(conn, status);
1127                 TALLOC_FREE(frame);
1128                 return;
1129         }
1130         conn->read_smb_req = NULL;
1131
1132         received = read_smb_recv(subreq, frame, &inbuf, &err);
1133         TALLOC_FREE(subreq);
1134         if (received == -1) {
1135                 status = map_nt_error_from_unix_common(err);
1136                 smbXcli_conn_disconnect(conn, status);
1137                 TALLOC_FREE(frame);
1138                 return;
1139         }
1140
1141         status = conn->dispatch_incoming(conn, frame, inbuf);
1142         TALLOC_FREE(frame);
1143         if (NT_STATUS_IS_OK(status)) {
1144                 /*
1145                  * We should not do any more processing
1146                  * as the dispatch function called
1147                  * tevent_req_done().
1148                  */
1149                 return;
1150         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1151                 /*
1152                  * We got an error, so notify all pending requests
1153                  */
1154                 smbXcli_conn_disconnect(conn, status);
1155                 return;
1156         }
1157
1158         /*
1159          * We got NT_STATUS_RETRY, so we may ask for a
1160          * next incoming pdu.
1161          */
1162         if (!smbXcli_conn_receive_next(conn)) {
1163                 smbXcli_conn_disconnect(conn, NT_STATUS_NO_MEMORY);
1164         }
1165 }
1166
1167 static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
1168                                                TALLOC_CTX *tmp_mem,
1169                                                uint8_t *inbuf)
1170 {
1171         struct tevent_req *req;
1172         struct smbXcli_req_state *state;
1173         NTSTATUS status;
1174         size_t num_pending;
1175         size_t i;
1176         uint16_t mid;
1177         bool oplock_break;
1178         const uint8_t *inhdr = inbuf + NBT_HDR_SIZE;
1179
1180         if ((IVAL(inhdr, 0) != SMB_MAGIC) /* 0xFF"SMB" */
1181             && (SVAL(inhdr, 0) != 0x45ff)) /* 0xFF"E" */ {
1182                 DEBUG(10, ("Got non-SMB PDU\n"));
1183                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1184         }
1185
1186         /*
1187          * If we supported multiple encrytion contexts
1188          * here we'd look up based on tid.
1189          */
1190         if (common_encryption_on(conn->smb1.trans_enc)
1191             && (CVAL(inbuf, 0) == 0)) {
1192                 uint16_t enc_ctx_num;
1193
1194                 status = get_enc_ctx_num(inbuf, &enc_ctx_num);
1195                 if (!NT_STATUS_IS_OK(status)) {
1196                         DEBUG(10, ("get_enc_ctx_num returned %s\n",
1197                                    nt_errstr(status)));
1198                         return status;
1199                 }
1200
1201                 if (enc_ctx_num != conn->smb1.trans_enc->enc_ctx_num) {
1202                         DEBUG(10, ("wrong enc_ctx %d, expected %d\n",
1203                                    enc_ctx_num,
1204                                    conn->smb1.trans_enc->enc_ctx_num));
1205                         return NT_STATUS_INVALID_HANDLE;
1206                 }
1207
1208                 status = common_decrypt_buffer(conn->smb1.trans_enc,
1209                                                (char *)inbuf);
1210                 if (!NT_STATUS_IS_OK(status)) {
1211                         DEBUG(10, ("common_decrypt_buffer returned %s\n",
1212                                    nt_errstr(status)));
1213                         return status;
1214                 }
1215         }
1216
1217         mid = SVAL(inhdr, HDR_MID);
1218         num_pending = talloc_array_length(conn->pending);
1219
1220         for (i=0; i<num_pending; i++) {
1221                 if (mid == smb1cli_req_mid(conn->pending[i])) {
1222                         break;
1223                 }
1224         }
1225         if (i == num_pending) {
1226                 /* Dump unexpected reply */
1227                 return NT_STATUS_RETRY;
1228         }
1229
1230         oplock_break = false;
1231
1232         if (mid == 0xffff) {
1233                 /*
1234                  * Paranoia checks that this is really an oplock break request.
1235                  */
1236                 oplock_break = (smb_len_nbt(inbuf) == 51); /* hdr + 8 words */
1237                 oplock_break &= ((CVAL(inhdr, HDR_FLG) & FLAG_REPLY) == 0);
1238                 oplock_break &= (CVAL(inhdr, HDR_COM) == SMBlockingX);
1239                 oplock_break &= (SVAL(inhdr, HDR_VWV+VWV(6)) == 0);
1240                 oplock_break &= (SVAL(inhdr, HDR_VWV+VWV(7)) == 0);
1241
1242                 if (!oplock_break) {
1243                         /* Dump unexpected reply */
1244                         return NT_STATUS_RETRY;
1245                 }
1246         }
1247
1248         req = conn->pending[i];
1249         state = tevent_req_data(req, struct smbXcli_req_state);
1250
1251         if (!oplock_break /* oplock breaks are not signed */
1252             && !smb_signing_check_pdu(conn->smb1.signing,
1253                                       inbuf, state->smb1.seqnum+1)) {
1254                 DEBUG(10, ("cli_check_sign_mac failed\n"));
1255                 return NT_STATUS_ACCESS_DENIED;
1256         }
1257
1258         if (state->smb1.chained_requests != NULL) {
1259                 struct tevent_req **chain = talloc_move(tmp_mem,
1260                                             &state->smb1.chained_requests);
1261                 size_t num_chained = talloc_array_length(chain);
1262
1263                 /*
1264                  * We steal the inbuf to the chain,
1265                  * so that it will stay until all
1266                  * requests of the chain are finished.
1267                  *
1268                  * Each requests in the chain will
1269                  * hold a talloc reference to the chain.
1270                  * This way we do not expose the talloc_reference()
1271                  * behavior to the callers.
1272                  */
1273                 talloc_steal(chain, inbuf);
1274
1275                 for (i=0; i<num_chained; i++) {
1276                         struct tevent_req **ref;
1277
1278                         req = chain[i];
1279                         state = tevent_req_data(req, struct smbXcli_req_state);
1280
1281                         smbXcli_req_unset_pending(req);
1282
1283                         /*
1284                          * as we finish multiple requests here
1285                          * we need to defer the callbacks as
1286                          * they could destroy our current stack state.
1287                          */
1288                         tevent_req_defer_callback(req, state->ev);
1289
1290                         ref = talloc_reference(state, chain);
1291                         if (tevent_req_nomem(ref, req)) {
1292                                 continue;
1293                         }
1294
1295                         state->inbuf = inbuf;
1296                         state->smb1.chain_num = i;
1297                         state->smb1.chain_length = num_chained;
1298
1299                         tevent_req_done(req);
1300                 }
1301                 return NT_STATUS_RETRY;
1302         }
1303
1304         smbXcli_req_unset_pending(req);
1305
1306         state->inbuf = talloc_move(state, &inbuf);
1307         state->smb1.chain_num = 0;
1308         state->smb1.chain_length = 1;
1309
1310         if (talloc_array_length(conn->pending) == 0) {
1311                 tevent_req_done(req);
1312                 return NT_STATUS_OK;
1313         }
1314
1315         tevent_req_defer_callback(req, state->ev);
1316         tevent_req_done(req);
1317         return NT_STATUS_RETRY;
1318 }
1319
1320 NTSTATUS smb1cli_req_recv(struct tevent_req *req,
1321                           TALLOC_CTX *mem_ctx, uint8_t **pinbuf,
1322                           uint8_t min_wct, uint8_t *pwct, uint16_t **pvwv,
1323                           uint32_t *pnum_bytes, uint8_t **pbytes)
1324 {
1325         struct smbXcli_req_state *state =
1326                 tevent_req_data(req,
1327                 struct smbXcli_req_state);
1328         NTSTATUS status = NT_STATUS_OK;
1329         uint8_t cmd, wct;
1330         uint16_t num_bytes;
1331         size_t wct_ofs, bytes_offset;
1332         int i;
1333
1334         if (tevent_req_is_nterror(req, &status)) {
1335                 return status;
1336         }
1337
1338         if (state->inbuf == NULL) {
1339                 if (min_wct != 0) {
1340                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
1341                 }
1342                 if (pinbuf) {
1343                         *pinbuf = NULL;
1344                 }
1345                 if (pwct) {
1346                         *pwct = 0;
1347                 }
1348                 if (pvwv) {
1349                         *pvwv = NULL;
1350                 }
1351                 if (pnum_bytes) {
1352                         *pnum_bytes = 0;
1353                 }
1354                 if (pbytes) {
1355                         *pbytes = NULL;
1356                 }
1357                 /* This was a request without a reply */
1358                 return NT_STATUS_OK;
1359         }
1360
1361         wct_ofs = NBT_HDR_SIZE + HDR_WCT;
1362         cmd = CVAL(state->inbuf, NBT_HDR_SIZE + HDR_COM);
1363
1364         for (i=0; i<state->smb1.chain_num; i++) {
1365                 if (i < state->smb1.chain_num-1) {
1366                         if (cmd == 0xff) {
1367                                 return NT_STATUS_REQUEST_ABORTED;
1368                         }
1369                         if (!smb1cli_is_andx_req(cmd)) {
1370                                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1371                         }
1372                 }
1373
1374                 if (!smb1cli_have_andx_command(state->inbuf, wct_ofs, cmd)) {
1375                         /*
1376                          * This request was not completed because a previous
1377                          * request in the chain had received an error.
1378                          */
1379                         return NT_STATUS_REQUEST_ABORTED;
1380                 }
1381
1382                 cmd = CVAL(state->inbuf, wct_ofs + 1);
1383                 wct_ofs = SVAL(state->inbuf, wct_ofs + 3);
1384
1385                 /*
1386                  * Skip the all-present length field. No overflow, we've just
1387                  * put a 16-bit value into a size_t.
1388                  */
1389                 wct_ofs += 4;
1390
1391                 if (wct_ofs+2 > talloc_get_size(state->inbuf)) {
1392                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
1393                 }
1394         }
1395
1396         status = smb1cli_pull_raw_error(state->inbuf+NBT_HDR_SIZE);
1397
1398         if (!smb1cli_have_andx_command(state->inbuf, wct_ofs, cmd)) {
1399
1400                 if ((cmd == SMBsesssetupX)
1401                     && NT_STATUS_EQUAL(
1402                             status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1403                         /*
1404                          * NT_STATUS_MORE_PROCESSING_REQUIRED is a
1405                          * valid return code for session setup
1406                          */
1407                         goto no_err;
1408                 }
1409
1410                 if (NT_STATUS_IS_ERR(status)) {
1411                         /*
1412                          * The last command takes the error code. All
1413                          * further commands down the requested chain
1414                          * will get a NT_STATUS_REQUEST_ABORTED.
1415                          */
1416                         return status;
1417                 }
1418         } else {
1419                 /*
1420                  * Only the last request in the chain get the returned
1421                  * status.
1422                  */
1423                 status = NT_STATUS_OK;
1424         }
1425
1426 no_err:
1427
1428         wct = CVAL(state->inbuf, wct_ofs);
1429         bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t);
1430         num_bytes = SVAL(state->inbuf, bytes_offset);
1431
1432         if (wct < min_wct) {
1433                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1434         }
1435
1436         /*
1437          * wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes
1438          * is a 16-bit value. So bytes_offset being size_t should be far from
1439          * wrapping.
1440          */
1441         if ((bytes_offset + 2 > talloc_get_size(state->inbuf))
1442             || (bytes_offset > 0xffff)) {
1443                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1444         }
1445
1446         if (pwct != NULL) {
1447                 *pwct = wct;
1448         }
1449         if (pvwv != NULL) {
1450                 *pvwv = (uint16_t *)(state->inbuf + wct_ofs + 1);
1451         }
1452         if (pnum_bytes != NULL) {
1453                 *pnum_bytes = num_bytes;
1454         }
1455         if (pbytes != NULL) {
1456                 *pbytes = (uint8_t *)state->inbuf + bytes_offset + 2;
1457         }
1458         if ((mem_ctx != NULL) && (pinbuf != NULL)) {
1459                 if (state->smb1.chain_num == state->smb1.chain_length-1) {
1460                         *pinbuf = talloc_move(mem_ctx, &state->inbuf);
1461                 } else {
1462                         *pinbuf = state->inbuf;
1463                 }
1464         }
1465
1466         return status;
1467 }
1468
1469 size_t smb1cli_req_wct_ofs(struct tevent_req **reqs, int num_reqs)
1470 {
1471         size_t wct_ofs;
1472         int i;
1473
1474         wct_ofs = HDR_WCT;
1475
1476         for (i=0; i<num_reqs; i++) {
1477                 struct smbXcli_req_state *state;
1478                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1479                 wct_ofs += smbXcli_iov_len(state->smb1.iov+2,
1480                                            state->smb1.iov_count-2);
1481                 wct_ofs = (wct_ofs + 3) & ~3;
1482         }
1483         return wct_ofs;
1484 }
1485
1486 NTSTATUS smb1cli_req_chain_submit(struct tevent_req **reqs, int num_reqs)
1487 {
1488         struct smbXcli_req_state *first_state =
1489                 tevent_req_data(reqs[0],
1490                 struct smbXcli_req_state);
1491         struct smbXcli_req_state *last_state =
1492                 tevent_req_data(reqs[num_reqs-1],
1493                 struct smbXcli_req_state);
1494         struct smbXcli_req_state *state;
1495         size_t wct_offset;
1496         size_t chain_padding = 0;
1497         int i, iovlen;
1498         struct iovec *iov = NULL;
1499         struct iovec *this_iov;
1500         NTSTATUS status;
1501         size_t nbt_len;
1502
1503         if (num_reqs == 1) {
1504                 return smb1cli_req_writev_submit(reqs[0], first_state,
1505                                                  first_state->smb1.iov,
1506                                                  first_state->smb1.iov_count);
1507         }
1508
1509         iovlen = 0;
1510         for (i=0; i<num_reqs; i++) {
1511                 if (!tevent_req_is_in_progress(reqs[i])) {
1512                         return NT_STATUS_INTERNAL_ERROR;
1513                 }
1514
1515                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1516
1517                 if (state->smb1.iov_count < 4) {
1518                         return NT_STATUS_INVALID_PARAMETER_MIX;
1519                 }
1520
1521                 if (i == 0) {
1522                         /*
1523                          * The NBT and SMB header
1524                          */
1525                         iovlen += 2;
1526                 } else {
1527                         /*
1528                          * Chain padding
1529                          */
1530                         iovlen += 1;
1531                 }
1532
1533                 /*
1534                  * words and bytes
1535                  */
1536                 iovlen += state->smb1.iov_count - 2;
1537         }
1538
1539         iov = talloc_zero_array(last_state, struct iovec, iovlen);
1540         if (iov == NULL) {
1541                 return NT_STATUS_NO_MEMORY;
1542         }
1543
1544         first_state->smb1.chained_requests = (struct tevent_req **)talloc_memdup(
1545                 last_state, reqs, sizeof(*reqs) * num_reqs);
1546         if (first_state->smb1.chained_requests == NULL) {
1547                 TALLOC_FREE(iov);
1548                 return NT_STATUS_NO_MEMORY;
1549         }
1550
1551         wct_offset = HDR_WCT;
1552         this_iov = iov;
1553
1554         for (i=0; i<num_reqs; i++) {
1555                 size_t next_padding = 0;
1556                 uint16_t *vwv;
1557
1558                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1559
1560                 if (i < num_reqs-1) {
1561                         if (!smb1cli_is_andx_req(CVAL(state->smb1.hdr, HDR_COM))
1562                             || CVAL(state->smb1.hdr, HDR_WCT) < 2) {
1563                                 TALLOC_FREE(iov);
1564                                 TALLOC_FREE(first_state->smb1.chained_requests);
1565                                 return NT_STATUS_INVALID_PARAMETER_MIX;
1566                         }
1567                 }
1568
1569                 wct_offset += smbXcli_iov_len(state->smb1.iov+2,
1570                                               state->smb1.iov_count-2) + 1;
1571                 if ((wct_offset % 4) != 0) {
1572                         next_padding = 4 - (wct_offset % 4);
1573                 }
1574                 wct_offset += next_padding;
1575                 vwv = state->smb1.vwv;
1576
1577                 if (i < num_reqs-1) {
1578                         struct smbXcli_req_state *next_state =
1579                                 tevent_req_data(reqs[i+1],
1580                                 struct smbXcli_req_state);
1581                         SCVAL(vwv+0, 0, CVAL(next_state->smb1.hdr, HDR_COM));
1582                         SCVAL(vwv+0, 1, 0);
1583                         SSVAL(vwv+1, 0, wct_offset);
1584                 } else if (smb1cli_is_andx_req(CVAL(state->smb1.hdr, HDR_COM))) {
1585                         /* properly end the chain */
1586                         SCVAL(vwv+0, 0, 0xff);
1587                         SCVAL(vwv+0, 1, 0xff);
1588                         SSVAL(vwv+1, 0, 0);
1589                 }
1590
1591                 if (i == 0) {
1592                         /*
1593                          * The NBT and SMB header
1594                          */
1595                         this_iov[0] = state->smb1.iov[0];
1596                         this_iov[1] = state->smb1.iov[1];
1597                         this_iov += 2;
1598                 } else {
1599                         /*
1600                          * This one is a bit subtle. We have to add
1601                          * chain_padding bytes between the requests, and we
1602                          * have to also include the wct field of the
1603                          * subsequent requests. We use the subsequent header
1604                          * for the padding, it contains the wct field in its
1605                          * last byte.
1606                          */
1607                         this_iov[0].iov_len = chain_padding+1;
1608                         this_iov[0].iov_base = (void *)&state->smb1.hdr[
1609                                 sizeof(state->smb1.hdr) - this_iov[0].iov_len];
1610                         memset(this_iov[0].iov_base, 0, this_iov[0].iov_len-1);
1611                         this_iov += 1;
1612                 }
1613
1614                 /*
1615                  * copy the words and bytes
1616                  */
1617                 memcpy(this_iov, state->smb1.iov+2,
1618                        sizeof(struct iovec) * (state->smb1.iov_count-2));
1619                 this_iov += state->smb1.iov_count - 2;
1620                 chain_padding = next_padding;
1621         }
1622
1623         nbt_len = smbXcli_iov_len(&iov[1], iovlen-1);
1624         if (nbt_len > first_state->conn->smb1.max_xmit) {
1625                 TALLOC_FREE(iov);
1626                 TALLOC_FREE(first_state->smb1.chained_requests);
1627                 return NT_STATUS_INVALID_PARAMETER_MIX;
1628         }
1629
1630         status = smb1cli_req_writev_submit(reqs[0], last_state, iov, iovlen);
1631         if (!NT_STATUS_IS_OK(status)) {
1632                 TALLOC_FREE(iov);
1633                 TALLOC_FREE(first_state->smb1.chained_requests);
1634                 return status;
1635         }
1636
1637         for (i=0; i < (num_reqs - 1); i++) {
1638                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1639
1640                 state->smb1.seqnum = last_state->smb1.seqnum;
1641         }
1642
1643         return NT_STATUS_OK;
1644 }
1645
1646 bool smbXcli_conn_has_async_calls(struct smbXcli_conn *conn)
1647 {
1648         return ((tevent_queue_length(conn->outgoing) != 0)
1649                 || (talloc_array_length(conn->pending) != 0));
1650 }
1651
1652 struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
1653                                       struct tevent_context *ev,
1654                                       struct smbXcli_conn *conn,
1655                                       uint16_t cmd,
1656                                       uint32_t additional_flags,
1657                                       uint32_t clear_flags,
1658                                       uint32_t timeout_msec,
1659                                       uint32_t pid,
1660                                       uint32_t tid,
1661                                       uint64_t uid,
1662                                       const uint8_t *fixed,
1663                                       uint16_t fixed_len,
1664                                       const uint8_t *dyn,
1665                                       uint32_t dyn_len)
1666 {
1667         struct tevent_req *req;
1668         struct smbXcli_req_state *state;
1669         uint32_t flags = 0;
1670
1671         req = tevent_req_create(mem_ctx, &state,
1672                                 struct smbXcli_req_state);
1673         if (req == NULL) {
1674                 return NULL;
1675         }
1676
1677         state->ev = ev;
1678         state->conn = conn;
1679
1680         state->smb2.recv_iov = talloc_zero_array(state, struct iovec, 3);
1681         if (state->smb2.recv_iov == NULL) {
1682                 TALLOC_FREE(req);
1683                 return NULL;
1684         }
1685
1686         flags |= additional_flags;
1687         flags &= ~clear_flags;
1688
1689         state->smb2.fixed = fixed;
1690         state->smb2.fixed_len = fixed_len;
1691         state->smb2.dyn = dyn;
1692         state->smb2.dyn_len = dyn_len;
1693
1694         SIVAL(state->smb2.hdr, SMB2_HDR_PROTOCOL_ID,    SMB2_MAGIC);
1695         SSVAL(state->smb2.hdr, SMB2_HDR_LENGTH,         SMB2_HDR_BODY);
1696         SSVAL(state->smb2.hdr, SMB2_HDR_CREDIT_CHARGE,  1);
1697         SIVAL(state->smb2.hdr, SMB2_HDR_STATUS,         NT_STATUS_V(NT_STATUS_OK));
1698         SSVAL(state->smb2.hdr, SMB2_HDR_OPCODE,         cmd);
1699         SSVAL(state->smb2.hdr, SMB2_HDR_CREDIT,         31);
1700         SIVAL(state->smb2.hdr, SMB2_HDR_FLAGS,          flags);
1701         SIVAL(state->smb2.hdr, SMB2_HDR_PID,            pid);
1702         SIVAL(state->smb2.hdr, SMB2_HDR_TID,            tid);
1703         SBVAL(state->smb2.hdr, SMB2_HDR_SESSION_ID,     uid);
1704
1705         switch (cmd) {
1706         case SMB2_OP_CANCEL:
1707                 state->one_way = true;
1708                 break;
1709         case SMB2_OP_BREAK:
1710                 /*
1711                  * If this is a dummy request, it will have
1712                  * UINT64_MAX as message id.
1713                  * If we send on break acknowledgement,
1714                  * this gets overwritten later.
1715                  */
1716                 SBVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
1717                 break;
1718         }
1719
1720         if (timeout_msec > 0) {
1721                 struct timeval endtime;
1722
1723                 endtime = timeval_current_ofs_msec(timeout_msec);
1724                 if (!tevent_req_set_endtime(req, ev, endtime)) {
1725                         return req;
1726                 }
1727         }
1728
1729         return req;
1730 }
1731
1732 static void smb2cli_writev_done(struct tevent_req *subreq);
1733 static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
1734                                                TALLOC_CTX *tmp_mem,
1735                                                uint8_t *inbuf);
1736
1737 NTSTATUS smb2cli_req_compound_submit(struct tevent_req **reqs,
1738                                      int num_reqs)
1739 {
1740         struct smbXcli_req_state *state;
1741         struct tevent_req *subreq;
1742         struct iovec *iov;
1743         int i, num_iov, nbt_len;
1744
1745         /*
1746          * 1 for the nbt length
1747          * per request: HDR, fixed, dyn, padding
1748          * -1 because the last one does not need padding
1749          */
1750
1751         iov = talloc_array(reqs[0], struct iovec, 1 + 4*num_reqs - 1);
1752         if (iov == NULL) {
1753                 return NT_STATUS_NO_MEMORY;
1754         }
1755
1756         num_iov = 1;
1757         nbt_len = 0;
1758
1759         for (i=0; i<num_reqs; i++) {
1760                 size_t reqlen;
1761                 bool ret;
1762                 uint64_t mid;
1763
1764                 if (!tevent_req_is_in_progress(reqs[i])) {
1765                         return NT_STATUS_INTERNAL_ERROR;
1766                 }
1767
1768                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1769
1770                 if (!smbXcli_conn_is_connected(state->conn)) {
1771                         return NT_STATUS_CONNECTION_DISCONNECTED;
1772                 }
1773
1774                 if ((state->conn->protocol != PROTOCOL_NONE) &&
1775                     (state->conn->protocol < PROTOCOL_SMB2_02)) {
1776                         return NT_STATUS_REVISION_MISMATCH;
1777                 }
1778
1779                 if (state->conn->smb2.mid == UINT64_MAX) {
1780                         return NT_STATUS_CONNECTION_ABORTED;
1781                 }
1782
1783                 mid = state->conn->smb2.mid;
1784                 state->conn->smb2.mid += 1;
1785
1786                 SBVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID, mid);
1787
1788                 iov[num_iov].iov_base = state->smb2.hdr;
1789                 iov[num_iov].iov_len  = sizeof(state->smb2.hdr);
1790                 num_iov += 1;
1791
1792                 iov[num_iov].iov_base = discard_const(state->smb2.fixed);
1793                 iov[num_iov].iov_len  = state->smb2.fixed_len;
1794                 num_iov += 1;
1795
1796                 if (state->smb2.dyn != NULL) {
1797                         iov[num_iov].iov_base = discard_const(state->smb2.dyn);
1798                         iov[num_iov].iov_len  = state->smb2.dyn_len;
1799                         num_iov += 1;
1800                 }
1801
1802                 reqlen  = sizeof(state->smb2.hdr);
1803                 reqlen += state->smb2.fixed_len;
1804                 reqlen += state->smb2.dyn_len;
1805
1806                 if (i < num_reqs-1) {
1807                         if ((reqlen % 8) > 0) {
1808                                 uint8_t pad = 8 - (reqlen % 8);
1809                                 iov[num_iov].iov_base = state->smb2.pad;
1810                                 iov[num_iov].iov_len = pad;
1811                                 num_iov += 1;
1812                                 reqlen += pad;
1813                         }
1814                         SIVAL(state->smb2.hdr, SMB2_HDR_NEXT_COMMAND, reqlen);
1815                 }
1816                 nbt_len += reqlen;
1817
1818                 ret = smbXcli_req_set_pending(reqs[i]);
1819                 if (!ret) {
1820                         return NT_STATUS_NO_MEMORY;
1821                 }
1822         }
1823
1824         /*
1825          * TODO: Do signing here
1826          */
1827
1828         state = tevent_req_data(reqs[0], struct smbXcli_req_state);
1829         _smb_setlen_tcp(state->length_hdr, nbt_len);
1830         iov[0].iov_base = state->length_hdr;
1831         iov[0].iov_len  = sizeof(state->length_hdr);
1832
1833         if (state->conn->dispatch_incoming == NULL) {
1834                 state->conn->dispatch_incoming = smb2cli_conn_dispatch_incoming;
1835         }
1836
1837         subreq = writev_send(state, state->ev, state->conn->outgoing,
1838                              state->conn->fd, false, iov, num_iov);
1839         if (subreq == NULL) {
1840                 return NT_STATUS_NO_MEMORY;
1841         }
1842         tevent_req_set_callback(subreq, smb2cli_writev_done, reqs[0]);
1843         return NT_STATUS_OK;
1844 }
1845
1846 struct tevent_req *smb2cli_req_send(TALLOC_CTX *mem_ctx,
1847                                     struct tevent_context *ev,
1848                                     struct smbXcli_conn *conn,
1849                                     uint16_t cmd,
1850                                     uint32_t additional_flags,
1851                                     uint32_t clear_flags,
1852                                     uint32_t timeout_msec,
1853                                     uint32_t pid,
1854                                     uint32_t tid,
1855                                     uint64_t uid,
1856                                     const uint8_t *fixed,
1857                                     uint16_t fixed_len,
1858                                     const uint8_t *dyn,
1859                                     uint32_t dyn_len)
1860 {
1861         struct tevent_req *req;
1862         NTSTATUS status;
1863
1864         req = smb2cli_req_create(mem_ctx, ev, conn, cmd,
1865                                  additional_flags, clear_flags,
1866                                  timeout_msec,
1867                                  pid, tid, uid,
1868                                  fixed, fixed_len, dyn, dyn_len);
1869         if (req == NULL) {
1870                 return NULL;
1871         }
1872         if (!tevent_req_is_in_progress(req)) {
1873                 return tevent_req_post(req, ev);
1874         }
1875         status = smb2cli_req_compound_submit(&req, 1);
1876         if (tevent_req_nterror(req, status)) {
1877                 return tevent_req_post(req, ev);
1878         }
1879         return req;
1880 }
1881
1882 static void smb2cli_writev_done(struct tevent_req *subreq)
1883 {
1884         struct tevent_req *req =
1885                 tevent_req_callback_data(subreq,
1886                 struct tevent_req);
1887         struct smbXcli_req_state *state =
1888                 tevent_req_data(req,
1889                 struct smbXcli_req_state);
1890         ssize_t nwritten;
1891         int err;
1892
1893         nwritten = writev_recv(subreq, &err);
1894         TALLOC_FREE(subreq);
1895         if (nwritten == -1) {
1896                 /* here, we need to notify all pending requests */
1897                 NTSTATUS status = map_nt_error_from_unix_common(err);
1898                 smbXcli_conn_disconnect(state->conn, status);
1899                 return;
1900         }
1901 }
1902
1903 static NTSTATUS smb2cli_inbuf_parse_compound(uint8_t *buf, TALLOC_CTX *mem_ctx,
1904                                              struct iovec **piov, int *pnum_iov)
1905 {
1906         struct iovec *iov;
1907         int num_iov;
1908         size_t buflen;
1909         size_t taken;
1910         uint8_t *first_hdr;
1911
1912         num_iov = 0;
1913
1914         iov = talloc_array(mem_ctx, struct iovec, num_iov);
1915         if (iov == NULL) {
1916                 return NT_STATUS_NO_MEMORY;
1917         }
1918
1919         buflen = smb_len_tcp(buf);
1920         taken = 0;
1921         first_hdr = buf + NBT_HDR_SIZE;
1922
1923         while (taken < buflen) {
1924                 size_t len = buflen - taken;
1925                 uint8_t *hdr = first_hdr + taken;
1926                 struct iovec *cur;
1927                 size_t full_size;
1928                 size_t next_command_ofs;
1929                 uint16_t body_size;
1930                 struct iovec *iov_tmp;
1931
1932                 /*
1933                  * We need the header plus the body length field
1934                  */
1935
1936                 if (len < SMB2_HDR_BODY + 2) {
1937                         DEBUG(10, ("%d bytes left, expected at least %d\n",
1938                                    (int)len, SMB2_HDR_BODY));
1939                         goto inval;
1940                 }
1941                 if (IVAL(hdr, 0) != SMB2_MAGIC) {
1942                         DEBUG(10, ("Got non-SMB2 PDU: %x\n",
1943                                    IVAL(hdr, 0)));
1944                         goto inval;
1945                 }
1946                 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
1947                         DEBUG(10, ("Got HDR len %d, expected %d\n",
1948                                    SVAL(hdr, 4), SMB2_HDR_BODY));
1949                         goto inval;
1950                 }
1951
1952                 full_size = len;
1953                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1954                 body_size = SVAL(hdr, SMB2_HDR_BODY);
1955
1956                 if (next_command_ofs != 0) {
1957                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
1958                                 goto inval;
1959                         }
1960                         if (next_command_ofs > full_size) {
1961                                 goto inval;
1962                         }
1963                         full_size = next_command_ofs;
1964                 }
1965                 if (body_size < 2) {
1966                         goto inval;
1967                 }
1968                 body_size &= 0xfffe;
1969
1970                 if (body_size > (full_size - SMB2_HDR_BODY)) {
1971                         goto inval;
1972                 }
1973
1974                 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
1975                                          num_iov + 3);
1976                 if (iov_tmp == NULL) {
1977                         TALLOC_FREE(iov);
1978                         return NT_STATUS_NO_MEMORY;
1979                 }
1980                 iov = iov_tmp;
1981                 cur = &iov[num_iov];
1982                 num_iov += 3;
1983
1984                 cur[0].iov_base = hdr;
1985                 cur[0].iov_len  = SMB2_HDR_BODY;
1986                 cur[1].iov_base = hdr + SMB2_HDR_BODY;
1987                 cur[1].iov_len  = body_size;
1988                 cur[2].iov_base = hdr + SMB2_HDR_BODY + body_size;
1989                 cur[2].iov_len  = full_size - (SMB2_HDR_BODY + body_size);
1990
1991                 taken += full_size;
1992         }
1993
1994         *piov = iov;
1995         *pnum_iov = num_iov;
1996         return NT_STATUS_OK;
1997
1998 inval:
1999         TALLOC_FREE(iov);
2000         return NT_STATUS_INVALID_NETWORK_RESPONSE;
2001 }
2002
2003 static struct tevent_req *smb2cli_conn_find_pending(struct smbXcli_conn *conn,
2004                                                     uint64_t mid)
2005 {
2006         size_t num_pending = talloc_array_length(conn->pending);
2007         size_t i;
2008
2009         for (i=0; i<num_pending; i++) {
2010                 struct tevent_req *req = conn->pending[i];
2011                 struct smbXcli_req_state *state =
2012                         tevent_req_data(req,
2013                         struct smbXcli_req_state);
2014
2015                 if (mid == BVAL(state->smb2.hdr, SMB2_HDR_MESSAGE_ID)) {
2016                         return req;
2017                 }
2018         }
2019         return NULL;
2020 }
2021
2022 static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
2023                                                TALLOC_CTX *tmp_mem,
2024                                                uint8_t *inbuf)
2025 {
2026         struct tevent_req *req;
2027         struct smbXcli_req_state *state = NULL;
2028         struct iovec *iov;
2029         int i, num_iov;
2030         NTSTATUS status;
2031         bool defer = true;
2032
2033         status = smb2cli_inbuf_parse_compound(inbuf, tmp_mem,
2034                                               &iov, &num_iov);
2035         if (!NT_STATUS_IS_OK(status)) {
2036                 return status;
2037         }
2038
2039         for (i=0; i<num_iov; i+=3) {
2040                 uint8_t *inbuf_ref = NULL;
2041                 struct iovec *cur = &iov[i];
2042                 uint8_t *inhdr = (uint8_t *)cur[0].iov_base;
2043                 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2044                 uint32_t flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2045                 uint64_t mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2046                 uint16_t req_opcode;
2047
2048                 req = smb2cli_conn_find_pending(conn, mid);
2049                 if (req == NULL) {
2050                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
2051                 }
2052                 state = tevent_req_data(req, struct smbXcli_req_state);
2053
2054                 req_opcode = SVAL(state->smb2.hdr, SMB2_HDR_OPCODE);
2055                 if (opcode != req_opcode) {
2056                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
2057                 }
2058
2059                 if (!(flags & SMB2_HDR_FLAG_REDIRECT)) {
2060                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
2061                 }
2062
2063                 status = NT_STATUS(IVAL(inhdr, SMB2_HDR_STATUS));
2064                 if ((flags & SMB2_HDR_FLAG_ASYNC) &&
2065                     NT_STATUS_EQUAL(status, STATUS_PENDING)) {
2066                         uint32_t req_flags = IVAL(state->smb2.hdr, SMB2_HDR_FLAGS);
2067                         uint64_t async_id = BVAL(inhdr, SMB2_HDR_ASYNC_ID);
2068
2069                         req_flags |= SMB2_HDR_FLAG_ASYNC;
2070                         SBVAL(state->smb2.hdr, SMB2_HDR_FLAGS, req_flags);
2071                         SBVAL(state->smb2.hdr, SMB2_HDR_ASYNC_ID, async_id);
2072                         continue;
2073                 }
2074
2075                 smbXcli_req_unset_pending(req);
2076
2077                 /*
2078                  * There might be more than one response
2079                  * we need to defer the notifications
2080                  */
2081                 if ((num_iov == 4) && (talloc_array_length(conn->pending) == 0)) {
2082                         defer = false;
2083                 }
2084
2085                 if (defer) {
2086                         tevent_req_defer_callback(req, state->ev);
2087                 }
2088
2089                 /*
2090                  * Note: here we use talloc_reference() in a way
2091                  *       that does not expose it to the caller.
2092                  */
2093                 inbuf_ref = talloc_reference(state->smb2.recv_iov, inbuf);
2094                 if (tevent_req_nomem(inbuf_ref, req)) {
2095                         continue;
2096                 }
2097
2098                 /* copy the related buffers */
2099                 state->smb2.recv_iov[0] = cur[0];
2100                 state->smb2.recv_iov[1] = cur[1];
2101                 state->smb2.recv_iov[2] = cur[2];
2102
2103                 tevent_req_done(req);
2104         }
2105
2106         if (defer) {
2107                 return NT_STATUS_RETRY;
2108         }
2109
2110         return NT_STATUS_OK;
2111 }
2112
2113 NTSTATUS smb2cli_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2114                           struct iovec **piov,
2115                           const struct smb2cli_req_expected_response *expected,
2116                           size_t num_expected)
2117 {
2118         struct smbXcli_req_state *state =
2119                 tevent_req_data(req,
2120                 struct smbXcli_req_state);
2121         NTSTATUS status;
2122         size_t body_size;
2123         bool found_status = false;
2124         bool found_size = false;
2125         size_t i;
2126
2127         if (piov != NULL) {
2128                 *piov = NULL;
2129         }
2130
2131         if (tevent_req_is_nterror(req, &status)) {
2132                 for (i=0; i < num_expected; i++) {
2133                         if (NT_STATUS_EQUAL(status, expected[i].status)) {
2134                                 found_status = true;
2135                                 break;
2136                         }
2137                 }
2138
2139                 if (found_status) {
2140                         return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2141                 }
2142
2143                 return status;
2144         }
2145
2146         if (num_expected == 0) {
2147                 found_status = true;
2148                 found_size = true;
2149         }
2150
2151         status = NT_STATUS(IVAL(state->smb2.recv_iov[0].iov_base, SMB2_HDR_STATUS));
2152         body_size = SVAL(state->smb2.recv_iov[1].iov_base, 0);
2153
2154         for (i=0; i < num_expected; i++) {
2155                 if (!NT_STATUS_EQUAL(status, expected[i].status)) {
2156                         continue;
2157                 }
2158
2159                 found_status = true;
2160                 if (expected[i].body_size == 0) {
2161                         found_size = true;
2162                         break;
2163                 }
2164
2165                 if (expected[i].body_size == body_size) {
2166                         found_size = true;
2167                         break;
2168                 }
2169         }
2170
2171         if (!found_status) {
2172                 return status;
2173         }
2174
2175         if (!found_size) {
2176                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2177         }
2178
2179         if (piov != NULL) {
2180                 *piov = talloc_move(mem_ctx, &state->smb2.recv_iov);
2181         }
2182
2183         return status;
2184 }