smbXcli: rework smbXcli_base.c to use smbXcli_conn/smbXcli_req
[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
95 struct smbXcli_req_state {
96         struct tevent_context *ev;
97         struct smbXcli_conn *conn;
98
99         uint8_t length_hdr[4];
100
101         bool one_way;
102
103         uint8_t *inbuf;
104
105         struct {
106                 /* Space for the header including the wct */
107                 uint8_t hdr[HDR_VWV];
108
109                 /*
110                  * For normal requests, smb1cli_req_send chooses a mid.
111                  * SecondaryV trans requests need to use the mid of the primary
112                  * request, so we need a place to store it.
113                  * Assume it is set if != 0.
114                  */
115                 uint16_t mid;
116
117                 uint16_t *vwv;
118                 uint8_t bytecount_buf[2];
119
120 #define MAX_SMB_IOV 5
121                 /* length_hdr, hdr, words, byte_count, buffers */
122                 struct iovec iov[1 + 3 + MAX_SMB_IOV];
123                 int iov_count;
124
125                 uint32_t seqnum;
126                 int chain_num;
127                 int chain_length;
128                 struct tevent_req **chained_requests;
129         } smb1;
130 };
131
132 static int smbXcli_conn_destructor(struct smbXcli_conn *conn)
133 {
134         /*
135          * NT_STATUS_OK, means we do not notify the callers
136          */
137         smbXcli_conn_disconnect(conn, NT_STATUS_OK);
138
139         if (conn->smb1.trans_enc) {
140                 common_free_encryption_state(&conn->smb1.trans_enc);
141         }
142
143         return 0;
144 }
145
146 struct smbXcli_conn *smbXcli_conn_create(TALLOC_CTX *mem_ctx,
147                                          int fd,
148                                          const char *remote_name,
149                                          enum smb_signing_setting signing_state,
150                                          uint32_t smb1_capabilities)
151 {
152         struct smbXcli_conn *conn = NULL;
153         void *ss = NULL;
154         struct sockaddr *sa = NULL;
155         socklen_t sa_length;
156         int ret;
157
158         conn = talloc_zero(mem_ctx, struct smbXcli_conn);
159         if (!conn) {
160                 return NULL;
161         }
162
163         conn->remote_name = talloc_strdup(conn, remote_name);
164         if (conn->remote_name == NULL) {
165                 goto error;
166         }
167
168         conn->fd = fd;
169
170         ss = (void *)&conn->local_ss;
171         sa = (struct sockaddr *)ss;
172         sa_length = sizeof(conn->local_ss);
173         ret = getsockname(fd, sa, &sa_length);
174         if (ret == -1) {
175                 goto error;
176         }
177         ss = (void *)&conn->remote_ss;
178         sa = (struct sockaddr *)ss;
179         sa_length = sizeof(conn->remote_ss);
180         ret = getpeername(fd, sa, &sa_length);
181         if (ret == -1) {
182                 goto error;
183         }
184
185         conn->outgoing = tevent_queue_create(conn, "smbXcli_outgoing");
186         if (conn->outgoing == NULL) {
187                 goto error;
188         }
189         conn->pending = NULL;
190
191         conn->protocol = PROTOCOL_NONE;
192
193         switch (signing_state) {
194         case SMB_SIGNING_OFF:
195                 /* never */
196                 conn->allow_signing = false;
197                 conn->desire_signing = false;
198                 conn->mandatory_signing = false;
199                 break;
200         case SMB_SIGNING_DEFAULT:
201         case SMB_SIGNING_IF_REQUIRED:
202                 /* if the server requires it */
203                 conn->allow_signing = true;
204                 conn->desire_signing = false;
205                 conn->mandatory_signing = false;
206                 break;
207         case SMB_SIGNING_REQUIRED:
208                 /* always */
209                 conn->allow_signing = true;
210                 conn->desire_signing = true;
211                 conn->mandatory_signing = true;
212                 break;
213         }
214
215         conn->smb1.client.capabilities = smb1_capabilities;
216         conn->smb1.client.max_xmit = UINT16_MAX;
217
218         conn->smb1.capabilities = conn->smb1.client.capabilities;
219         conn->smb1.max_xmit = 1024;
220
221         conn->smb1.mid = 1;
222
223         /* initialise signing */
224         conn->smb1.signing = smb_signing_init(conn,
225                                               conn->allow_signing,
226                                               conn->desire_signing,
227                                               conn->mandatory_signing);
228         if (!conn->smb1.signing) {
229                 goto error;
230         }
231
232         talloc_set_destructor(conn, smbXcli_conn_destructor);
233         return conn;
234
235  error:
236         TALLOC_FREE(conn);
237         return NULL;
238 }
239
240 bool smbXcli_conn_is_connected(struct smbXcli_conn *conn)
241 {
242         if (conn == NULL) {
243                 return false;
244         }
245
246         if (conn->fd == -1) {
247                 return false;
248         }
249
250         return true;
251 }
252
253 enum protocol_types smbXcli_conn_protocol(struct smbXcli_conn *conn)
254 {
255         return conn->protocol;
256 }
257
258 bool smbXcli_conn_use_unicode(struct smbXcli_conn *conn)
259 {
260         if (conn->protocol >= PROTOCOL_SMB2_02) {
261                 return true;
262         }
263
264         if (conn->smb1.capabilities & CAP_UNICODE) {
265                 return true;
266         }
267
268         return false;
269 }
270
271 void smbXcli_conn_set_sockopt(struct smbXcli_conn *conn, const char *options)
272 {
273         set_socket_options(conn->fd, options);
274 }
275
276 const struct sockaddr_storage *smbXcli_conn_local_sockaddr(struct smbXcli_conn *conn)
277 {
278         return &conn->local_ss;
279 }
280
281 const struct sockaddr_storage *smbXcli_conn_remote_sockaddr(struct smbXcli_conn *conn)
282 {
283         return &conn->remote_ss;
284 }
285
286 const char *smbXcli_conn_remote_name(struct smbXcli_conn *conn)
287 {
288         return conn->remote_name;
289 }
290
291 bool smb1cli_conn_activate_signing(struct smbXcli_conn *conn,
292                                    const DATA_BLOB user_session_key,
293                                    const DATA_BLOB response)
294 {
295         return smb_signing_activate(conn->smb1.signing,
296                                     user_session_key,
297                                     response);
298 }
299
300 bool smb1cli_conn_check_signing(struct smbXcli_conn *conn,
301                                 const uint8_t *buf, uint32_t seqnum)
302 {
303         return smb_signing_check_pdu(conn->smb1.signing, buf, seqnum);
304 }
305
306 bool smb1cli_conn_signing_is_active(struct smbXcli_conn *conn)
307 {
308         return smb_signing_is_active(conn->smb1.signing);
309 }
310
311 void smb1cli_conn_set_encryption(struct smbXcli_conn *conn,
312                                  struct smb_trans_enc_state *es)
313 {
314         /* Replace the old state, if any. */
315         if (conn->smb1.trans_enc) {
316                 common_free_encryption_state(&conn->smb1.trans_enc);
317         }
318         conn->smb1.trans_enc = es;
319 }
320
321 bool smb1cli_conn_encryption_on(struct smbXcli_conn *conn)
322 {
323         return common_encryption_on(conn->smb1.trans_enc);
324 }
325
326
327 static NTSTATUS smb1cli_pull_raw_error(const uint8_t *buf)
328 {
329         const uint8_t *hdr = buf + NBT_HDR_SIZE;
330         uint32_t flags2 = SVAL(hdr, HDR_FLG2);
331         NTSTATUS status = NT_STATUS(IVAL(hdr, HDR_RCLS));
332
333         if (NT_STATUS_IS_OK(status)) {
334                 return NT_STATUS_OK;
335         }
336
337         if (flags2 & FLAGS2_32_BIT_ERROR_CODES) {
338                 return status;
339         }
340
341         return NT_STATUS_DOS(CVAL(hdr, HDR_RCLS), SVAL(hdr, HDR_ERR));
342 }
343
344 /**
345  * Figure out if there is an andx command behind the current one
346  * @param[in] buf       The smb buffer to look at
347  * @param[in] ofs       The offset to the wct field that is followed by the cmd
348  * @retval Is there a command following?
349  */
350
351 static bool smb1cli_have_andx_command(const uint8_t *buf,
352                                       uint16_t ofs,
353                                       uint8_t cmd)
354 {
355         uint8_t wct;
356         size_t buflen = talloc_get_size(buf);
357
358         if (!smb1cli_is_andx_req(cmd)) {
359                 return false;
360         }
361
362         if ((ofs == buflen-1) || (ofs == buflen)) {
363                 return false;
364         }
365
366         wct = CVAL(buf, ofs);
367         if (wct < 2) {
368                 /*
369                  * Not enough space for the command and a following pointer
370                  */
371                 return false;
372         }
373         return (CVAL(buf, ofs+1) != 0xff);
374 }
375
376 /**
377  * Is the SMB command able to hold an AND_X successor
378  * @param[in] cmd       The SMB command in question
379  * @retval Can we add a chained request after "cmd"?
380  */
381 bool smb1cli_is_andx_req(uint8_t cmd)
382 {
383         switch (cmd) {
384         case SMBtconX:
385         case SMBlockingX:
386         case SMBopenX:
387         case SMBreadX:
388         case SMBwriteX:
389         case SMBsesssetupX:
390         case SMBulogoffX:
391         case SMBntcreateX:
392                 return true;
393                 break;
394         default:
395                 break;
396         }
397
398         return false;
399 }
400
401 static uint16_t smb1cli_alloc_mid(struct smbXcli_conn *conn)
402 {
403         size_t num_pending = talloc_array_length(conn->pending);
404         uint16_t result;
405
406         while (true) {
407                 size_t i;
408
409                 result = conn->smb1.mid++;
410                 if ((result == 0) || (result == 0xffff)) {
411                         continue;
412                 }
413
414                 for (i=0; i<num_pending; i++) {
415                         if (result == smb1cli_req_mid(conn->pending[i])) {
416                                 break;
417                         }
418                 }
419
420                 if (i == num_pending) {
421                         return result;
422                 }
423         }
424 }
425
426 void smbXcli_req_unset_pending(struct tevent_req *req)
427 {
428         struct smbXcli_req_state *state =
429                 tevent_req_data(req,
430                 struct smbXcli_req_state);
431         struct smbXcli_conn *conn = state->conn;
432         size_t num_pending = talloc_array_length(conn->pending);
433         size_t i;
434
435         if (state->smb1.mid != 0) {
436                 /*
437                  * This is a [nt]trans[2] request which waits
438                  * for more than one reply.
439                  */
440                 return;
441         }
442
443         talloc_set_destructor(req, NULL);
444
445         if (num_pending == 1) {
446                 /*
447                  * The pending read_smb tevent_req is a child of
448                  * conn->pending. So if nothing is pending anymore, we need to
449                  * delete the socket read fde.
450                  */
451                 TALLOC_FREE(conn->pending);
452                 conn->read_smb_req = NULL;
453                 return;
454         }
455
456         for (i=0; i<num_pending; i++) {
457                 if (req == conn->pending[i]) {
458                         break;
459                 }
460         }
461         if (i == num_pending) {
462                 /*
463                  * Something's seriously broken. Just returning here is the
464                  * right thing nevertheless, the point of this routine is to
465                  * remove ourselves from conn->pending.
466                  */
467                 return;
468         }
469
470         /*
471          * Remove ourselves from the conn->pending array
472          */
473         for (; i < (num_pending - 1); i++) {
474                 conn->pending[i] = conn->pending[i+1];
475         }
476
477         /*
478          * No NULL check here, we're shrinking by sizeof(void *), and
479          * talloc_realloc just adjusts the size for this.
480          */
481         conn->pending = talloc_realloc(NULL, conn->pending, struct tevent_req *,
482                                        num_pending - 1);
483         return;
484 }
485
486 static int smbXcli_req_destructor(struct tevent_req *req)
487 {
488         struct smbXcli_req_state *state =
489                 tevent_req_data(req,
490                 struct smbXcli_req_state);
491
492         /*
493          * Make sure we really remove it from
494          * the pending array on destruction.
495          */
496         state->smb1.mid = 0;
497         smbXcli_req_unset_pending(req);
498         return 0;
499 }
500
501 static bool smbXcli_conn_receive_next(struct smbXcli_conn *conn);
502
503 bool smbXcli_req_set_pending(struct tevent_req *req)
504 {
505         struct smbXcli_req_state *state =
506                 tevent_req_data(req,
507                 struct smbXcli_req_state);
508         struct smbXcli_conn *conn;
509         struct tevent_req **pending;
510         size_t num_pending;
511
512         conn = state->conn;
513
514         if (!smbXcli_conn_is_connected(conn)) {
515                 return false;
516         }
517
518         num_pending = talloc_array_length(conn->pending);
519
520         pending = talloc_realloc(conn, conn->pending, struct tevent_req *,
521                                  num_pending+1);
522         if (pending == NULL) {
523                 return false;
524         }
525         pending[num_pending] = req;
526         conn->pending = pending;
527         talloc_set_destructor(req, smbXcli_req_destructor);
528
529         if (!smbXcli_conn_receive_next(conn)) {
530                 /*
531                  * the caller should notify the current request
532                  *
533                  * And all other pending requests get notified
534                  * by smbXcli_conn_disconnect().
535                  */
536                 smbXcli_req_unset_pending(req);
537                 smbXcli_conn_disconnect(conn, NT_STATUS_NO_MEMORY);
538                 return false;
539         }
540
541         return true;
542 }
543
544 static void smbXcli_conn_received(struct tevent_req *subreq);
545
546 static bool smbXcli_conn_receive_next(struct smbXcli_conn *conn)
547 {
548         size_t num_pending = talloc_array_length(conn->pending);
549         struct tevent_req *req;
550         struct smbXcli_req_state *state;
551
552         if (conn->read_smb_req != NULL) {
553                 return true;
554         }
555
556         if (num_pending == 0) {
557                 return true;
558         }
559
560         req = conn->pending[0];
561         state = tevent_req_data(req, struct smbXcli_req_state);
562
563         /*
564          * We're the first ones, add the read_smb request that waits for the
565          * answer from the server
566          */
567         conn->read_smb_req = read_smb_send(conn->pending, state->ev, conn->fd);
568         if (conn->read_smb_req == NULL) {
569                 return false;
570         }
571         tevent_req_set_callback(conn->read_smb_req, smbXcli_conn_received, conn);
572         return true;
573 }
574
575 void smbXcli_conn_disconnect(struct smbXcli_conn *conn, NTSTATUS status)
576 {
577         if (conn->fd != -1) {
578                 close(conn->fd);
579         }
580         conn->fd = -1;
581
582         /*
583          * Cancel all pending requests. We do not do a for-loop walking
584          * conn->pending because that array changes in
585          * smbXcli_req_unset_pending.
586          */
587         while (talloc_array_length(conn->pending) > 0) {
588                 struct tevent_req *req;
589                 struct smbXcli_req_state *state;
590
591                 req = conn->pending[0];
592                 state = tevent_req_data(req, struct smbXcli_req_state);
593
594                 /*
595                  * We're dead. No point waiting for trans2
596                  * replies.
597                  */
598                 state->smb1.mid = 0;
599
600                 smbXcli_req_unset_pending(req);
601
602                 if (NT_STATUS_IS_OK(status)) {
603                         /* do not notify the callers */
604                         continue;
605                 }
606
607                 /*
608                  * we need to defer the callback, because we may notify more
609                  * then one caller.
610                  */
611                 tevent_req_defer_callback(req, state->ev);
612                 tevent_req_nterror(req, status);
613         }
614 }
615
616 /*
617  * Fetch a smb request's mid. Only valid after the request has been sent by
618  * smb1cli_req_send().
619  */
620 uint16_t smb1cli_req_mid(struct tevent_req *req)
621 {
622         struct smbXcli_req_state *state =
623                 tevent_req_data(req,
624                 struct smbXcli_req_state);
625
626         if (state->smb1.mid != 0) {
627                 return state->smb1.mid;
628         }
629
630         return SVAL(state->smb1.hdr, HDR_MID);
631 }
632
633 void smb1cli_req_set_mid(struct tevent_req *req, uint16_t mid)
634 {
635         struct smbXcli_req_state *state =
636                 tevent_req_data(req,
637                 struct smbXcli_req_state);
638
639         state->smb1.mid = mid;
640 }
641
642 uint32_t smb1cli_req_seqnum(struct tevent_req *req)
643 {
644         struct smbXcli_req_state *state =
645                 tevent_req_data(req,
646                 struct smbXcli_req_state);
647
648         return state->smb1.seqnum;
649 }
650
651 void smb1cli_req_set_seqnum(struct tevent_req *req, uint32_t seqnum)
652 {
653         struct smbXcli_req_state *state =
654                 tevent_req_data(req,
655                 struct smbXcli_req_state);
656
657         state->smb1.seqnum = seqnum;
658 }
659
660 static size_t smbXcli_iov_len(const struct iovec *iov, int count)
661 {
662         size_t result = 0;
663         int i;
664         for (i=0; i<count; i++) {
665                 result += iov[i].iov_len;
666         }
667         return result;
668 }
669
670 static uint8_t *smbXcli_iov_concat(TALLOC_CTX *mem_ctx,
671                                    const struct iovec *iov,
672                                    int count)
673 {
674         size_t len = smbXcli_iov_len(iov, count);
675         size_t copied;
676         uint8_t *buf;
677         int i;
678
679         buf = talloc_array(mem_ctx, uint8_t, len);
680         if (buf == NULL) {
681                 return NULL;
682         }
683         copied = 0;
684         for (i=0; i<count; i++) {
685                 memcpy(buf+copied, iov[i].iov_base, iov[i].iov_len);
686                 copied += iov[i].iov_len;
687         }
688         return buf;
689 }
690
691 struct tevent_req *smb1cli_req_create(TALLOC_CTX *mem_ctx,
692                                       struct tevent_context *ev,
693                                       struct smbXcli_conn *conn,
694                                       uint8_t smb_command,
695                                       uint8_t additional_flags,
696                                       uint8_t clear_flags,
697                                       uint16_t additional_flags2,
698                                       uint16_t clear_flags2,
699                                       uint32_t timeout_msec,
700                                       uint32_t pid,
701                                       uint16_t tid,
702                                       uint16_t uid,
703                                       uint8_t wct, uint16_t *vwv,
704                                       int iov_count,
705                                       struct iovec *bytes_iov)
706 {
707         struct tevent_req *req;
708         struct smbXcli_req_state *state;
709         uint8_t flags = 0;
710         uint16_t flags2 = 0;
711
712         if (iov_count > MAX_SMB_IOV) {
713                 /*
714                  * Should not happen :-)
715                  */
716                 return NULL;
717         }
718
719         req = tevent_req_create(mem_ctx, &state,
720                                 struct smbXcli_req_state);
721         if (req == NULL) {
722                 return NULL;
723         }
724         state->ev = ev;
725         state->conn = conn;
726
727         if (conn->protocol >= PROTOCOL_LANMAN1) {
728                 flags |= FLAG_CASELESS_PATHNAMES;
729                 flags |= FLAG_CANONICAL_PATHNAMES;
730         }
731
732         if (conn->protocol >= PROTOCOL_LANMAN2) {
733                 flags2 |= FLAGS2_LONG_PATH_COMPONENTS;
734                 flags2 |= FLAGS2_EXTENDED_ATTRIBUTES;
735         }
736
737         if (conn->protocol >= PROTOCOL_NT1) {
738                 if (conn->smb1.capabilities & CAP_UNICODE) {
739                         flags2 |= FLAGS2_UNICODE_STRINGS;
740                 }
741                 if (conn->smb1.capabilities & CAP_STATUS32) {
742                         flags2 |= FLAGS2_32_BIT_ERROR_CODES;
743                 }
744                 if (conn->smb1.capabilities & CAP_EXTENDED_SECURITY) {
745                         flags2 |= FLAGS2_EXTENDED_SECURITY;
746                 }
747         }
748
749         flags |= additional_flags;
750         flags &= ~clear_flags;
751         flags2 |= additional_flags2;
752         flags2 &= ~clear_flags2;
753
754         SIVAL(state->smb1.hdr, 0,           SMB_MAGIC);
755         SCVAL(state->smb1.hdr, HDR_COM,     smb_command);
756         SIVAL(state->smb1.hdr, HDR_RCLS,    NT_STATUS_V(NT_STATUS_OK));
757         SCVAL(state->smb1.hdr, HDR_FLG,     flags);
758         SSVAL(state->smb1.hdr, HDR_FLG2,    flags2);
759         SSVAL(state->smb1.hdr, HDR_PIDHIGH, pid >> 16);
760         SSVAL(state->smb1.hdr, HDR_TID,     tid);
761         SSVAL(state->smb1.hdr, HDR_PID,     pid);
762         SSVAL(state->smb1.hdr, HDR_UID,     uid);
763         SSVAL(state->smb1.hdr, HDR_MID,     0); /* this comes later */
764         SSVAL(state->smb1.hdr, HDR_WCT,     wct);
765
766         state->smb1.vwv = vwv;
767
768         SSVAL(state->smb1.bytecount_buf, 0, smbXcli_iov_len(bytes_iov, iov_count));
769
770         state->smb1.iov[0].iov_base = (void *)state->length_hdr;
771         state->smb1.iov[0].iov_len  = sizeof(state->length_hdr);
772         state->smb1.iov[1].iov_base = (void *)state->smb1.hdr;
773         state->smb1.iov[1].iov_len  = sizeof(state->smb1.hdr);
774         state->smb1.iov[2].iov_base = (void *)state->smb1.vwv;
775         state->smb1.iov[2].iov_len  = wct * sizeof(uint16_t);
776         state->smb1.iov[3].iov_base = (void *)state->smb1.bytecount_buf;
777         state->smb1.iov[3].iov_len  = sizeof(uint16_t);
778
779         if (iov_count != 0) {
780                 memcpy(&state->smb1.iov[4], bytes_iov,
781                        iov_count * sizeof(*bytes_iov));
782         }
783         state->smb1.iov_count = iov_count + 4;
784
785         if (timeout_msec > 0) {
786                 struct timeval endtime;
787
788                 endtime = timeval_current_ofs_msec(timeout_msec);
789                 if (!tevent_req_set_endtime(req, ev, endtime)) {
790                         return req;
791                 }
792         }
793
794         switch (smb_command) {
795         case SMBtranss:
796         case SMBtranss2:
797         case SMBnttranss:
798         case SMBntcancel:
799                 state->one_way = true;
800                 break;
801         case SMBlockingX:
802                 if ((wct == 8) &&
803                     (CVAL(vwv+3, 0) == LOCKING_ANDX_OPLOCK_RELEASE)) {
804                         state->one_way = true;
805                 }
806                 break;
807         }
808
809         return req;
810 }
811
812 static NTSTATUS smb1cli_conn_signv(struct smbXcli_conn *conn,
813                                    struct iovec *iov, int iov_count,
814                                    uint32_t *seqnum)
815 {
816         uint8_t *buf;
817
818         /*
819          * Obvious optimization: Make cli_calculate_sign_mac work with struct
820          * iovec directly. MD5Update would do that just fine.
821          */
822
823         if (iov_count < 4) {
824                 return NT_STATUS_INVALID_PARAMETER_MIX;
825         }
826         if (iov[0].iov_len != NBT_HDR_SIZE) {
827                 return NT_STATUS_INVALID_PARAMETER_MIX;
828         }
829         if (iov[1].iov_len != (MIN_SMB_SIZE-sizeof(uint16_t))) {
830                 return NT_STATUS_INVALID_PARAMETER_MIX;
831         }
832         if (iov[2].iov_len > (0xFF * sizeof(uint16_t))) {
833                 return NT_STATUS_INVALID_PARAMETER_MIX;
834         }
835         if (iov[3].iov_len != sizeof(uint16_t)) {
836                 return NT_STATUS_INVALID_PARAMETER_MIX;
837         }
838
839         buf = smbXcli_iov_concat(talloc_tos(), iov, iov_count);
840         if (buf == NULL) {
841                 return NT_STATUS_NO_MEMORY;
842         }
843
844         *seqnum = smb_signing_next_seqnum(conn->smb1.signing, false);
845         smb_signing_sign_pdu(conn->smb1.signing, buf, *seqnum);
846         memcpy(iov[1].iov_base, buf+4, iov[1].iov_len);
847
848         TALLOC_FREE(buf);
849         return NT_STATUS_OK;
850 }
851
852 static void smb1cli_req_writev_done(struct tevent_req *subreq);
853 static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
854                                                TALLOC_CTX *tmp_mem,
855                                                uint8_t *inbuf);
856
857 static NTSTATUS smb1cli_req_writev_submit(struct tevent_req *req,
858                                           struct smbXcli_req_state *state,
859                                           struct iovec *iov, int iov_count)
860 {
861         struct tevent_req *subreq;
862         NTSTATUS status;
863         uint16_t mid;
864
865         if (!smbXcli_conn_is_connected(state->conn)) {
866                 return NT_STATUS_CONNECTION_DISCONNECTED;
867         }
868
869         if (state->conn->protocol > PROTOCOL_NT1) {
870                 return NT_STATUS_REVISION_MISMATCH;
871         }
872
873         if (iov_count < 4) {
874                 return NT_STATUS_INVALID_PARAMETER_MIX;
875         }
876         if (iov[0].iov_len != NBT_HDR_SIZE) {
877                 return NT_STATUS_INVALID_PARAMETER_MIX;
878         }
879         if (iov[1].iov_len != (MIN_SMB_SIZE-sizeof(uint16_t))) {
880                 return NT_STATUS_INVALID_PARAMETER_MIX;
881         }
882         if (iov[2].iov_len > (0xFF * sizeof(uint16_t))) {
883                 return NT_STATUS_INVALID_PARAMETER_MIX;
884         }
885         if (iov[3].iov_len != sizeof(uint16_t)) {
886                 return NT_STATUS_INVALID_PARAMETER_MIX;
887         }
888
889         if (state->smb1.mid != 0) {
890                 mid = state->smb1.mid;
891         } else {
892                 mid = smb1cli_alloc_mid(state->conn);
893         }
894         SSVAL(iov[1].iov_base, HDR_MID, mid);
895
896         _smb_setlen_nbt(iov[0].iov_base, smbXcli_iov_len(&iov[1], iov_count-1));
897
898         status = smb1cli_conn_signv(state->conn, iov, iov_count,
899                                     &state->smb1.seqnum);
900
901         if (!NT_STATUS_IS_OK(status)) {
902                 return status;
903         }
904
905         /*
906          * If we supported multiple encrytion contexts
907          * here we'd look up based on tid.
908          */
909         if (common_encryption_on(state->conn->smb1.trans_enc)) {
910                 char *buf, *enc_buf;
911
912                 buf = (char *)smbXcli_iov_concat(talloc_tos(), iov, iov_count);
913                 if (buf == NULL) {
914                         return NT_STATUS_NO_MEMORY;
915                 }
916                 status = common_encrypt_buffer(state->conn->smb1.trans_enc,
917                                                (char *)buf, &enc_buf);
918                 TALLOC_FREE(buf);
919                 if (!NT_STATUS_IS_OK(status)) {
920                         DEBUG(0, ("Error in encrypting client message: %s\n",
921                                   nt_errstr(status)));
922                         return status;
923                 }
924                 buf = (char *)talloc_memdup(state, enc_buf,
925                                             smb_len_nbt(enc_buf)+4);
926                 SAFE_FREE(enc_buf);
927                 if (buf == NULL) {
928                         return NT_STATUS_NO_MEMORY;
929                 }
930                 iov[0].iov_base = (void *)buf;
931                 iov[0].iov_len = talloc_get_size(buf);
932                 iov_count = 1;
933         }
934
935         if (state->conn->dispatch_incoming == NULL) {
936                 state->conn->dispatch_incoming = smb1cli_conn_dispatch_incoming;
937         }
938
939         subreq = writev_send(state, state->ev, state->conn->outgoing,
940                              state->conn->fd, false, iov, iov_count);
941         if (subreq == NULL) {
942                 return NT_STATUS_NO_MEMORY;
943         }
944         tevent_req_set_callback(subreq, smb1cli_req_writev_done, req);
945         return NT_STATUS_OK;
946 }
947
948 struct tevent_req *smb1cli_req_send(TALLOC_CTX *mem_ctx,
949                                     struct tevent_context *ev,
950                                     struct smbXcli_conn *conn,
951                                     uint8_t smb_command,
952                                     uint8_t additional_flags,
953                                     uint8_t clear_flags,
954                                     uint16_t additional_flags2,
955                                     uint16_t clear_flags2,
956                                     uint32_t timeout_msec,
957                                     uint32_t pid,
958                                     uint16_t tid,
959                                     uint16_t uid,
960                                     uint8_t wct, uint16_t *vwv,
961                                     uint32_t num_bytes,
962                                     const uint8_t *bytes)
963 {
964         struct tevent_req *req;
965         struct iovec iov;
966         NTSTATUS status;
967
968         iov.iov_base = discard_const_p(void, bytes);
969         iov.iov_len = num_bytes;
970
971         req = smb1cli_req_create(mem_ctx, ev, conn, smb_command,
972                                  additional_flags, clear_flags,
973                                  additional_flags2, clear_flags2,
974                                  timeout_msec,
975                                  pid, tid, uid,
976                                  wct, vwv, 1, &iov);
977         if (req == NULL) {
978                 return NULL;
979         }
980         if (!tevent_req_is_in_progress(req)) {
981                 return tevent_req_post(req, ev);
982         }
983         status = smb1cli_req_chain_submit(&req, 1);
984         if (tevent_req_nterror(req, status)) {
985                 return tevent_req_post(req, ev);
986         }
987         return req;
988 }
989
990 static void smb1cli_req_writev_done(struct tevent_req *subreq)
991 {
992         struct tevent_req *req =
993                 tevent_req_callback_data(subreq,
994                 struct tevent_req);
995         struct smbXcli_req_state *state =
996                 tevent_req_data(req,
997                 struct smbXcli_req_state);
998         ssize_t nwritten;
999         int err;
1000
1001         nwritten = writev_recv(subreq, &err);
1002         TALLOC_FREE(subreq);
1003         if (nwritten == -1) {
1004                 NTSTATUS status = map_nt_error_from_unix_common(err);
1005                 smbXcli_conn_disconnect(state->conn, status);
1006                 return;
1007         }
1008
1009         if (state->one_way) {
1010                 state->inbuf = NULL;
1011                 tevent_req_done(req);
1012                 return;
1013         }
1014
1015         if (!smbXcli_req_set_pending(req)) {
1016                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1017                 return;
1018         }
1019 }
1020
1021 static void smbXcli_conn_received(struct tevent_req *subreq)
1022 {
1023         struct smbXcli_conn *conn =
1024                 tevent_req_callback_data(subreq,
1025                 struct smbXcli_conn);
1026         TALLOC_CTX *frame = talloc_stackframe();
1027         NTSTATUS status;
1028         uint8_t *inbuf;
1029         ssize_t received;
1030         int err;
1031
1032         if (subreq != conn->read_smb_req) {
1033                 DEBUG(1, ("Internal error: cli_smb_received called with "
1034                           "unexpected subreq\n"));
1035                 status = NT_STATUS_INTERNAL_ERROR;
1036                 smbXcli_conn_disconnect(conn, status);
1037                 TALLOC_FREE(frame);
1038                 return;
1039         }
1040         conn->read_smb_req = NULL;
1041
1042         received = read_smb_recv(subreq, frame, &inbuf, &err);
1043         TALLOC_FREE(subreq);
1044         if (received == -1) {
1045                 status = map_nt_error_from_unix_common(err);
1046                 smbXcli_conn_disconnect(conn, status);
1047                 TALLOC_FREE(frame);
1048                 return;
1049         }
1050
1051         status = conn->dispatch_incoming(conn, frame, inbuf);
1052         TALLOC_FREE(frame);
1053         if (NT_STATUS_IS_OK(status)) {
1054                 /*
1055                  * We should not do any more processing
1056                  * as the dispatch function called
1057                  * tevent_req_done().
1058                  */
1059                 return;
1060         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1061                 /*
1062                  * We got an error, so notify all pending requests
1063                  */
1064                 smbXcli_conn_disconnect(conn, status);
1065                 return;
1066         }
1067
1068         /*
1069          * We got NT_STATUS_RETRY, so we may ask for a
1070          * next incoming pdu.
1071          */
1072         if (!smbXcli_conn_receive_next(conn)) {
1073                 smbXcli_conn_disconnect(conn, NT_STATUS_NO_MEMORY);
1074         }
1075 }
1076
1077 static NTSTATUS smb1cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
1078                                                TALLOC_CTX *tmp_mem,
1079                                                uint8_t *inbuf)
1080 {
1081         struct tevent_req *req;
1082         struct smbXcli_req_state *state;
1083         NTSTATUS status;
1084         size_t num_pending;
1085         size_t i;
1086         uint16_t mid;
1087         bool oplock_break;
1088         const uint8_t *inhdr = inbuf + NBT_HDR_SIZE;
1089
1090         if ((IVAL(inhdr, 0) != SMB_MAGIC) /* 0xFF"SMB" */
1091             && (SVAL(inhdr, 0) != 0x45ff)) /* 0xFF"E" */ {
1092                 DEBUG(10, ("Got non-SMB PDU\n"));
1093                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1094         }
1095
1096         /*
1097          * If we supported multiple encrytion contexts
1098          * here we'd look up based on tid.
1099          */
1100         if (common_encryption_on(conn->smb1.trans_enc)
1101             && (CVAL(inbuf, 0) == 0)) {
1102                 uint16_t enc_ctx_num;
1103
1104                 status = get_enc_ctx_num(inbuf, &enc_ctx_num);
1105                 if (!NT_STATUS_IS_OK(status)) {
1106                         DEBUG(10, ("get_enc_ctx_num returned %s\n",
1107                                    nt_errstr(status)));
1108                         return status;
1109                 }
1110
1111                 if (enc_ctx_num != conn->smb1.trans_enc->enc_ctx_num) {
1112                         DEBUG(10, ("wrong enc_ctx %d, expected %d\n",
1113                                    enc_ctx_num,
1114                                    conn->smb1.trans_enc->enc_ctx_num));
1115                         return NT_STATUS_INVALID_HANDLE;
1116                 }
1117
1118                 status = common_decrypt_buffer(conn->smb1.trans_enc,
1119                                                (char *)inbuf);
1120                 if (!NT_STATUS_IS_OK(status)) {
1121                         DEBUG(10, ("common_decrypt_buffer returned %s\n",
1122                                    nt_errstr(status)));
1123                         return status;
1124                 }
1125         }
1126
1127         mid = SVAL(inhdr, HDR_MID);
1128         num_pending = talloc_array_length(conn->pending);
1129
1130         for (i=0; i<num_pending; i++) {
1131                 if (mid == smb1cli_req_mid(conn->pending[i])) {
1132                         break;
1133                 }
1134         }
1135         if (i == num_pending) {
1136                 /* Dump unexpected reply */
1137                 return NT_STATUS_RETRY;
1138         }
1139
1140         oplock_break = false;
1141
1142         if (mid == 0xffff) {
1143                 /*
1144                  * Paranoia checks that this is really an oplock break request.
1145                  */
1146                 oplock_break = (smb_len_nbt(inbuf) == 51); /* hdr + 8 words */
1147                 oplock_break &= ((CVAL(inhdr, HDR_FLG) & FLAG_REPLY) == 0);
1148                 oplock_break &= (CVAL(inhdr, HDR_COM) == SMBlockingX);
1149                 oplock_break &= (SVAL(inhdr, HDR_VWV+VWV(6)) == 0);
1150                 oplock_break &= (SVAL(inhdr, HDR_VWV+VWV(7)) == 0);
1151
1152                 if (!oplock_break) {
1153                         /* Dump unexpected reply */
1154                         return NT_STATUS_RETRY;
1155                 }
1156         }
1157
1158         req = conn->pending[i];
1159         state = tevent_req_data(req, struct smbXcli_req_state);
1160
1161         if (!oplock_break /* oplock breaks are not signed */
1162             && !smb_signing_check_pdu(conn->smb1.signing,
1163                                       inbuf, state->smb1.seqnum+1)) {
1164                 DEBUG(10, ("cli_check_sign_mac failed\n"));
1165                 return NT_STATUS_ACCESS_DENIED;
1166         }
1167
1168         if (state->smb1.chained_requests != NULL) {
1169                 struct tevent_req **chain = talloc_move(tmp_mem,
1170                                             &state->smb1.chained_requests);
1171                 size_t num_chained = talloc_array_length(chain);
1172
1173                 /*
1174                  * We steal the inbuf to the chain,
1175                  * so that it will stay until all
1176                  * requests of the chain are finished.
1177                  *
1178                  * Each requests in the chain will
1179                  * hold a talloc reference to the chain.
1180                  * This way we do not expose the talloc_reference()
1181                  * behavior to the callers.
1182                  */
1183                 talloc_steal(chain, inbuf);
1184
1185                 for (i=0; i<num_chained; i++) {
1186                         struct tevent_req **ref;
1187
1188                         req = chain[i];
1189                         state = tevent_req_data(req, struct smbXcli_req_state);
1190
1191                         smbXcli_req_unset_pending(req);
1192
1193                         /*
1194                          * as we finish multiple requests here
1195                          * we need to defer the callbacks as
1196                          * they could destroy our current stack state.
1197                          */
1198                         tevent_req_defer_callback(req, state->ev);
1199
1200                         ref = talloc_reference(state, chain);
1201                         if (tevent_req_nomem(ref, req)) {
1202                                 continue;
1203                         }
1204
1205                         state->inbuf = inbuf;
1206                         state->smb1.chain_num = i;
1207                         state->smb1.chain_length = num_chained;
1208
1209                         tevent_req_done(req);
1210                 }
1211                 return NT_STATUS_RETRY;
1212         }
1213
1214         smbXcli_req_unset_pending(req);
1215
1216         state->inbuf = talloc_move(state, &inbuf);
1217         state->smb1.chain_num = 0;
1218         state->smb1.chain_length = 1;
1219
1220         if (talloc_array_length(conn->pending) == 0) {
1221                 tevent_req_done(req);
1222                 return NT_STATUS_OK;
1223         }
1224
1225         tevent_req_defer_callback(req, state->ev);
1226         tevent_req_done(req);
1227         return NT_STATUS_RETRY;
1228 }
1229
1230 NTSTATUS smb1cli_req_recv(struct tevent_req *req,
1231                           TALLOC_CTX *mem_ctx, uint8_t **pinbuf,
1232                           uint8_t min_wct, uint8_t *pwct, uint16_t **pvwv,
1233                           uint32_t *pnum_bytes, uint8_t **pbytes)
1234 {
1235         struct smbXcli_req_state *state =
1236                 tevent_req_data(req,
1237                 struct smbXcli_req_state);
1238         NTSTATUS status = NT_STATUS_OK;
1239         uint8_t cmd, wct;
1240         uint16_t num_bytes;
1241         size_t wct_ofs, bytes_offset;
1242         int i;
1243
1244         if (tevent_req_is_nterror(req, &status)) {
1245                 return status;
1246         }
1247
1248         if (state->inbuf == NULL) {
1249                 if (min_wct != 0) {
1250                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
1251                 }
1252                 if (pinbuf) {
1253                         *pinbuf = NULL;
1254                 }
1255                 if (pwct) {
1256                         *pwct = 0;
1257                 }
1258                 if (pvwv) {
1259                         *pvwv = NULL;
1260                 }
1261                 if (pnum_bytes) {
1262                         *pnum_bytes = 0;
1263                 }
1264                 if (pbytes) {
1265                         *pbytes = NULL;
1266                 }
1267                 /* This was a request without a reply */
1268                 return NT_STATUS_OK;
1269         }
1270
1271         wct_ofs = NBT_HDR_SIZE + HDR_WCT;
1272         cmd = CVAL(state->inbuf, NBT_HDR_SIZE + HDR_COM);
1273
1274         for (i=0; i<state->smb1.chain_num; i++) {
1275                 if (i < state->smb1.chain_num-1) {
1276                         if (cmd == 0xff) {
1277                                 return NT_STATUS_REQUEST_ABORTED;
1278                         }
1279                         if (!smb1cli_is_andx_req(cmd)) {
1280                                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1281                         }
1282                 }
1283
1284                 if (!smb1cli_have_andx_command(state->inbuf, wct_ofs, cmd)) {
1285                         /*
1286                          * This request was not completed because a previous
1287                          * request in the chain had received an error.
1288                          */
1289                         return NT_STATUS_REQUEST_ABORTED;
1290                 }
1291
1292                 cmd = CVAL(state->inbuf, wct_ofs + 1);
1293                 wct_ofs = SVAL(state->inbuf, wct_ofs + 3);
1294
1295                 /*
1296                  * Skip the all-present length field. No overflow, we've just
1297                  * put a 16-bit value into a size_t.
1298                  */
1299                 wct_ofs += 4;
1300
1301                 if (wct_ofs+2 > talloc_get_size(state->inbuf)) {
1302                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
1303                 }
1304         }
1305
1306         status = smb1cli_pull_raw_error(state->inbuf);
1307
1308         if (!smb1cli_have_andx_command(state->inbuf, wct_ofs, cmd)) {
1309
1310                 if ((cmd == SMBsesssetupX)
1311                     && NT_STATUS_EQUAL(
1312                             status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1313                         /*
1314                          * NT_STATUS_MORE_PROCESSING_REQUIRED is a
1315                          * valid return code for session setup
1316                          */
1317                         goto no_err;
1318                 }
1319
1320                 if (NT_STATUS_IS_ERR(status)) {
1321                         /*
1322                          * The last command takes the error code. All
1323                          * further commands down the requested chain
1324                          * will get a NT_STATUS_REQUEST_ABORTED.
1325                          */
1326                         return status;
1327                 }
1328         } else {
1329                 /*
1330                  * Only the last request in the chain get the returned
1331                  * status.
1332                  */
1333                 status = NT_STATUS_OK;
1334         }
1335
1336 no_err:
1337
1338         wct = CVAL(state->inbuf, wct_ofs);
1339         bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t);
1340         num_bytes = SVAL(state->inbuf, bytes_offset);
1341
1342         if (wct < min_wct) {
1343                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1344         }
1345
1346         /*
1347          * wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes
1348          * is a 16-bit value. So bytes_offset being size_t should be far from
1349          * wrapping.
1350          */
1351         if ((bytes_offset + 2 > talloc_get_size(state->inbuf))
1352             || (bytes_offset > 0xffff)) {
1353                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1354         }
1355
1356         if (pwct != NULL) {
1357                 *pwct = wct;
1358         }
1359         if (pvwv != NULL) {
1360                 *pvwv = (uint16_t *)(state->inbuf + wct_ofs + 1);
1361         }
1362         if (pnum_bytes != NULL) {
1363                 *pnum_bytes = num_bytes;
1364         }
1365         if (pbytes != NULL) {
1366                 *pbytes = (uint8_t *)state->inbuf + bytes_offset + 2;
1367         }
1368         if ((mem_ctx != NULL) && (pinbuf != NULL)) {
1369                 if (state->smb1.chain_num == state->smb1.chain_length-1) {
1370                         *pinbuf = talloc_move(mem_ctx, &state->inbuf);
1371                 } else {
1372                         *pinbuf = state->inbuf;
1373                 }
1374         }
1375
1376         return status;
1377 }
1378
1379 size_t smb1cli_req_wct_ofs(struct tevent_req **reqs, int num_reqs)
1380 {
1381         size_t wct_ofs;
1382         int i;
1383
1384         wct_ofs = HDR_WCT;
1385
1386         for (i=0; i<num_reqs; i++) {
1387                 struct smbXcli_req_state *state;
1388                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1389                 wct_ofs += smbXcli_iov_len(state->smb1.iov+2,
1390                                            state->smb1.iov_count-2);
1391                 wct_ofs = (wct_ofs + 3) & ~3;
1392         }
1393         return wct_ofs;
1394 }
1395
1396 NTSTATUS smb1cli_req_chain_submit(struct tevent_req **reqs, int num_reqs)
1397 {
1398         struct smbXcli_req_state *first_state =
1399                 tevent_req_data(reqs[0],
1400                 struct smbXcli_req_state);
1401         struct smbXcli_req_state *last_state =
1402                 tevent_req_data(reqs[num_reqs-1],
1403                 struct smbXcli_req_state);
1404         struct smbXcli_req_state *state;
1405         size_t wct_offset;
1406         size_t chain_padding = 0;
1407         int i, iovlen;
1408         struct iovec *iov = NULL;
1409         struct iovec *this_iov;
1410         NTSTATUS status;
1411         size_t nbt_len;
1412
1413         if (num_reqs == 1) {
1414                 return smb1cli_req_writev_submit(reqs[0], first_state,
1415                                                  first_state->smb1.iov,
1416                                                  first_state->smb1.iov_count);
1417         }
1418
1419         iovlen = 0;
1420         for (i=0; i<num_reqs; i++) {
1421                 if (!tevent_req_is_in_progress(reqs[i])) {
1422                         return NT_STATUS_INTERNAL_ERROR;
1423                 }
1424
1425                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1426
1427                 if (state->smb1.iov_count < 4) {
1428                         return NT_STATUS_INVALID_PARAMETER_MIX;
1429                 }
1430
1431                 if (i == 0) {
1432                         /*
1433                          * The NBT and SMB header
1434                          */
1435                         iovlen += 2;
1436                 } else {
1437                         /*
1438                          * Chain padding
1439                          */
1440                         iovlen += 1;
1441                 }
1442
1443                 /*
1444                  * words and bytes
1445                  */
1446                 iovlen += state->smb1.iov_count - 2;
1447         }
1448
1449         iov = talloc_zero_array(last_state, struct iovec, iovlen);
1450         if (iov == NULL) {
1451                 return NT_STATUS_NO_MEMORY;
1452         }
1453
1454         first_state->smb1.chained_requests = (struct tevent_req **)talloc_memdup(
1455                 last_state, reqs, sizeof(*reqs) * num_reqs);
1456         if (first_state->smb1.chained_requests == NULL) {
1457                 TALLOC_FREE(iov);
1458                 return NT_STATUS_NO_MEMORY;
1459         }
1460
1461         wct_offset = HDR_WCT;
1462         this_iov = iov;
1463
1464         for (i=0; i<num_reqs; i++) {
1465                 size_t next_padding = 0;
1466                 uint16_t *vwv;
1467
1468                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1469
1470                 if (i < num_reqs-1) {
1471                         if (!smb1cli_is_andx_req(CVAL(state->smb1.hdr, HDR_COM))
1472                             || CVAL(state->smb1.hdr, HDR_WCT) < 2) {
1473                                 TALLOC_FREE(iov);
1474                                 TALLOC_FREE(first_state->smb1.chained_requests);
1475                                 return NT_STATUS_INVALID_PARAMETER_MIX;
1476                         }
1477                 }
1478
1479                 wct_offset += smbXcli_iov_len(state->smb1.iov+2,
1480                                               state->smb1.iov_count-2) + 1;
1481                 if ((wct_offset % 4) != 0) {
1482                         next_padding = 4 - (wct_offset % 4);
1483                 }
1484                 wct_offset += next_padding;
1485                 vwv = state->smb1.vwv;
1486
1487                 if (i < num_reqs-1) {
1488                         struct smbXcli_req_state *next_state =
1489                                 tevent_req_data(reqs[i+1],
1490                                 struct smbXcli_req_state);
1491                         SCVAL(vwv+0, 0, CVAL(next_state->smb1.hdr, HDR_COM));
1492                         SCVAL(vwv+0, 1, 0);
1493                         SSVAL(vwv+1, 0, wct_offset);
1494                 } else if (smb1cli_is_andx_req(CVAL(state->smb1.hdr, HDR_COM))) {
1495                         /* properly end the chain */
1496                         SCVAL(vwv+0, 0, 0xff);
1497                         SCVAL(vwv+0, 1, 0xff);
1498                         SSVAL(vwv+1, 0, 0);
1499                 }
1500
1501                 if (i == 0) {
1502                         /*
1503                          * The NBT and SMB header
1504                          */
1505                         this_iov[0] = state->smb1.iov[0];
1506                         this_iov[1] = state->smb1.iov[1];
1507                         this_iov += 2;
1508                 } else {
1509                         /*
1510                          * This one is a bit subtle. We have to add
1511                          * chain_padding bytes between the requests, and we
1512                          * have to also include the wct field of the
1513                          * subsequent requests. We use the subsequent header
1514                          * for the padding, it contains the wct field in its
1515                          * last byte.
1516                          */
1517                         this_iov[0].iov_len = chain_padding+1;
1518                         this_iov[0].iov_base = (void *)&state->smb1.hdr[
1519                                 sizeof(state->smb1.hdr) - this_iov[0].iov_len];
1520                         memset(this_iov[0].iov_base, 0, this_iov[0].iov_len-1);
1521                         this_iov += 1;
1522                 }
1523
1524                 /*
1525                  * copy the words and bytes
1526                  */
1527                 memcpy(this_iov, state->smb1.iov+2,
1528                        sizeof(struct iovec) * (state->smb1.iov_count-2));
1529                 this_iov += state->smb1.iov_count - 2;
1530                 chain_padding = next_padding;
1531         }
1532
1533         nbt_len = smbXcli_iov_len(&iov[1], iovlen-1);
1534         if (nbt_len > first_state->conn->smb1.max_xmit) {
1535                 TALLOC_FREE(iov);
1536                 TALLOC_FREE(first_state->smb1.chained_requests);
1537                 return NT_STATUS_INVALID_PARAMETER_MIX;
1538         }
1539
1540         status = smb1cli_req_writev_submit(reqs[0], last_state, iov, iovlen);
1541         if (!NT_STATUS_IS_OK(status)) {
1542                 TALLOC_FREE(iov);
1543                 TALLOC_FREE(first_state->smb1.chained_requests);
1544                 return status;
1545         }
1546
1547         for (i=0; i < (num_reqs - 1); i++) {
1548                 state = tevent_req_data(reqs[i], struct smbXcli_req_state);
1549
1550                 state->smb1.seqnum = last_state->smb1.seqnum;
1551         }
1552
1553         return NT_STATUS_OK;
1554 }
1555
1556 bool smbXcli_conn_has_async_calls(struct smbXcli_conn *conn)
1557 {
1558         return ((tevent_queue_length(conn->outgoing) != 0)
1559                 || (talloc_array_length(conn->pending) != 0));
1560 }