More simple const fixes.
[samba.git] / source3 / smbd / smb2_server.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29
30 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
31
32 static const char *smb2_names[] = {
33         "SMB2_NEGPROT",
34         "SMB2_SESSSETUP",
35         "SMB2_LOGOFF",
36         "SMB2_TCON",
37         "SMB2_TDIS",
38         "SMB2_CREATE",
39         "SMB2_CLOSE",
40         "SMB2_FLUSH",
41         "SMB2_READ",
42         "SMB2_WRITE",
43         "SMB2_LOCK",
44         "SMB2_IOCTL",
45         "SMB2_CANCEL",
46         "SMB2_KEEPALIVE",
47         "SMB2_FIND",
48         "SMB2_NOTIFY",
49         "SMB2_GETINFO",
50         "SMB2_SETINFO",
51         "SMB2_BREAK"
52 };
53
54 const char *smb2_opcode_name(uint16_t opcode)
55 {
56         if (opcode > 0x12) {
57                 return "Bad SMB2 opcode";
58         }
59         return smb2_names[opcode];
60 }
61
62 static void print_req_vectors(struct smbd_smb2_request *req)
63 {
64         int i;
65
66         for (i = 0; i < req->in.vector_count; i++) {
67                 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
68                         (unsigned int)i,
69                         (unsigned int)req->in.vector[i].iov_len);
70         }
71         for (i = 0; i < req->out.vector_count; i++) {
72                 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
73                         (unsigned int)i,
74                         (unsigned int)req->out.vector[i].iov_len);
75         }
76 }
77
78 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
79 {
80         if (size < (4 + SMB2_HDR_BODY)) {
81                 return false;
82         }
83
84         if (IVAL(inbuf, 4) != SMB2_MAGIC) {
85                 return false;
86         }
87
88         return true;
89 }
90
91 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
92 {
93         NTSTATUS status;
94         int ret;
95
96         TALLOC_FREE(sconn->smb1.fde);
97
98         sconn->smb2.event_ctx = smbd_event_context();
99
100         sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
101         if (sconn->smb2.recv_queue == NULL) {
102                 return NT_STATUS_NO_MEMORY;
103         }
104
105         sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
106         if (sconn->smb2.send_queue == NULL) {
107                 return NT_STATUS_NO_MEMORY;
108         }
109
110         sconn->smb2.sessions.idtree = idr_init(sconn);
111         if (sconn->smb2.sessions.idtree == NULL) {
112                 return NT_STATUS_NO_MEMORY;
113         }
114         sconn->smb2.sessions.limit = 0x0000FFFE;
115         sconn->smb2.sessions.list = NULL;
116         sconn->smb2.seqnum_low = 0;
117         sconn->smb2.credits_granted = 0;
118         sconn->smb2.max_credits = lp_smb2_max_credits();
119         sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
120                         DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR*sconn->smb2.max_credits);
121         if (sconn->smb2.credits_bitmap == NULL) {
122                 return NT_STATUS_NO_MEMORY;
123         }
124
125         ret = tstream_bsd_existing_socket(sconn, sconn->sock,
126                                           &sconn->smb2.stream);
127         if (ret == -1) {
128                 status = map_nt_error_from_unix(errno);
129                 return status;
130         }
131
132         /* Ensure child is set to non-blocking mode */
133         set_blocking(sconn->sock, false);
134         return NT_STATUS_OK;
135 }
136
137 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
138 #define _smb2_setlen(_buf,len) do { \
139         uint8_t *buf = (uint8_t *)_buf; \
140         buf[0] = 0; \
141         buf[1] = ((len)&0xFF0000)>>16; \
142         buf[2] = ((len)&0xFF00)>>8; \
143         buf[3] = (len)&0xFF; \
144 } while (0)
145
146 static void smb2_setup_nbt_length(struct iovec *vector, int count)
147 {
148         size_t len = 0;
149         int i;
150
151         for (i=1; i < count; i++) {
152                 len += vector[i].iov_len;
153         }
154
155         _smb2_setlen(vector[0].iov_base, len);
156 }
157
158 static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
159 {
160         if (*req) {
161                 (*req)->parent = NULL;
162                 (*req)->mem_pool = NULL;
163         }
164
165         return 0;
166 }
167
168 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
169 {
170         if (req->parent) {
171                 *req->parent = NULL;
172                 talloc_free(req->mem_pool);
173         }
174
175         return 0;
176 }
177
178 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
179 {
180         TALLOC_CTX *mem_pool;
181         struct smbd_smb2_request **parent;
182         struct smbd_smb2_request *req;
183
184 #if 0
185         /* Enable this to find subtle valgrind errors. */
186         mem_pool = talloc_init("smbd_smb2_request_allocate");
187 #else
188         mem_pool = talloc_pool(mem_ctx, 8192);
189 #endif
190         if (mem_pool == NULL) {
191                 return NULL;
192         }
193
194         parent = talloc(mem_pool, struct smbd_smb2_request *);
195         if (parent == NULL) {
196                 talloc_free(mem_pool);
197                 return NULL;
198         }
199
200         req = talloc_zero(parent, struct smbd_smb2_request);
201         if (req == NULL) {
202                 talloc_free(mem_pool);
203                 return NULL;
204         }
205         *parent         = req;
206         req->mem_pool   = mem_pool;
207         req->parent     = parent;
208
209         talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
210         talloc_set_destructor(req, smbd_smb2_request_destructor);
211
212         return req;
213 }
214
215 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
216                                          const uint8_t *inbuf, size_t size,
217                                          struct smbd_smb2_request **_req)
218 {
219         struct smbd_smb2_request *req;
220         uint32_t protocol_version;
221         const uint8_t *inhdr = NULL;
222         off_t ofs = 0;
223         uint16_t cmd;
224         uint32_t next_command_ofs;
225
226         if (size < (4 + SMB2_HDR_BODY + 2)) {
227                 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
228                 return NT_STATUS_INVALID_PARAMETER;
229         }
230
231         inhdr = inbuf + 4;
232
233         protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
234         if (protocol_version != SMB2_MAGIC) {
235                 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
236                          protocol_version));
237                 return NT_STATUS_INVALID_PARAMETER;
238         }
239
240         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
241         if (cmd != SMB2_OP_NEGPROT) {
242                 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
243                          cmd));
244                 return NT_STATUS_INVALID_PARAMETER;
245         }
246
247         next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
248         if (next_command_ofs != 0) {
249                 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
250                          next_command_ofs));
251                 return NT_STATUS_INVALID_PARAMETER;
252         }
253
254         req = smbd_smb2_request_allocate(sconn);
255         if (req == NULL) {
256                 return NT_STATUS_NO_MEMORY;
257         }
258         req->sconn = sconn;
259
260         talloc_steal(req, inbuf);
261
262         req->in.vector = talloc_array(req, struct iovec, 4);
263         if (req->in.vector == NULL) {
264                 TALLOC_FREE(req);
265                 return NT_STATUS_NO_MEMORY;
266         }
267         req->in.vector_count = 4;
268
269         memcpy(req->in.nbt_hdr, inbuf, 4);
270
271         ofs = 0;
272         req->in.vector[0].iov_base      = discard_const_p(void, req->in.nbt_hdr);
273         req->in.vector[0].iov_len       = 4;
274         ofs += req->in.vector[0].iov_len;
275
276         req->in.vector[1].iov_base      = discard_const_p(void, (inbuf + ofs));
277         req->in.vector[1].iov_len       = SMB2_HDR_BODY;
278         ofs += req->in.vector[1].iov_len;
279
280         req->in.vector[2].iov_base      = discard_const_p(void, (inbuf + ofs));
281         req->in.vector[2].iov_len       = SVAL(inbuf, ofs) & 0xFFFE;
282         ofs += req->in.vector[2].iov_len;
283
284         if (ofs > size) {
285                 return NT_STATUS_INVALID_PARAMETER;
286         }
287
288         req->in.vector[3].iov_base      = discard_const_p(void, (inbuf + ofs));
289         req->in.vector[3].iov_len       = size - ofs;
290         ofs += req->in.vector[3].iov_len;
291
292         req->current_idx = 1;
293
294         *_req = req;
295         return NT_STATUS_OK;
296 }
297
298 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
299                                 const uint8_t *inhdr)
300 {
301         uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
302         struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
303         uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
304         unsigned int bitmap_offset;
305
306         if (opcode == SMB2_OP_CANCEL) {
307                 /* SMB2_CANCEL requests by definition resend messageids. */
308                 return true;
309         }
310
311         if (message_id < sconn->smb2.seqnum_low ||
312                         message_id > (sconn->smb2.seqnum_low +
313                         (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
314                 DEBUG(0,("smb2_validate_message_id: bad message_id "
315                         "%llu (low = %llu, max = %lu)\n",
316                         (unsigned long long)message_id,
317                         (unsigned long long)sconn->smb2.seqnum_low,
318                         (unsigned long)sconn->smb2.max_credits ));
319                 return false;
320         }
321
322         /* client just used a credit. */
323         SMB_ASSERT(sconn->smb2.credits_granted > 0);
324         sconn->smb2.credits_granted -= 1;
325
326         /* Mark the message_id as seen in the bitmap. */
327         bitmap_offset = (unsigned int)(message_id %
328                         (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
329         if (bitmap_query(credits_bm, bitmap_offset)) {
330                 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
331                         "%llu (bm offset %u)\n",
332                         (unsigned long long)message_id,
333                         bitmap_offset));
334                 return false;
335         }
336         bitmap_set(credits_bm, bitmap_offset);
337
338         if (message_id == sconn->smb2.seqnum_low + 1) {
339                 /* Move the window forward by all the message_id's
340                    already seen. */
341                 while (bitmap_query(credits_bm, bitmap_offset)) {
342                         DEBUG(10,("smb2_validate_message_id: clearing "
343                                 "id %llu (position %u) from bitmap\n",
344                                 (unsigned long long)(sconn->smb2.seqnum_low + 1),
345                                 bitmap_offset ));
346                         bitmap_clear(credits_bm, bitmap_offset);
347                         sconn->smb2.seqnum_low += 1;
348                         bitmap_offset = (bitmap_offset + 1) %
349                                 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
350                 }
351         }
352
353         return true;
354 }
355
356 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
357 {
358         int count;
359         int idx;
360         bool compound_related = false;
361
362         count = req->in.vector_count;
363
364         if (count < 4) {
365                 /* It's not a SMB2 request */
366                 return NT_STATUS_INVALID_PARAMETER;
367         }
368
369         for (idx=1; idx < count; idx += 3) {
370                 const uint8_t *inhdr = NULL;
371                 uint32_t flags;
372
373                 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
374                         return NT_STATUS_INVALID_PARAMETER;
375                 }
376
377                 if (req->in.vector[idx+1].iov_len < 2) {
378                         return NT_STATUS_INVALID_PARAMETER;
379                 }
380
381                 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
382
383                 /* Check the SMB2 header */
384                 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
385                         return NT_STATUS_INVALID_PARAMETER;
386                 }
387
388                 if (!smb2_validate_message_id(req->sconn, inhdr)) {
389                         return NT_STATUS_INVALID_PARAMETER;
390                 }
391
392                 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
393                 if (idx == 1) {
394                         /*
395                          * the 1st request should never have the
396                          * SMB2_HDR_FLAG_CHAINED flag set
397                          */
398                         if (flags & SMB2_HDR_FLAG_CHAINED) {
399                                 req->next_status = NT_STATUS_INVALID_PARAMETER;
400                                 return NT_STATUS_OK;
401                         }
402                 } else if (idx == 4) {
403                         /*
404                          * the 2nd request triggers related vs. unrelated
405                          * compounded requests
406                          */
407                         if (flags & SMB2_HDR_FLAG_CHAINED) {
408                                 compound_related = true;
409                         }
410                 } else if (idx > 4) {
411 #if 0
412                         /*
413                          * It seems the this tests are wrong
414                          * see the SMB2-COMPOUND test
415                          */
416
417                         /*
418                          * all other requests should match the 2nd one
419                          */
420                         if (flags & SMB2_HDR_FLAG_CHAINED) {
421                                 if (!compound_related) {
422                                         req->next_status =
423                                                 NT_STATUS_INVALID_PARAMETER;
424                                         return NT_STATUS_OK;
425                                 }
426                         } else {
427                                 if (compound_related) {
428                                         req->next_status =
429                                                 NT_STATUS_INVALID_PARAMETER;
430                                         return NT_STATUS_OK;
431                                 }
432                         }
433 #endif
434                 }
435         }
436
437         return NT_STATUS_OK;
438 }
439
440 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
441                         const struct iovec *in_vector,
442                         struct iovec *out_vector)
443 {
444         uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
445         uint16_t credits_requested = 0;
446         uint16_t credits_granted = 0;
447
448         if (in_vector != NULL) {
449                 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
450                 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
451         }
452
453         SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
454
455         /* Remember what we gave out. */
456         credits_granted = MIN(credits_requested, (sconn->smb2.max_credits -
457                 sconn->smb2.credits_granted));
458
459         if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
460                 /* First negprot packet, or ensure the client credits can
461                    never drop to zero. */
462                 credits_granted = 1;
463         }
464
465         SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
466         sconn->smb2.credits_granted += credits_granted;
467
468         DEBUG(10,("smb2_set_operation_credit: requested %u, "
469                 "granted %u, total granted %u\n",
470                 (unsigned int)credits_requested,
471                 (unsigned int)credits_granted,
472                 (unsigned int)sconn->smb2.credits_granted ));
473 }
474
475 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
476                                 struct smbd_smb2_request *outreq)
477 {
478         int count, idx;
479
480         count = outreq->out.vector_count;
481
482         for (idx=1; idx < count; idx += 3) {
483                 smb2_set_operation_credit(outreq->sconn,
484                         &inreq->in.vector[idx],
485                         &outreq->out.vector[idx]);
486         }
487 }
488
489 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
490 {
491         struct iovec *vector;
492         int count;
493         int idx;
494
495         count = req->in.vector_count;
496         vector = talloc_zero_array(req, struct iovec, count);
497         if (vector == NULL) {
498                 return NT_STATUS_NO_MEMORY;
499         }
500
501         vector[0].iov_base      = req->out.nbt_hdr;
502         vector[0].iov_len       = 4;
503         SIVAL(req->out.nbt_hdr, 0, 0);
504
505         for (idx=1; idx < count; idx += 3) {
506                 const uint8_t *inhdr = NULL;
507                 uint32_t in_flags;
508                 uint8_t *outhdr = NULL;
509                 uint8_t *outbody = NULL;
510                 uint32_t next_command_ofs = 0;
511                 struct iovec *current = &vector[idx];
512
513                 if ((idx + 3) < count) {
514                         /* we have a next command -
515                          * setup for the error case. */
516                         next_command_ofs = SMB2_HDR_BODY + 9;
517                 }
518
519                 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
520                 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
521
522                 outhdr = talloc_zero_array(vector, uint8_t,
523                                       OUTVEC_ALLOC_SIZE);
524                 if (outhdr == NULL) {
525                         return NT_STATUS_NO_MEMORY;
526                 }
527
528                 outbody = outhdr + SMB2_HDR_BODY;
529
530                 current[0].iov_base     = (void *)outhdr;
531                 current[0].iov_len      = SMB2_HDR_BODY;
532
533                 current[1].iov_base     = (void *)outbody;
534                 current[1].iov_len      = 8;
535
536                 current[2].iov_base     = NULL;
537                 current[2].iov_len      = 0;
538
539                 /* setup the SMB2 header */
540                 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
541                 SSVAL(outhdr, SMB2_HDR_LENGTH,          SMB2_HDR_BODY);
542                 SSVAL(outhdr, SMB2_HDR_EPOCH,           0);
543                 SIVAL(outhdr, SMB2_HDR_STATUS,
544                       NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
545                 SSVAL(outhdr, SMB2_HDR_OPCODE,
546                       SVAL(inhdr, SMB2_HDR_OPCODE));
547                 SIVAL(outhdr, SMB2_HDR_FLAGS,
548                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
549                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
550                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
551                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
552                 SIVAL(outhdr, SMB2_HDR_PID,
553                       IVAL(inhdr, SMB2_HDR_PID));
554                 SIVAL(outhdr, SMB2_HDR_TID,
555                       IVAL(inhdr, SMB2_HDR_TID));
556                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
557                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
558                 memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
559
560                 /* setup error body header */
561                 SSVAL(outbody, 0x00, 0x08 + 1);
562                 SSVAL(outbody, 0x02, 0);
563                 SIVAL(outbody, 0x04, 0);
564         }
565
566         req->out.vector = vector;
567         req->out.vector_count = count;
568
569         /* setup the length of the NBT packet */
570         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
571
572         DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
573
574         return NT_STATUS_OK;
575 }
576
577 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
578                                          const char *reason,
579                                          const char *location)
580 {
581         DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
582                   reason, location));
583         exit_server_cleanly(reason);
584 }
585
586 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
587                         struct iovec *outvec,
588                         const struct iovec *srcvec)
589 {
590         /* vec[0] is always boilerplate and must
591          * be allocated with size OUTVEC_ALLOC_SIZE. */
592
593         outvec[0].iov_base = talloc_memdup(ctx,
594                                 srcvec[0].iov_base,
595                                 OUTVEC_ALLOC_SIZE);
596         if (!outvec[0].iov_base) {
597                 return false;
598         }
599         outvec[0].iov_len = SMB2_HDR_BODY;
600
601         /*
602          * If this is a "standard" vec[1] of length 8,
603          * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
604          * then duplicate this. Else use talloc_memdup().
605          */
606
607         if (srcvec[1].iov_len == 8 &&
608                         srcvec[1].iov_base ==
609                                 ((uint8_t *)srcvec[0].iov_base) +
610                                         SMB2_HDR_BODY) {
611                 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
612                                         SMB2_HDR_BODY;
613                 outvec[1].iov_len = 8;
614         } else {
615                 outvec[1].iov_base = talloc_memdup(ctx,
616                                 srcvec[1].iov_base,
617                                 srcvec[1].iov_len);
618                 if (!outvec[1].iov_base) {
619                         return false;
620                 }
621                 outvec[1].iov_len = srcvec[1].iov_len;
622         }
623
624         /*
625          * If this is a "standard" vec[2] of length 1,
626          * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
627          * then duplicate this. Else use talloc_memdup().
628          */
629
630         if (srcvec[2].iov_base &&
631                         srcvec[2].iov_len) {
632                 if (srcvec[2].iov_base ==
633                                 ((uint8_t *)srcvec[0].iov_base) +
634                                         (OUTVEC_ALLOC_SIZE - 1) &&
635                                 srcvec[2].iov_len == 1) {
636                         /* Common SMB2 error packet case. */
637                         outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
638                                 (OUTVEC_ALLOC_SIZE - 1);
639                 } else {
640                         outvec[2].iov_base = talloc_memdup(ctx,
641                                         srcvec[2].iov_base,
642                                         srcvec[2].iov_len);
643                         if (!outvec[2].iov_base) {
644                                 return false;
645                         }
646                 }
647                 outvec[2].iov_len = srcvec[2].iov_len;
648         } else {
649                 outvec[2].iov_base = NULL;
650                 outvec[2].iov_len = 0;
651         }
652         return true;
653 }
654
655 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
656 {
657         struct smbd_smb2_request *newreq = NULL;
658         struct iovec *outvec = NULL;
659         int count = req->out.vector_count;
660         int i;
661
662         newreq = smbd_smb2_request_allocate(req->sconn);
663         if (!newreq) {
664                 return NULL;
665         }
666
667         newreq->sconn = req->sconn;
668         newreq->do_signing = req->do_signing;
669         newreq->current_idx = req->current_idx;
670         newreq->async = false;
671         newreq->cancelled = false;
672
673         outvec = talloc_zero_array(newreq, struct iovec, count);
674         if (!outvec) {
675                 TALLOC_FREE(newreq);
676                 return NULL;
677         }
678         newreq->out.vector = outvec;
679         newreq->out.vector_count = count;
680
681         /* Setup the outvec's identically to req. */
682         outvec[0].iov_base = newreq->out.nbt_hdr;
683         outvec[0].iov_len = 4;
684         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
685
686         /* Setup the vectors identically to the ones in req. */
687         for (i = 1; i < count; i += 3) {
688                 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
689                         break;
690                 }
691         }
692
693         if (i < count) {
694                 /* Alloc failed. */
695                 TALLOC_FREE(newreq);
696                 return NULL;
697         }
698
699         smb2_setup_nbt_length(newreq->out.vector,
700                 newreq->out.vector_count);
701
702         return newreq;
703 }
704
705 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
706
707 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
708 {
709         int i = 0;
710         uint8_t *outhdr = NULL;
711         struct smbd_smb2_request *nreq = NULL;
712
713         /* Create a new smb2 request we'll use
714            for the interim return. */
715         nreq = dup_smb2_req(req);
716         if (!nreq) {
717                 return NT_STATUS_NO_MEMORY;
718         }
719
720         /* Lose the last 3 out vectors. They're the
721            ones we'll be using for the async reply. */
722         nreq->out.vector_count -= 3;
723
724         smb2_setup_nbt_length(nreq->out.vector,
725                 nreq->out.vector_count);
726
727         /* Step back to the previous reply. */
728         i = nreq->current_idx - 3;
729         outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
730         /* And end the chain. */
731         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
732
733         /* Calculate outgoing credits */
734         smb2_calculate_credits(req, nreq);
735
736         /* Re-sign if needed. */
737         if (nreq->do_signing) {
738                 NTSTATUS status;
739                 status = smb2_signing_sign_pdu(nreq->session->session_key,
740                                         &nreq->out.vector[i], 3);
741                 if (!NT_STATUS_IS_OK(status)) {
742                         return status;
743                 }
744         }
745         if (DEBUGLEVEL >= 10) {
746                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
747                         (unsigned int)nreq->current_idx );
748                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
749                         (unsigned int)nreq->out.vector_count );
750                 print_req_vectors(nreq);
751         }
752         nreq->subreq = tstream_writev_queue_send(nreq,
753                                         nreq->sconn->smb2.event_ctx,
754                                         nreq->sconn->smb2.stream,
755                                         nreq->sconn->smb2.send_queue,
756                                         nreq->out.vector,
757                                         nreq->out.vector_count);
758
759         if (nreq->subreq == NULL) {
760                 return NT_STATUS_NO_MEMORY;
761         }
762
763         tevent_req_set_callback(nreq->subreq,
764                         smbd_smb2_request_writev_done,
765                         nreq);
766
767         return NT_STATUS_OK;
768 }
769
770 struct smbd_smb2_request_pending_state {
771         struct smbd_server_connection *sconn;
772         uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
773         struct iovec vector[3];
774 };
775
776 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
777 {
778         struct smbd_smb2_request_pending_state *state =
779                 tevent_req_callback_data(subreq,
780                         struct smbd_smb2_request_pending_state);
781         struct smbd_server_connection *sconn = state->sconn;
782         int ret;
783         int sys_errno;
784
785         ret = tstream_writev_queue_recv(subreq, &sys_errno);
786         TALLOC_FREE(subreq);
787         if (ret == -1) {
788                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
789                 smbd_server_connection_terminate(sconn, nt_errstr(status));
790                 return;
791         }
792
793         TALLOC_FREE(state);
794 }
795
796 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
797                                          struct tevent_req *subreq)
798 {
799         NTSTATUS status;
800         struct smbd_smb2_request_pending_state *state = NULL;
801         int i = req->current_idx;
802         uint8_t *reqhdr = NULL;
803         uint8_t *hdr = NULL;
804         uint8_t *body = NULL;
805         uint32_t flags = 0;
806         uint64_t message_id = 0;
807         uint64_t async_id = 0;
808         struct iovec *outvec = NULL;
809
810         if (!tevent_req_is_in_progress(subreq)) {
811                 return NT_STATUS_OK;
812         }
813
814         req->subreq = subreq;
815         subreq = NULL;
816
817         if (req->async) {
818                 /* We're already async. */
819                 return NT_STATUS_OK;
820         }
821
822         if (req->in.vector_count > i + 3) {
823                 /*
824                  * We're trying to go async in a compound
825                  * request chain. This is not allowed.
826                  * Cancel the outstanding request.
827                  */
828                 tevent_req_cancel(req->subreq);
829                 return smbd_smb2_request_error(req,
830                         NT_STATUS_INSUFFICIENT_RESOURCES);
831         }
832
833         if (DEBUGLEVEL >= 10) {
834                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
835                         (unsigned int)req->current_idx );
836                 print_req_vectors(req);
837         }
838
839         if (req->out.vector_count > 4) {
840                 /* This is a compound reply. We
841                  * must do an interim response
842                  * followed by the async response
843                  * to match W2K8R2.
844                  */
845                 status = smb2_send_async_interim_response(req);
846                 if (!NT_STATUS_IS_OK(status)) {
847                         return status;
848                 }
849         }
850
851         /* Don't return an intermediate packet on a pipe read/write. */
852         if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
853                 return NT_STATUS_OK;
854         }
855
856         reqhdr = (uint8_t *)req->out.vector[i].iov_base;
857         flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
858         message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
859         async_id = message_id; /* keep it simple for now... */
860
861         /*
862          * What we send is identical to a smbd_smb2_request_error
863          * packet with an error status of STATUS_PENDING. Make use
864          * of this fact sometime when refactoring. JRA.
865          */
866
867         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
868         if (state == NULL) {
869                 return NT_STATUS_NO_MEMORY;
870         }
871         state->sconn = req->sconn;
872
873         state->vector[0].iov_base = (void *)state->buf;
874         state->vector[0].iov_len = 4;
875
876         state->vector[1].iov_base = state->buf + 4;
877         state->vector[1].iov_len = SMB2_HDR_BODY;
878
879         state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
880         state->vector[2].iov_len = 9;
881
882         smb2_setup_nbt_length(state->vector, 3);
883
884         hdr = (uint8_t *)state->vector[1].iov_base;
885         body = (uint8_t *)state->vector[2].iov_base;
886
887         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
888         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
889         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
890         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
891         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
892
893         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
894         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
895         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
896         SBVAL(hdr, SMB2_HDR_PID, async_id);
897         SBVAL(hdr, SMB2_HDR_SESSION_ID,
898                 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
899         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
900
901         SSVAL(body, 0x00, 0x08 + 1);
902
903         SCVAL(body, 0x02, 0);
904         SCVAL(body, 0x03, 0);
905         SIVAL(body, 0x04, 0);
906         /* Match W2K8R2... */
907         SCVAL(body, 0x08, 0x21);
908
909         /* Ensure we correctly go through crediting. Grant
910            the credits now, and zero credits on the final
911            response. */
912         smb2_set_operation_credit(req->sconn,
913                         &req->in.vector[i],
914                         &state->vector[1]);
915
916         if (req->do_signing) {
917                 status = smb2_signing_sign_pdu(req->session->session_key,
918                                         state->vector, 3);
919                 if (!NT_STATUS_IS_OK(status)) {
920                         return status;
921                 }
922         }
923
924         subreq = tstream_writev_queue_send(state,
925                                         req->sconn->smb2.event_ctx,
926                                         req->sconn->smb2.stream,
927                                         req->sconn->smb2.send_queue,
928                                         state->vector,
929                                         3);
930
931         if (subreq == NULL) {
932                 return NT_STATUS_NO_MEMORY;
933         }
934
935         tevent_req_set_callback(subreq,
936                         smbd_smb2_request_pending_writev_done,
937                         state);
938
939         /* Note we're going async with this request. */
940         req->async = true;
941
942         /*
943          * Now manipulate req so that the outstanding async request
944          * is the only one left in the struct smbd_smb2_request.
945          */
946
947         if (req->current_idx == 1) {
948                 /* There was only one. */
949                 goto out;
950         }
951
952         /* Re-arrange the in.vectors. */
953         req->in.vector[1] = req->in.vector[i];
954         req->in.vector[2] = req->in.vector[i+1];
955         req->in.vector[3] = req->in.vector[i+2];
956         req->in.vector_count = 4;
957         /* Reset the new in size. */
958         smb2_setup_nbt_length(req->in.vector, 4);
959
960         /* Now recreate the out.vectors. */
961         outvec = talloc_zero_array(req, struct iovec, 4);
962         if (!outvec) {
963                 return NT_STATUS_NO_MEMORY;
964         }
965
966         /* 0 is always boilerplate and must
967          * be of size 4 for the length field. */
968
969         outvec[0].iov_base = req->out.nbt_hdr;
970         outvec[0].iov_len = 4;
971         SIVAL(req->out.nbt_hdr, 0, 0);
972
973         if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
974                 return NT_STATUS_NO_MEMORY;
975         }
976
977         TALLOC_FREE(req->out.vector);
978
979         req->out.vector = outvec;
980
981         req->current_idx = 1;
982         req->out.vector_count = 4;
983
984   out:
985
986         smb2_setup_nbt_length(req->out.vector,
987                 req->out.vector_count);
988
989         /* Ensure our final reply matches the interim one. */
990         reqhdr = (uint8_t *)req->out.vector[1].iov_base;
991         SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
992         SBVAL(reqhdr, SMB2_HDR_PID, async_id);
993
994         {
995                 const uint8_t *inhdr =
996                         (const uint8_t *)req->in.vector[1].iov_base;
997                 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
998                         "going async\n",
999                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1000                         (unsigned long long)async_id ));
1001         }
1002         return NT_STATUS_OK;
1003 }
1004
1005 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1006 {
1007         struct smbd_server_connection *sconn = req->sconn;
1008         struct smbd_smb2_request *cur;
1009         const uint8_t *inhdr;
1010         int i = req->current_idx;
1011         uint32_t flags;
1012         uint64_t search_message_id;
1013         uint64_t search_async_id;
1014         uint64_t found_id;
1015
1016         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1017
1018         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1019         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1020         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1021
1022         /*
1023          * we don't need the request anymore
1024          * cancel requests never have a response
1025          */
1026         DLIST_REMOVE(req->sconn->smb2.requests, req);
1027         TALLOC_FREE(req);
1028
1029         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1030                 const uint8_t *outhdr;
1031                 uint64_t message_id;
1032                 uint64_t async_id;
1033
1034                 i = cur->current_idx;
1035
1036                 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1037
1038                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1039                 async_id = BVAL(outhdr, SMB2_HDR_PID);
1040
1041                 if (flags & SMB2_HDR_FLAG_ASYNC) {
1042                         if (search_async_id == async_id) {
1043                                 found_id = async_id;
1044                                 break;
1045                         }
1046                 } else {
1047                         if (search_message_id == message_id) {
1048                                 found_id = message_id;
1049                                 break;
1050                         }
1051                 }
1052         }
1053
1054         if (cur && cur->subreq) {
1055                 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1056                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1057                         "cancel opcode[%s] mid %llu\n",
1058                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1059                         (unsigned long long)found_id ));
1060                 tevent_req_cancel(cur->subreq);
1061         }
1062
1063         return NT_STATUS_OK;
1064 }
1065
1066 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1067 {
1068         const uint8_t *inhdr;
1069         int i = req->current_idx;
1070         uint16_t opcode;
1071         uint32_t flags;
1072         uint64_t mid;
1073         NTSTATUS status;
1074         NTSTATUS session_status;
1075         uint32_t allowed_flags;
1076         NTSTATUS return_value;
1077
1078         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1079
1080         /* TODO: verify more things */
1081
1082         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1083         opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1084         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1085         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1086                 smb2_opcode_name(opcode),
1087                 (unsigned long long)mid));
1088
1089         allowed_flags = SMB2_HDR_FLAG_CHAINED |
1090                         SMB2_HDR_FLAG_SIGNED |
1091                         SMB2_HDR_FLAG_DFS;
1092         if (opcode == SMB2_OP_CANCEL) {
1093                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1094         }
1095         if ((flags & ~allowed_flags) != 0) {
1096                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1097         }
1098
1099         session_status = smbd_smb2_request_check_session(req);
1100
1101         req->do_signing = false;
1102         if (flags & SMB2_HDR_FLAG_SIGNED) {
1103                 if (!NT_STATUS_IS_OK(session_status)) {
1104                         return smbd_smb2_request_error(req, session_status);
1105                 }
1106
1107                 req->do_signing = true;
1108                 status = smb2_signing_check_pdu(req->session->session_key,
1109                                                 &req->in.vector[i], 3);
1110                 if (!NT_STATUS_IS_OK(status)) {
1111                         return smbd_smb2_request_error(req, status);
1112                 }
1113         } else if (req->session && req->session->do_signing) {
1114                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1115         }
1116
1117         if (flags & SMB2_HDR_FLAG_CHAINED) {
1118                 /*
1119                  * This check is mostly for giving the correct error code
1120                  * for compounded requests.
1121                  *
1122                  * TODO: we may need to move this after the session
1123                  *       and tcon checks.
1124                  */
1125                 if (!NT_STATUS_IS_OK(req->next_status)) {
1126                         return smbd_smb2_request_error(req, req->next_status);
1127                 }
1128         } else {
1129                 req->compat_chain_fsp = NULL;
1130         }
1131
1132         switch (opcode) {
1133         case SMB2_OP_NEGPROT:
1134                 {
1135                         START_PROFILE(smb2_negprot);
1136                         return_value = smbd_smb2_request_process_negprot(req);
1137                         END_PROFILE(smb2_negprot);
1138                 }
1139                 break;
1140
1141         case SMB2_OP_SESSSETUP:
1142                 {
1143                         START_PROFILE(smb2_sesssetup);
1144                         return_value = smbd_smb2_request_process_sesssetup(req);
1145                         END_PROFILE(smb2_sesssetup);
1146                 }
1147                 break;
1148
1149         case SMB2_OP_LOGOFF:
1150                 if (!NT_STATUS_IS_OK(session_status)) {
1151                         return_value = smbd_smb2_request_error(req, session_status);
1152                         break;
1153                 }
1154
1155                 {
1156                         START_PROFILE(smb2_logoff);
1157                         return_value = smbd_smb2_request_process_logoff(req);
1158                         END_PROFILE(smb2_logoff);
1159                 }
1160                 break;
1161
1162         case SMB2_OP_TCON:
1163                 if (!NT_STATUS_IS_OK(session_status)) {
1164                         return_value = smbd_smb2_request_error(req, session_status);
1165                         break;
1166                 }
1167                 status = smbd_smb2_request_check_session(req);
1168                 if (!NT_STATUS_IS_OK(status)) {
1169                         return_value = smbd_smb2_request_error(req, status);
1170                         break;
1171                 }
1172
1173                 {
1174                         START_PROFILE(smb2_tcon);
1175                         return_value = smbd_smb2_request_process_tcon(req);
1176                         END_PROFILE(smb2_tcon);
1177                 }
1178                 break;
1179
1180         case SMB2_OP_TDIS:
1181                 if (!NT_STATUS_IS_OK(session_status)) {
1182                         return_value = smbd_smb2_request_error(req, session_status);
1183                         break;
1184                 }
1185                 status = smbd_smb2_request_check_tcon(req);
1186                 if (!NT_STATUS_IS_OK(status)) {
1187                         return_value = smbd_smb2_request_error(req, status);
1188                         break;
1189                 }
1190
1191                 {
1192                         START_PROFILE(smb2_tdis);
1193                         return_value = smbd_smb2_request_process_tdis(req);
1194                         END_PROFILE(smb2_tdis);
1195                 }
1196                 break;
1197
1198         case SMB2_OP_CREATE:
1199                 if (!NT_STATUS_IS_OK(session_status)) {
1200                         return_value = smbd_smb2_request_error(req, session_status);
1201                         break;
1202                 }
1203                 status = smbd_smb2_request_check_tcon(req);
1204                 if (!NT_STATUS_IS_OK(status)) {
1205                         return_value = smbd_smb2_request_error(req, status);
1206                         break;
1207                 }
1208
1209                 {
1210                         START_PROFILE(smb2_create);
1211                         return_value = smbd_smb2_request_process_create(req);
1212                         END_PROFILE(smb2_create);
1213                 }
1214                 break;
1215
1216         case SMB2_OP_CLOSE:
1217                 if (!NT_STATUS_IS_OK(session_status)) {
1218                         return_value = smbd_smb2_request_error(req, session_status);
1219                         break;
1220                 }
1221                 status = smbd_smb2_request_check_tcon(req);
1222                 if (!NT_STATUS_IS_OK(status)) {
1223                         return_value = smbd_smb2_request_error(req, status);
1224                         break;
1225                 }
1226
1227                 {
1228                         START_PROFILE(smb2_close);
1229                         return_value = smbd_smb2_request_process_close(req);
1230                         END_PROFILE(smb2_close);
1231                 }
1232                 break;
1233
1234         case SMB2_OP_FLUSH:
1235                 if (!NT_STATUS_IS_OK(session_status)) {
1236                         return_value = smbd_smb2_request_error(req, session_status);
1237                         break;
1238                 }
1239                 status = smbd_smb2_request_check_tcon(req);
1240                 if (!NT_STATUS_IS_OK(status)) {
1241                         return_value = smbd_smb2_request_error(req, status);
1242                         break;
1243                 }
1244
1245                 {
1246                         START_PROFILE(smb2_flush);
1247                         return_value = smbd_smb2_request_process_flush(req);
1248                         END_PROFILE(smb2_flush);
1249                 }
1250                 break;
1251
1252         case SMB2_OP_READ:
1253                 if (!NT_STATUS_IS_OK(session_status)) {
1254                         return_value = smbd_smb2_request_error(req, session_status);
1255                         break;
1256                 }
1257                 status = smbd_smb2_request_check_tcon(req);
1258                 if (!NT_STATUS_IS_OK(status)) {
1259                         return_value = smbd_smb2_request_error(req, status);
1260                         break;
1261                 }
1262
1263                 {
1264                         START_PROFILE(smb2_read);
1265                         return_value = smbd_smb2_request_process_read(req);
1266                         END_PROFILE(smb2_read);
1267                 }
1268                 break;
1269
1270         case SMB2_OP_WRITE:
1271                 if (!NT_STATUS_IS_OK(session_status)) {
1272                         return_value = smbd_smb2_request_error(req, session_status);
1273                         break;
1274                 }
1275                 status = smbd_smb2_request_check_tcon(req);
1276                 if (!NT_STATUS_IS_OK(status)) {
1277                         return_value = smbd_smb2_request_error(req, status);
1278                         break;
1279                 }
1280
1281                 {
1282                         START_PROFILE(smb2_write);
1283                         return_value = smbd_smb2_request_process_write(req);
1284                         END_PROFILE(smb2_write);
1285                 }
1286                 break;
1287
1288         case SMB2_OP_LOCK:
1289                 if (!NT_STATUS_IS_OK(session_status)) {
1290                         /* Too ugly to live ? JRA. */
1291                         if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1292                                 session_status = NT_STATUS_FILE_CLOSED;
1293                         }
1294                         return_value = smbd_smb2_request_error(req, session_status);
1295                         break;
1296                 }
1297                 status = smbd_smb2_request_check_tcon(req);
1298                 if (!NT_STATUS_IS_OK(status)) {
1299                         /* Too ugly to live ? JRA. */
1300                         if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1301                                 status = NT_STATUS_FILE_CLOSED;
1302                         }
1303                         return_value = smbd_smb2_request_error(req, status);
1304                         break;
1305                 }
1306
1307                 {
1308                         START_PROFILE(smb2_lock);
1309                         return_value = smbd_smb2_request_process_lock(req);
1310                         END_PROFILE(smb2_lock);
1311                 }
1312                 break;
1313
1314         case SMB2_OP_IOCTL:
1315                 if (!NT_STATUS_IS_OK(session_status)) {
1316                         return_value = smbd_smb2_request_error(req, session_status);
1317                         break;
1318                 }
1319                 status = smbd_smb2_request_check_tcon(req);
1320                 if (!NT_STATUS_IS_OK(status)) {
1321                         return_value = smbd_smb2_request_error(req, status);
1322                         break;
1323                 }
1324
1325                 {
1326                         START_PROFILE(smb2_ioctl);
1327                         return_value = smbd_smb2_request_process_ioctl(req);
1328                         END_PROFILE(smb2_ioctl);
1329                 }
1330                 break;
1331
1332         case SMB2_OP_CANCEL:
1333                 {
1334                         START_PROFILE(smb2_cancel);
1335                         return_value = smbd_smb2_request_process_cancel(req);
1336                         END_PROFILE(smb2_cancel);
1337                 }
1338                 break;
1339
1340         case SMB2_OP_KEEPALIVE:
1341                 {START_PROFILE(smb2_keepalive);
1342                 return_value = smbd_smb2_request_process_keepalive(req);
1343                 END_PROFILE(smb2_keepalive);}
1344                 break;
1345
1346         case SMB2_OP_FIND:
1347                 if (!NT_STATUS_IS_OK(session_status)) {
1348                         return_value = smbd_smb2_request_error(req, session_status);
1349                         break;
1350                 }
1351                 status = smbd_smb2_request_check_tcon(req);
1352                 if (!NT_STATUS_IS_OK(status)) {
1353                         return_value = smbd_smb2_request_error(req, status);
1354                         break;
1355                 }
1356
1357                 {
1358                         START_PROFILE(smb2_find);
1359                         return_value = smbd_smb2_request_process_find(req);
1360                         END_PROFILE(smb2_find);
1361                 }
1362                 break;
1363
1364         case SMB2_OP_NOTIFY:
1365                 if (!NT_STATUS_IS_OK(session_status)) {
1366                         return_value = smbd_smb2_request_error(req, session_status);
1367                         break;
1368                 }
1369                 status = smbd_smb2_request_check_tcon(req);
1370                 if (!NT_STATUS_IS_OK(status)) {
1371                         return_value = smbd_smb2_request_error(req, status);
1372                         break;
1373                 }
1374
1375                 {
1376                         START_PROFILE(smb2_notify);
1377                         return_value = smbd_smb2_request_process_notify(req);
1378                         END_PROFILE(smb2_notify);
1379                 }
1380                 break;
1381
1382         case SMB2_OP_GETINFO:
1383                 if (!NT_STATUS_IS_OK(session_status)) {
1384                         return_value = smbd_smb2_request_error(req, session_status);
1385                         break;
1386                 }
1387                 status = smbd_smb2_request_check_tcon(req);
1388                 if (!NT_STATUS_IS_OK(status)) {
1389                         return_value = smbd_smb2_request_error(req, status);
1390                         break;
1391                 }
1392
1393                 {
1394                         START_PROFILE(smb2_getinfo);
1395                         return_value = smbd_smb2_request_process_getinfo(req);
1396                         END_PROFILE(smb2_getinfo);
1397                 }
1398                 break;
1399
1400         case SMB2_OP_SETINFO:
1401                 if (!NT_STATUS_IS_OK(session_status)) {
1402                         return_value = smbd_smb2_request_error(req, session_status);
1403                         break;
1404                 }
1405                 status = smbd_smb2_request_check_tcon(req);
1406                 if (!NT_STATUS_IS_OK(status)) {
1407                         return_value = smbd_smb2_request_error(req, status);
1408                         break;
1409                 }
1410
1411                 {
1412                         START_PROFILE(smb2_setinfo);
1413                         return_value = smbd_smb2_request_process_setinfo(req);
1414                         END_PROFILE(smb2_setinfo);
1415                 }
1416                 break;
1417
1418         case SMB2_OP_BREAK:
1419                 if (!NT_STATUS_IS_OK(session_status)) {
1420                         return_value = smbd_smb2_request_error(req, session_status);
1421                         break;
1422                 }
1423                 status = smbd_smb2_request_check_tcon(req);
1424                 if (!NT_STATUS_IS_OK(status)) {
1425                         return_value = smbd_smb2_request_error(req, status);
1426                         break;
1427                 }
1428
1429                 {
1430                         START_PROFILE(smb2_break);
1431                         return_value = smbd_smb2_request_process_break(req);
1432                         END_PROFILE(smb2_break);
1433                 }
1434                 break;
1435
1436         default:
1437                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1438                 break;
1439         }
1440         return return_value;
1441 }
1442
1443 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1444 {
1445         struct tevent_req *subreq;
1446         int i = req->current_idx;
1447
1448         req->subreq = NULL;
1449
1450         req->current_idx += 3;
1451
1452         if (req->current_idx < req->out.vector_count) {
1453                 /*
1454                  * We must process the remaining compound
1455                  * SMB2 requests before any new incoming SMB2
1456                  * requests. This is because incoming SMB2
1457                  * requests may include a cancel for a
1458                  * compound request we haven't processed
1459                  * yet.
1460                  */
1461                 struct tevent_immediate *im = tevent_create_immediate(req);
1462                 if (!im) {
1463                         return NT_STATUS_NO_MEMORY;
1464                 }
1465                 tevent_schedule_immediate(im,
1466                                         req->sconn->smb2.event_ctx,
1467                                         smbd_smb2_request_dispatch_immediate,
1468                                         req);
1469                 return NT_STATUS_OK;
1470         }
1471
1472         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1473
1474         /* Set credit for this operation (zero credits if this
1475            is a final reply for an async operation). */
1476         smb2_set_operation_credit(req->sconn,
1477                         req->async ? NULL : &req->in.vector[i],
1478                         &req->out.vector[i]);
1479
1480         if (req->do_signing) {
1481                 NTSTATUS status;
1482                 status = smb2_signing_sign_pdu(req->session->session_key,
1483                                                &req->out.vector[i], 3);
1484                 if (!NT_STATUS_IS_OK(status)) {
1485                         return status;
1486                 }
1487         }
1488
1489         if (DEBUGLEVEL >= 10) {
1490                 dbgtext("smbd_smb2_request_reply: sending...\n");
1491                 print_req_vectors(req);
1492         }
1493
1494         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1495         if (req->out.vector_count == 4 &&
1496                         req->out.vector[3].iov_base == NULL &&
1497                         req->out.vector[3].iov_len != 0) {
1498                 /* Dynamic part is NULL. Chop it off,
1499                    We're going to send it via sendfile. */
1500                 req->out.vector_count -= 1;
1501         }
1502
1503         subreq = tstream_writev_queue_send(req,
1504                                            req->sconn->smb2.event_ctx,
1505                                            req->sconn->smb2.stream,
1506                                            req->sconn->smb2.send_queue,
1507                                            req->out.vector,
1508                                            req->out.vector_count);
1509         if (subreq == NULL) {
1510                 return NT_STATUS_NO_MEMORY;
1511         }
1512         tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1513         /*
1514          * We're done with this request -
1515          * move it off the "being processed" queue.
1516          */
1517         DLIST_REMOVE(req->sconn->smb2.requests, req);
1518
1519         return NT_STATUS_OK;
1520 }
1521
1522 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1523                                         struct tevent_immediate *im,
1524                                         void *private_data)
1525 {
1526         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1527                                         struct smbd_smb2_request);
1528         struct smbd_server_connection *sconn = req->sconn;
1529         NTSTATUS status;
1530
1531         TALLOC_FREE(im);
1532
1533         if (DEBUGLEVEL >= 10) {
1534                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1535                         req->current_idx, req->in.vector_count));
1536                 print_req_vectors(req);
1537         }
1538
1539         status = smbd_smb2_request_dispatch(req);
1540         if (!NT_STATUS_IS_OK(status)) {
1541                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1542                 return;
1543         }
1544 }
1545
1546 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1547 {
1548         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1549                                         struct smbd_smb2_request);
1550         struct smbd_server_connection *sconn = req->sconn;
1551         int ret;
1552         int sys_errno;
1553
1554         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1555         TALLOC_FREE(subreq);
1556         TALLOC_FREE(req);
1557         if (ret == -1) {
1558                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1559                 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1560                         nt_errstr(status)));
1561                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1562                 return;
1563         }
1564 }
1565
1566 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1567                                    NTSTATUS status,
1568                                    DATA_BLOB body, DATA_BLOB *dyn,
1569                                    const char *location)
1570 {
1571         uint8_t *outhdr;
1572         int i = req->current_idx;
1573         uint32_t next_command_ofs;
1574
1575         DEBUG(10,("smbd_smb2_request_done_ex: "
1576                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1577                   i, nt_errstr(status), (unsigned int)body.length,
1578                   dyn ? "yes": "no",
1579                   (unsigned int)(dyn ? dyn->length : 0),
1580                   location));
1581
1582         if (body.length < 2) {
1583                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1584         }
1585
1586         if ((body.length % 2) != 0) {
1587                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1588         }
1589
1590         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1591
1592         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1593         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1594
1595         req->out.vector[i+1].iov_base = (void *)body.data;
1596         req->out.vector[i+1].iov_len = body.length;
1597
1598         if (dyn) {
1599                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
1600                 req->out.vector[i+2].iov_len    = dyn->length;
1601         } else {
1602                 req->out.vector[i+2].iov_base = NULL;
1603                 req->out.vector[i+2].iov_len = 0;
1604         }
1605
1606         /* see if we need to recalculate the offset to the next response */
1607         if (next_command_ofs > 0) {
1608                 next_command_ofs  = SMB2_HDR_BODY;
1609                 next_command_ofs += req->out.vector[i+1].iov_len;
1610                 next_command_ofs += req->out.vector[i+2].iov_len;
1611         }
1612
1613         if ((next_command_ofs % 8) != 0) {
1614                 size_t pad_size = 8 - (next_command_ofs % 8);
1615                 if (req->out.vector[i+2].iov_len == 0) {
1616                         /*
1617                          * if the dyn buffer is empty
1618                          * we can use it to add padding
1619                          */
1620                         uint8_t *pad;
1621
1622                         pad = talloc_zero_array(req->out.vector,
1623                                                 uint8_t, pad_size);
1624                         if (pad == NULL) {
1625                                 return smbd_smb2_request_error(req,
1626                                                 NT_STATUS_NO_MEMORY);
1627                         }
1628
1629                         req->out.vector[i+2].iov_base = (void *)pad;
1630                         req->out.vector[i+2].iov_len = pad_size;
1631                 } else {
1632                         /*
1633                          * For now we copy the dynamic buffer
1634                          * and add the padding to the new buffer
1635                          */
1636                         size_t old_size;
1637                         uint8_t *old_dyn;
1638                         size_t new_size;
1639                         uint8_t *new_dyn;
1640
1641                         old_size = req->out.vector[i+2].iov_len;
1642                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1643
1644                         new_size = old_size + pad_size;
1645                         new_dyn = talloc_zero_array(req->out.vector,
1646                                                uint8_t, new_size);
1647                         if (new_dyn == NULL) {
1648                                 return smbd_smb2_request_error(req,
1649                                                 NT_STATUS_NO_MEMORY);
1650                         }
1651
1652                         memcpy(new_dyn, old_dyn, old_size);
1653                         memset(new_dyn + old_size, 0, pad_size);
1654
1655                         req->out.vector[i+2].iov_base = (void *)new_dyn;
1656                         req->out.vector[i+2].iov_len = new_size;
1657                 }
1658                 next_command_ofs += pad_size;
1659         }
1660
1661         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1662
1663         return smbd_smb2_request_reply(req);
1664 }
1665
1666 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1667                                     NTSTATUS status,
1668                                     DATA_BLOB *info,
1669                                     const char *location)
1670 {
1671         DATA_BLOB body;
1672         int i = req->current_idx;
1673         uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1674
1675         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1676                   i, nt_errstr(status), info ? " +info" : "",
1677                   location));
1678
1679         body.data = outhdr + SMB2_HDR_BODY;
1680         body.length = 8;
1681         SSVAL(body.data, 0, 9);
1682
1683         if (info) {
1684                 SIVAL(body.data, 0x04, info->length);
1685         } else {
1686                 /* Allocated size of req->out.vector[i].iov_base
1687                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1688                  * 1 byte without having to do an alloc.
1689                  */
1690                 info = talloc_zero_array(req->out.vector,
1691                                         DATA_BLOB,
1692                                         1);
1693                 if (!info) {
1694                         return NT_STATUS_NO_MEMORY;
1695                 }
1696                 info->data = ((uint8_t *)outhdr) +
1697                         OUTVEC_ALLOC_SIZE - 1;
1698                 info->length = 1;
1699                 SCVAL(info->data, 0, 0);
1700         }
1701
1702         /*
1703          * if a request fails, all other remaining
1704          * compounded requests should fail too
1705          */
1706         req->next_status = NT_STATUS_INVALID_PARAMETER;
1707
1708         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1709 }
1710
1711
1712 struct smbd_smb2_send_oplock_break_state {
1713         struct smbd_server_connection *sconn;
1714         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1715         struct iovec vector;
1716 };
1717
1718 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1719
1720 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1721                                      uint64_t file_id_persistent,
1722                                      uint64_t file_id_volatile,
1723                                      uint8_t oplock_level)
1724 {
1725         struct smbd_smb2_send_oplock_break_state *state;
1726         struct tevent_req *subreq;
1727         uint8_t *hdr;
1728         uint8_t *body;
1729
1730         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1731         if (state == NULL) {
1732                 return NT_STATUS_NO_MEMORY;
1733         }
1734         state->sconn = sconn;
1735
1736         state->vector.iov_base = (void *)state->buf;
1737         state->vector.iov_len = sizeof(state->buf);
1738
1739         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1740         hdr = state->buf + 4;
1741         body = hdr + SMB2_HDR_BODY;
1742
1743         SIVAL(hdr, 0,                           SMB2_MAGIC);
1744         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
1745         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
1746         SIVAL(hdr, SMB2_HDR_STATUS,             0);
1747         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
1748         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
1749         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
1750         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
1751         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
1752         SIVAL(hdr, SMB2_HDR_PID,                0);
1753         SIVAL(hdr, SMB2_HDR_TID,                0);
1754         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
1755         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1756
1757         SSVAL(body, 0x00, 0x18);
1758
1759         SCVAL(body, 0x02, oplock_level);
1760         SCVAL(body, 0x03, 0);           /* reserved */
1761         SIVAL(body, 0x04, 0);           /* reserved */
1762         SBVAL(body, 0x08, file_id_persistent);
1763         SBVAL(body, 0x10, file_id_volatile);
1764
1765         subreq = tstream_writev_queue_send(state,
1766                                            sconn->smb2.event_ctx,
1767                                            sconn->smb2.stream,
1768                                            sconn->smb2.send_queue,
1769                                            &state->vector, 1);
1770         if (subreq == NULL) {
1771                 return NT_STATUS_NO_MEMORY;
1772         }
1773         tevent_req_set_callback(subreq,
1774                                 smbd_smb2_oplock_break_writev_done,
1775                                 state);
1776
1777         return NT_STATUS_OK;
1778 }
1779
1780 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1781 {
1782         struct smbd_smb2_send_oplock_break_state *state =
1783                 tevent_req_callback_data(subreq,
1784                 struct smbd_smb2_send_oplock_break_state);
1785         struct smbd_server_connection *sconn = state->sconn;
1786         int ret;
1787         int sys_errno;
1788
1789         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1790         TALLOC_FREE(subreq);
1791         if (ret == -1) {
1792                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1793                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1794                 return;
1795         }
1796
1797         TALLOC_FREE(state);
1798 }
1799
1800 struct smbd_smb2_request_read_state {
1801         size_t missing;
1802         bool asked_for_header;
1803         struct smbd_smb2_request *smb2_req;
1804 };
1805
1806 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1807                                          void *private_data,
1808                                          TALLOC_CTX *mem_ctx,
1809                                          struct iovec **_vector,
1810                                          size_t *_count);
1811 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1812
1813 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1814                                         struct tevent_context *ev,
1815                                         struct smbd_server_connection *sconn)
1816 {
1817         struct tevent_req *req;
1818         struct smbd_smb2_request_read_state *state;
1819         struct tevent_req *subreq;
1820
1821         req = tevent_req_create(mem_ctx, &state,
1822                                 struct smbd_smb2_request_read_state);
1823         if (req == NULL) {
1824                 return NULL;
1825         }
1826         state->missing = 0;
1827         state->asked_for_header = false;
1828
1829         state->smb2_req = smbd_smb2_request_allocate(state);
1830         if (tevent_req_nomem(state->smb2_req, req)) {
1831                 return tevent_req_post(req, ev);
1832         }
1833         state->smb2_req->sconn = sconn;
1834
1835         subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1836                                               sconn->smb2.recv_queue,
1837                                               smbd_smb2_request_next_vector,
1838                                               state);
1839         if (tevent_req_nomem(subreq, req)) {
1840                 return tevent_req_post(req, ev);
1841         }
1842         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1843
1844         return req;
1845 }
1846
1847 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1848                                          void *private_data,
1849                                          TALLOC_CTX *mem_ctx,
1850                                          struct iovec **_vector,
1851                                          size_t *_count)
1852 {
1853         struct smbd_smb2_request_read_state *state =
1854                 talloc_get_type_abort(private_data,
1855                 struct smbd_smb2_request_read_state);
1856         struct smbd_smb2_request *req = state->smb2_req;
1857         struct iovec *vector;
1858         int idx = req->in.vector_count;
1859         size_t len = 0;
1860         uint8_t *buf = NULL;
1861
1862         if (req->in.vector_count == 0) {
1863                 /*
1864                  * first we need to get the NBT header
1865                  */
1866                 req->in.vector = talloc_array(req, struct iovec,
1867                                               req->in.vector_count + 1);
1868                 if (req->in.vector == NULL) {
1869                         return -1;
1870                 }
1871                 req->in.vector_count += 1;
1872
1873                 req->in.vector[idx].iov_base    = (void *)req->in.nbt_hdr;
1874                 req->in.vector[idx].iov_len     = 4;
1875
1876                 vector = talloc_array(mem_ctx, struct iovec, 1);
1877                 if (vector == NULL) {
1878                         return -1;
1879                 }
1880
1881                 vector[0] = req->in.vector[idx];
1882
1883                 *_vector = vector;
1884                 *_count = 1;
1885                 return 0;
1886         }
1887
1888         if (req->in.vector_count == 1) {
1889                 /*
1890                  * Now we analyze the NBT header
1891                  */
1892                 state->missing = smb2_len(req->in.vector[0].iov_base);
1893
1894                 if (state->missing == 0) {
1895                         /* if there're no remaining bytes, we're done */
1896                         *_vector = NULL;
1897                         *_count = 0;
1898                         return 0;
1899                 }
1900
1901                 req->in.vector = talloc_realloc(req, req->in.vector,
1902                                                 struct iovec,
1903                                                 req->in.vector_count + 1);
1904                 if (req->in.vector == NULL) {
1905                         return -1;
1906                 }
1907                 req->in.vector_count += 1;
1908
1909                 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1910                         /*
1911                          * it's a special NBT message,
1912                          * so get all remaining bytes
1913                          */
1914                         len = state->missing;
1915                 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1916                         /*
1917                          * it's an invalid message, just read what we can get
1918                          * and let the caller handle the error
1919                          */
1920                         len = state->missing;
1921                 } else {
1922                         /*
1923                          * We assume it's a SMB2 request,
1924                          * and we first get the header and the
1925                          * first 2 bytes (the struct size) of the body
1926                          */
1927                         len = SMB2_HDR_BODY + 2;
1928
1929                         state->asked_for_header = true;
1930                 }
1931
1932                 state->missing -= len;
1933
1934                 buf = talloc_array(req->in.vector, uint8_t, len);
1935                 if (buf == NULL) {
1936                         return -1;
1937                 }
1938
1939                 req->in.vector[idx].iov_base    = (void *)buf;
1940                 req->in.vector[idx].iov_len     = len;
1941
1942                 vector = talloc_array(mem_ctx, struct iovec, 1);
1943                 if (vector == NULL) {
1944                         return -1;
1945                 }
1946
1947                 vector[0] = req->in.vector[idx];
1948
1949                 *_vector = vector;
1950                 *_count = 1;
1951                 return 0;
1952         }
1953
1954         if (state->missing == 0) {
1955                 /* if there're no remaining bytes, we're done */
1956                 *_vector = NULL;
1957                 *_count = 0;
1958                 return 0;
1959         }
1960
1961         if (state->asked_for_header) {
1962                 const uint8_t *hdr;
1963                 size_t full_size;
1964                 size_t next_command_ofs;
1965                 size_t body_size;
1966                 uint8_t *body;
1967                 size_t dyn_size;
1968                 uint8_t *dyn;
1969                 bool invalid = false;
1970
1971                 state->asked_for_header = false;
1972
1973                 /*
1974                  * We got the SMB2 header and the first 2 bytes
1975                  * of the body. We fix the size to just the header
1976                  * and manually copy the 2 first bytes to the body section
1977                  */
1978                 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1979                 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1980
1981                 /* allocate vectors for body and dynamic areas */
1982                 req->in.vector = talloc_realloc(req, req->in.vector,
1983                                                 struct iovec,
1984                                                 req->in.vector_count + 2);
1985                 if (req->in.vector == NULL) {
1986                         return -1;
1987                 }
1988                 req->in.vector_count += 2;
1989
1990                 full_size = state->missing + SMB2_HDR_BODY + 2;
1991                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
1992                 body_size = SVAL(hdr, SMB2_HDR_BODY);
1993
1994                 if (next_command_ofs != 0) {
1995                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
1996                                 /*
1997                                  * this is invalid, just return a zero
1998                                  * body and let the caller deal with the error
1999                                  */
2000                                 invalid = true;
2001                         } else if (next_command_ofs > full_size) {
2002                                 /*
2003                                  * this is invalid, just return a zero
2004                                  * body and let the caller deal with the error
2005                                  */
2006                                 invalid = true;
2007                         } else {
2008                                 full_size = next_command_ofs;
2009                         }
2010                 }
2011
2012                 if (!invalid) {
2013                         if (body_size < 2) {
2014                                 /*
2015                                  * this is invalid, just return a zero
2016                                  * body and let the caller deal with the error
2017                                  */
2018                                 invalid = true;
2019                         }
2020
2021                         if ((body_size % 2) != 0) {
2022                                 body_size -= 1;
2023                         }
2024
2025                         if (body_size > (full_size - SMB2_HDR_BODY)) {
2026                                 /*
2027                                  * this is invalid, just return a zero
2028                                  * body and let the caller deal with the error
2029                                  */
2030                                 invalid = true;
2031                         }
2032                 }
2033
2034                 if (invalid) {
2035                         /* the caller should check this */
2036                         body_size = 2;
2037                 }
2038
2039                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2040
2041                 state->missing -= (body_size - 2) + dyn_size;
2042
2043                 body = talloc_array(req->in.vector, uint8_t, body_size);
2044                 if (body == NULL) {
2045                         return -1;
2046                 }
2047
2048                 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2049                 if (dyn == NULL) {
2050                         return -1;
2051                 }
2052
2053                 req->in.vector[idx].iov_base    = (void *)body;
2054                 req->in.vector[idx].iov_len     = body_size;
2055                 req->in.vector[idx+1].iov_base  = (void *)dyn;
2056                 req->in.vector[idx+1].iov_len   = dyn_size;
2057
2058                 vector = talloc_array(mem_ctx, struct iovec, 2);
2059                 if (vector == NULL) {
2060                         return -1;
2061                 }
2062
2063                 /*
2064                  * the first 2 bytes of the body were already fetched
2065                  * together with the header
2066                  */
2067                 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2068                 vector[0].iov_base = body + 2;
2069                 vector[0].iov_len = body_size - 2;
2070
2071                 vector[1] = req->in.vector[idx+1];
2072
2073                 *_vector = vector;
2074                 *_count = 2;
2075                 return 0;
2076         }
2077
2078         /*
2079          * when we endup here, we're looking for a new SMB2 request
2080          * next. And we ask for its header and the first 2 bytes of
2081          * the body (like we did for the first SMB2 request).
2082          */
2083
2084         req->in.vector = talloc_realloc(req, req->in.vector,
2085                                         struct iovec,
2086                                         req->in.vector_count + 1);
2087         if (req->in.vector == NULL) {
2088                 return -1;
2089         }
2090         req->in.vector_count += 1;
2091
2092         /*
2093          * We assume it's a SMB2 request,
2094          * and we first get the header and the
2095          * first 2 bytes (the struct size) of the body
2096          */
2097         len = SMB2_HDR_BODY + 2;
2098
2099         if (len > state->missing) {
2100                 /* let the caller handle the error */
2101                 len = state->missing;
2102         }
2103
2104         state->missing -= len;
2105         state->asked_for_header = true;
2106
2107         buf = talloc_array(req->in.vector, uint8_t, len);
2108         if (buf == NULL) {
2109                 return -1;
2110         }
2111
2112         req->in.vector[idx].iov_base    = (void *)buf;
2113         req->in.vector[idx].iov_len     = len;
2114
2115         vector = talloc_array(mem_ctx, struct iovec, 1);
2116         if (vector == NULL) {
2117                 return -1;
2118         }
2119
2120         vector[0] = req->in.vector[idx];
2121
2122         *_vector = vector;
2123         *_count = 1;
2124         return 0;
2125 }
2126
2127 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2128 {
2129         struct tevent_req *req =
2130                 tevent_req_callback_data(subreq,
2131                 struct tevent_req);
2132         int ret;
2133         int sys_errno;
2134         NTSTATUS status;
2135
2136         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2137         if (ret == -1) {
2138                 status = map_nt_error_from_unix(sys_errno);
2139                 tevent_req_nterror(req, status);
2140                 return;
2141         }
2142
2143         tevent_req_done(req);
2144 }
2145
2146 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2147                                             TALLOC_CTX *mem_ctx,
2148                                             struct smbd_smb2_request **_smb2_req)
2149 {
2150         struct smbd_smb2_request_read_state *state =
2151                 tevent_req_data(req,
2152                 struct smbd_smb2_request_read_state);
2153         NTSTATUS status;
2154
2155         if (tevent_req_is_nterror(req, &status)) {
2156                 tevent_req_received(req);
2157                 return status;
2158         }
2159
2160         talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2161         *_smb2_req = state->smb2_req;
2162         tevent_req_received(req);
2163         return NT_STATUS_OK;
2164 }
2165
2166 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2167
2168 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2169                              const uint8_t *inbuf, size_t size)
2170 {
2171         NTSTATUS status;
2172         struct smbd_smb2_request *req = NULL;
2173         struct tevent_req *subreq;
2174
2175         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2176                  (unsigned int)size));
2177
2178         status = smbd_initialize_smb2(sconn);
2179         if (!NT_STATUS_IS_OK(status)) {
2180                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2181                 return;
2182         }
2183
2184         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2185         if (!NT_STATUS_IS_OK(status)) {
2186                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2187                 return;
2188         }
2189
2190         status = smbd_smb2_request_setup_out(req);
2191         if (!NT_STATUS_IS_OK(status)) {
2192                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2193                 return;
2194         }
2195
2196         status = smbd_smb2_request_dispatch(req);
2197         if (!NT_STATUS_IS_OK(status)) {
2198                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2199                 return;
2200         }
2201
2202         /* ask for the next request */
2203         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2204         if (subreq == NULL) {
2205                 smbd_server_connection_terminate(sconn, "no memory for reading");
2206                 return;
2207         }
2208         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2209 }
2210
2211 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2212 {
2213         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2214                                                struct smbd_server_connection);
2215         NTSTATUS status;
2216         struct smbd_smb2_request *req = NULL;
2217
2218         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2219         TALLOC_FREE(subreq);
2220         if (!NT_STATUS_IS_OK(status)) {
2221                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2222                         nt_errstr(status)));
2223                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2224                 return;
2225         }
2226
2227         if (req->in.nbt_hdr[0] != 0x00) {
2228                 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2229                          req->in.nbt_hdr[0]));
2230                 TALLOC_FREE(req);
2231                 goto next;
2232         }
2233
2234         req->current_idx = 1;
2235
2236         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2237                  req->current_idx, req->in.vector_count));
2238
2239         status = smbd_smb2_request_validate(req);
2240         if (!NT_STATUS_IS_OK(status)) {
2241                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2242                 return;
2243         }
2244
2245         status = smbd_smb2_request_setup_out(req);
2246         if (!NT_STATUS_IS_OK(status)) {
2247                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2248                 return;
2249         }
2250
2251         status = smbd_smb2_request_dispatch(req);
2252         if (!NT_STATUS_IS_OK(status)) {
2253                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2254                 return;
2255         }
2256
2257 next:
2258         /* ask for the next request (this constructs the main loop) */
2259         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2260         if (subreq == NULL) {
2261                 smbd_server_connection_terminate(sconn, "no memory for reading");
2262                 return;
2263         }
2264         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2265 }