Second part of fix for bug #8219 - SMB Panic from Windows 7 Client.
[metze/samba/wip.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 = server_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->session = req->session;
669         newreq->do_signing = req->do_signing;
670         newreq->current_idx = req->current_idx;
671         newreq->async = false;
672         newreq->cancelled = false;
673         /* Note we are leaving:
674                 ->tcon
675                 ->smb1req
676                 ->compat_chain_fsp
677            uninitialized as NULL here as
678            they're not used in the interim
679            response code. JRA. */
680
681         outvec = talloc_zero_array(newreq, struct iovec, count);
682         if (!outvec) {
683                 TALLOC_FREE(newreq);
684                 return NULL;
685         }
686         newreq->out.vector = outvec;
687         newreq->out.vector_count = count;
688
689         /* Setup the outvec's identically to req. */
690         outvec[0].iov_base = newreq->out.nbt_hdr;
691         outvec[0].iov_len = 4;
692         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
693
694         /* Setup the vectors identically to the ones in req. */
695         for (i = 1; i < count; i += 3) {
696                 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
697                         break;
698                 }
699         }
700
701         if (i < count) {
702                 /* Alloc failed. */
703                 TALLOC_FREE(newreq);
704                 return NULL;
705         }
706
707         smb2_setup_nbt_length(newreq->out.vector,
708                 newreq->out.vector_count);
709
710         return newreq;
711 }
712
713 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
714
715 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
716 {
717         int i = 0;
718         uint8_t *outhdr = NULL;
719         struct smbd_smb2_request *nreq = NULL;
720
721         /* Create a new smb2 request we'll use
722            for the interim return. */
723         nreq = dup_smb2_req(req);
724         if (!nreq) {
725                 return NT_STATUS_NO_MEMORY;
726         }
727
728         /* Lose the last 3 out vectors. They're the
729            ones we'll be using for the async reply. */
730         nreq->out.vector_count -= 3;
731
732         smb2_setup_nbt_length(nreq->out.vector,
733                 nreq->out.vector_count);
734
735         /* Step back to the previous reply. */
736         i = nreq->current_idx - 3;
737         outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
738         /* And end the chain. */
739         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
740
741         /* Calculate outgoing credits */
742         smb2_calculate_credits(req, nreq);
743
744         /* Re-sign if needed. */
745         if (nreq->do_signing) {
746                 NTSTATUS status;
747                 status = smb2_signing_sign_pdu(nreq->session->session_key,
748                                         &nreq->out.vector[i], 3);
749                 if (!NT_STATUS_IS_OK(status)) {
750                         return status;
751                 }
752         }
753         if (DEBUGLEVEL >= 10) {
754                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
755                         (unsigned int)nreq->current_idx );
756                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
757                         (unsigned int)nreq->out.vector_count );
758                 print_req_vectors(nreq);
759         }
760         nreq->subreq = tstream_writev_queue_send(nreq,
761                                         nreq->sconn->smb2.event_ctx,
762                                         nreq->sconn->smb2.stream,
763                                         nreq->sconn->smb2.send_queue,
764                                         nreq->out.vector,
765                                         nreq->out.vector_count);
766
767         if (nreq->subreq == NULL) {
768                 return NT_STATUS_NO_MEMORY;
769         }
770
771         tevent_req_set_callback(nreq->subreq,
772                         smbd_smb2_request_writev_done,
773                         nreq);
774
775         return NT_STATUS_OK;
776 }
777
778 struct smbd_smb2_request_pending_state {
779         struct smbd_server_connection *sconn;
780         uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
781         struct iovec vector[3];
782 };
783
784 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
785 {
786         struct smbd_smb2_request_pending_state *state =
787                 tevent_req_callback_data(subreq,
788                         struct smbd_smb2_request_pending_state);
789         struct smbd_server_connection *sconn = state->sconn;
790         int ret;
791         int sys_errno;
792
793         ret = tstream_writev_queue_recv(subreq, &sys_errno);
794         TALLOC_FREE(subreq);
795         if (ret == -1) {
796                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
797                 smbd_server_connection_terminate(sconn, nt_errstr(status));
798                 return;
799         }
800
801         TALLOC_FREE(state);
802 }
803
804 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
805                                          struct tevent_req *subreq)
806 {
807         NTSTATUS status;
808         struct smbd_smb2_request_pending_state *state = NULL;
809         int i = req->current_idx;
810         uint8_t *reqhdr = NULL;
811         uint8_t *hdr = NULL;
812         uint8_t *body = NULL;
813         uint32_t flags = 0;
814         uint64_t message_id = 0;
815         uint64_t async_id = 0;
816         struct iovec *outvec = NULL;
817
818         if (!tevent_req_is_in_progress(subreq)) {
819                 return NT_STATUS_OK;
820         }
821
822         req->subreq = subreq;
823         subreq = NULL;
824
825         if (req->async) {
826                 /* We're already async. */
827                 return NT_STATUS_OK;
828         }
829
830         if (req->in.vector_count > i + 3) {
831                 /*
832                  * We're trying to go async in a compound
833                  * request chain. This is not allowed.
834                  * Cancel the outstanding request.
835                  */
836                 tevent_req_cancel(req->subreq);
837                 return smbd_smb2_request_error(req,
838                         NT_STATUS_INSUFFICIENT_RESOURCES);
839         }
840
841         if (DEBUGLEVEL >= 10) {
842                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
843                         (unsigned int)req->current_idx );
844                 print_req_vectors(req);
845         }
846
847         if (req->out.vector_count > 4) {
848                 /* This is a compound reply. We
849                  * must do an interim response
850                  * followed by the async response
851                  * to match W2K8R2.
852                  */
853                 status = smb2_send_async_interim_response(req);
854                 if (!NT_STATUS_IS_OK(status)) {
855                         return status;
856                 }
857         }
858
859         /* Don't return an intermediate packet on a pipe read/write. */
860         if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
861                 return NT_STATUS_OK;
862         }
863
864         reqhdr = (uint8_t *)req->out.vector[i].iov_base;
865         flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
866         message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
867         async_id = message_id; /* keep it simple for now... */
868
869         /*
870          * What we send is identical to a smbd_smb2_request_error
871          * packet with an error status of STATUS_PENDING. Make use
872          * of this fact sometime when refactoring. JRA.
873          */
874
875         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
876         if (state == NULL) {
877                 return NT_STATUS_NO_MEMORY;
878         }
879         state->sconn = req->sconn;
880
881         state->vector[0].iov_base = (void *)state->buf;
882         state->vector[0].iov_len = 4;
883
884         state->vector[1].iov_base = state->buf + 4;
885         state->vector[1].iov_len = SMB2_HDR_BODY;
886
887         state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
888         state->vector[2].iov_len = 9;
889
890         smb2_setup_nbt_length(state->vector, 3);
891
892         hdr = (uint8_t *)state->vector[1].iov_base;
893         body = (uint8_t *)state->vector[2].iov_base;
894
895         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
896         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
897         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
898         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
899         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
900
901         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
902         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
903         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
904         SBVAL(hdr, SMB2_HDR_PID, async_id);
905         SBVAL(hdr, SMB2_HDR_SESSION_ID,
906                 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
907         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
908
909         SSVAL(body, 0x00, 0x08 + 1);
910
911         SCVAL(body, 0x02, 0);
912         SCVAL(body, 0x03, 0);
913         SIVAL(body, 0x04, 0);
914         /* Match W2K8R2... */
915         SCVAL(body, 0x08, 0x21);
916
917         /* Ensure we correctly go through crediting. Grant
918            the credits now, and zero credits on the final
919            response. */
920         smb2_set_operation_credit(req->sconn,
921                         &req->in.vector[i],
922                         &state->vector[1]);
923
924         if (req->do_signing) {
925                 status = smb2_signing_sign_pdu(req->session->session_key,
926                                         &state->vector[1], 2);
927                 if (!NT_STATUS_IS_OK(status)) {
928                         return status;
929                 }
930         }
931
932         subreq = tstream_writev_queue_send(state,
933                                         req->sconn->smb2.event_ctx,
934                                         req->sconn->smb2.stream,
935                                         req->sconn->smb2.send_queue,
936                                         state->vector,
937                                         3);
938
939         if (subreq == NULL) {
940                 return NT_STATUS_NO_MEMORY;
941         }
942
943         tevent_req_set_callback(subreq,
944                         smbd_smb2_request_pending_writev_done,
945                         state);
946
947         /* Note we're going async with this request. */
948         req->async = true;
949
950         /*
951          * Now manipulate req so that the outstanding async request
952          * is the only one left in the struct smbd_smb2_request.
953          */
954
955         if (req->current_idx == 1) {
956                 /* There was only one. */
957                 goto out;
958         }
959
960         /* Re-arrange the in.vectors. */
961         req->in.vector[1] = req->in.vector[i];
962         req->in.vector[2] = req->in.vector[i+1];
963         req->in.vector[3] = req->in.vector[i+2];
964         req->in.vector_count = 4;
965         /* Reset the new in size. */
966         smb2_setup_nbt_length(req->in.vector, 4);
967
968         /* Now recreate the out.vectors. */
969         outvec = talloc_zero_array(req, struct iovec, 4);
970         if (!outvec) {
971                 return NT_STATUS_NO_MEMORY;
972         }
973
974         /* 0 is always boilerplate and must
975          * be of size 4 for the length field. */
976
977         outvec[0].iov_base = req->out.nbt_hdr;
978         outvec[0].iov_len = 4;
979         SIVAL(req->out.nbt_hdr, 0, 0);
980
981         if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
982                 return NT_STATUS_NO_MEMORY;
983         }
984
985         TALLOC_FREE(req->out.vector);
986
987         req->out.vector = outvec;
988
989         req->current_idx = 1;
990         req->out.vector_count = 4;
991
992   out:
993
994         smb2_setup_nbt_length(req->out.vector,
995                 req->out.vector_count);
996
997         /* Ensure our final reply matches the interim one. */
998         reqhdr = (uint8_t *)req->out.vector[1].iov_base;
999         SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1000         SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1001
1002         {
1003                 const uint8_t *inhdr =
1004                         (const uint8_t *)req->in.vector[1].iov_base;
1005                 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1006                         "going async\n",
1007                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1008                         (unsigned long long)async_id ));
1009         }
1010         return NT_STATUS_OK;
1011 }
1012
1013 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1014 {
1015         struct smbd_server_connection *sconn = req->sconn;
1016         struct smbd_smb2_request *cur;
1017         const uint8_t *inhdr;
1018         int i = req->current_idx;
1019         uint32_t flags;
1020         uint64_t search_message_id;
1021         uint64_t search_async_id;
1022         uint64_t found_id;
1023
1024         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1025
1026         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1027         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1028         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1029
1030         /*
1031          * we don't need the request anymore
1032          * cancel requests never have a response
1033          */
1034         DLIST_REMOVE(req->sconn->smb2.requests, req);
1035         TALLOC_FREE(req);
1036
1037         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1038                 const uint8_t *outhdr;
1039                 uint64_t message_id;
1040                 uint64_t async_id;
1041
1042                 i = cur->current_idx;
1043
1044                 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1045
1046                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1047                 async_id = BVAL(outhdr, SMB2_HDR_PID);
1048
1049                 if (flags & SMB2_HDR_FLAG_ASYNC) {
1050                         if (search_async_id == async_id) {
1051                                 found_id = async_id;
1052                                 break;
1053                         }
1054                 } else {
1055                         if (search_message_id == message_id) {
1056                                 found_id = message_id;
1057                                 break;
1058                         }
1059                 }
1060         }
1061
1062         if (cur && cur->subreq) {
1063                 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1064                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1065                         "cancel opcode[%s] mid %llu\n",
1066                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1067                         (unsigned long long)found_id ));
1068                 tevent_req_cancel(cur->subreq);
1069         }
1070
1071         return NT_STATUS_OK;
1072 }
1073
1074 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1075 {
1076         const uint8_t *inhdr;
1077         int i = req->current_idx;
1078         uint16_t opcode;
1079         uint32_t flags;
1080         uint64_t mid;
1081         NTSTATUS status;
1082         NTSTATUS session_status;
1083         uint32_t allowed_flags;
1084         NTSTATUS return_value;
1085
1086         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1087
1088         /* TODO: verify more things */
1089
1090         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1091         opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1092         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1093         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1094                 smb2_opcode_name(opcode),
1095                 (unsigned long long)mid));
1096
1097         allowed_flags = SMB2_HDR_FLAG_CHAINED |
1098                         SMB2_HDR_FLAG_SIGNED |
1099                         SMB2_HDR_FLAG_DFS;
1100         if (opcode == SMB2_OP_CANCEL) {
1101                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1102         }
1103         if ((flags & ~allowed_flags) != 0) {
1104                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1105         }
1106
1107         session_status = smbd_smb2_request_check_session(req);
1108
1109         req->do_signing = false;
1110         if (flags & SMB2_HDR_FLAG_SIGNED) {
1111                 if (!NT_STATUS_IS_OK(session_status)) {
1112                         return smbd_smb2_request_error(req, session_status);
1113                 }
1114
1115                 req->do_signing = true;
1116                 status = smb2_signing_check_pdu(req->session->session_key,
1117                                                 &req->in.vector[i], 3);
1118                 if (!NT_STATUS_IS_OK(status)) {
1119                         return smbd_smb2_request_error(req, status);
1120                 }
1121         } else if (req->session && req->session->do_signing) {
1122                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1123         }
1124
1125         if (flags & SMB2_HDR_FLAG_CHAINED) {
1126                 /*
1127                  * This check is mostly for giving the correct error code
1128                  * for compounded requests.
1129                  *
1130                  * TODO: we may need to move this after the session
1131                  *       and tcon checks.
1132                  */
1133                 if (!NT_STATUS_IS_OK(req->next_status)) {
1134                         return smbd_smb2_request_error(req, req->next_status);
1135                 }
1136         } else {
1137                 req->compat_chain_fsp = NULL;
1138         }
1139
1140         switch (opcode) {
1141         case SMB2_OP_NEGPROT:
1142                 {
1143                         START_PROFILE(smb2_negprot);
1144                         return_value = smbd_smb2_request_process_negprot(req);
1145                         END_PROFILE(smb2_negprot);
1146                 }
1147                 break;
1148
1149         case SMB2_OP_SESSSETUP:
1150                 {
1151                         START_PROFILE(smb2_sesssetup);
1152                         return_value = smbd_smb2_request_process_sesssetup(req);
1153                         END_PROFILE(smb2_sesssetup);
1154                 }
1155                 break;
1156
1157         case SMB2_OP_LOGOFF:
1158                 if (!NT_STATUS_IS_OK(session_status)) {
1159                         return_value = smbd_smb2_request_error(req, session_status);
1160                         break;
1161                 }
1162
1163                 {
1164                         START_PROFILE(smb2_logoff);
1165                         return_value = smbd_smb2_request_process_logoff(req);
1166                         END_PROFILE(smb2_logoff);
1167                 }
1168                 break;
1169
1170         case SMB2_OP_TCON:
1171                 if (!NT_STATUS_IS_OK(session_status)) {
1172                         return_value = smbd_smb2_request_error(req, session_status);
1173                         break;
1174                 }
1175                 status = smbd_smb2_request_check_session(req);
1176                 if (!NT_STATUS_IS_OK(status)) {
1177                         return_value = smbd_smb2_request_error(req, status);
1178                         break;
1179                 }
1180
1181                 {
1182                         START_PROFILE(smb2_tcon);
1183                         return_value = smbd_smb2_request_process_tcon(req);
1184                         END_PROFILE(smb2_tcon);
1185                 }
1186                 break;
1187
1188         case SMB2_OP_TDIS:
1189                 if (!NT_STATUS_IS_OK(session_status)) {
1190                         return_value = smbd_smb2_request_error(req, session_status);
1191                         break;
1192                 }
1193                 status = smbd_smb2_request_check_tcon(req);
1194                 if (!NT_STATUS_IS_OK(status)) {
1195                         return_value = smbd_smb2_request_error(req, status);
1196                         break;
1197                 }
1198
1199                 {
1200                         START_PROFILE(smb2_tdis);
1201                         return_value = smbd_smb2_request_process_tdis(req);
1202                         END_PROFILE(smb2_tdis);
1203                 }
1204                 break;
1205
1206         case SMB2_OP_CREATE:
1207                 if (!NT_STATUS_IS_OK(session_status)) {
1208                         return_value = smbd_smb2_request_error(req, session_status);
1209                         break;
1210                 }
1211                 status = smbd_smb2_request_check_tcon(req);
1212                 if (!NT_STATUS_IS_OK(status)) {
1213                         return_value = smbd_smb2_request_error(req, status);
1214                         break;
1215                 }
1216
1217                 {
1218                         START_PROFILE(smb2_create);
1219                         return_value = smbd_smb2_request_process_create(req);
1220                         END_PROFILE(smb2_create);
1221                 }
1222                 break;
1223
1224         case SMB2_OP_CLOSE:
1225                 if (!NT_STATUS_IS_OK(session_status)) {
1226                         return_value = smbd_smb2_request_error(req, session_status);
1227                         break;
1228                 }
1229                 status = smbd_smb2_request_check_tcon(req);
1230                 if (!NT_STATUS_IS_OK(status)) {
1231                         return_value = smbd_smb2_request_error(req, status);
1232                         break;
1233                 }
1234
1235                 {
1236                         START_PROFILE(smb2_close);
1237                         return_value = smbd_smb2_request_process_close(req);
1238                         END_PROFILE(smb2_close);
1239                 }
1240                 break;
1241
1242         case SMB2_OP_FLUSH:
1243                 if (!NT_STATUS_IS_OK(session_status)) {
1244                         return_value = smbd_smb2_request_error(req, session_status);
1245                         break;
1246                 }
1247                 status = smbd_smb2_request_check_tcon(req);
1248                 if (!NT_STATUS_IS_OK(status)) {
1249                         return_value = smbd_smb2_request_error(req, status);
1250                         break;
1251                 }
1252
1253                 {
1254                         START_PROFILE(smb2_flush);
1255                         return_value = smbd_smb2_request_process_flush(req);
1256                         END_PROFILE(smb2_flush);
1257                 }
1258                 break;
1259
1260         case SMB2_OP_READ:
1261                 if (!NT_STATUS_IS_OK(session_status)) {
1262                         return_value = smbd_smb2_request_error(req, session_status);
1263                         break;
1264                 }
1265                 status = smbd_smb2_request_check_tcon(req);
1266                 if (!NT_STATUS_IS_OK(status)) {
1267                         return_value = smbd_smb2_request_error(req, status);
1268                         break;
1269                 }
1270
1271                 {
1272                         START_PROFILE(smb2_read);
1273                         return_value = smbd_smb2_request_process_read(req);
1274                         END_PROFILE(smb2_read);
1275                 }
1276                 break;
1277
1278         case SMB2_OP_WRITE:
1279                 if (!NT_STATUS_IS_OK(session_status)) {
1280                         return_value = smbd_smb2_request_error(req, session_status);
1281                         break;
1282                 }
1283                 status = smbd_smb2_request_check_tcon(req);
1284                 if (!NT_STATUS_IS_OK(status)) {
1285                         return_value = smbd_smb2_request_error(req, status);
1286                         break;
1287                 }
1288
1289                 {
1290                         START_PROFILE(smb2_write);
1291                         return_value = smbd_smb2_request_process_write(req);
1292                         END_PROFILE(smb2_write);
1293                 }
1294                 break;
1295
1296         case SMB2_OP_LOCK:
1297                 if (!NT_STATUS_IS_OK(session_status)) {
1298                         /* Too ugly to live ? JRA. */
1299                         if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1300                                 session_status = NT_STATUS_FILE_CLOSED;
1301                         }
1302                         return_value = smbd_smb2_request_error(req, session_status);
1303                         break;
1304                 }
1305                 status = smbd_smb2_request_check_tcon(req);
1306                 if (!NT_STATUS_IS_OK(status)) {
1307                         /* Too ugly to live ? JRA. */
1308                         if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1309                                 status = NT_STATUS_FILE_CLOSED;
1310                         }
1311                         return_value = smbd_smb2_request_error(req, status);
1312                         break;
1313                 }
1314
1315                 {
1316                         START_PROFILE(smb2_lock);
1317                         return_value = smbd_smb2_request_process_lock(req);
1318                         END_PROFILE(smb2_lock);
1319                 }
1320                 break;
1321
1322         case SMB2_OP_IOCTL:
1323                 if (!NT_STATUS_IS_OK(session_status)) {
1324                         return_value = smbd_smb2_request_error(req, session_status);
1325                         break;
1326                 }
1327                 status = smbd_smb2_request_check_tcon(req);
1328                 if (!NT_STATUS_IS_OK(status)) {
1329                         return_value = smbd_smb2_request_error(req, status);
1330                         break;
1331                 }
1332
1333                 {
1334                         START_PROFILE(smb2_ioctl);
1335                         return_value = smbd_smb2_request_process_ioctl(req);
1336                         END_PROFILE(smb2_ioctl);
1337                 }
1338                 break;
1339
1340         case SMB2_OP_CANCEL:
1341                 {
1342                         START_PROFILE(smb2_cancel);
1343                         return_value = smbd_smb2_request_process_cancel(req);
1344                         END_PROFILE(smb2_cancel);
1345                 }
1346                 break;
1347
1348         case SMB2_OP_KEEPALIVE:
1349                 {START_PROFILE(smb2_keepalive);
1350                 return_value = smbd_smb2_request_process_keepalive(req);
1351                 END_PROFILE(smb2_keepalive);}
1352                 break;
1353
1354         case SMB2_OP_FIND:
1355                 if (!NT_STATUS_IS_OK(session_status)) {
1356                         return_value = smbd_smb2_request_error(req, session_status);
1357                         break;
1358                 }
1359                 status = smbd_smb2_request_check_tcon(req);
1360                 if (!NT_STATUS_IS_OK(status)) {
1361                         return_value = smbd_smb2_request_error(req, status);
1362                         break;
1363                 }
1364
1365                 {
1366                         START_PROFILE(smb2_find);
1367                         return_value = smbd_smb2_request_process_find(req);
1368                         END_PROFILE(smb2_find);
1369                 }
1370                 break;
1371
1372         case SMB2_OP_NOTIFY:
1373                 if (!NT_STATUS_IS_OK(session_status)) {
1374                         return_value = smbd_smb2_request_error(req, session_status);
1375                         break;
1376                 }
1377                 status = smbd_smb2_request_check_tcon(req);
1378                 if (!NT_STATUS_IS_OK(status)) {
1379                         return_value = smbd_smb2_request_error(req, status);
1380                         break;
1381                 }
1382
1383                 {
1384                         START_PROFILE(smb2_notify);
1385                         return_value = smbd_smb2_request_process_notify(req);
1386                         END_PROFILE(smb2_notify);
1387                 }
1388                 break;
1389
1390         case SMB2_OP_GETINFO:
1391                 if (!NT_STATUS_IS_OK(session_status)) {
1392                         return_value = smbd_smb2_request_error(req, session_status);
1393                         break;
1394                 }
1395                 status = smbd_smb2_request_check_tcon(req);
1396                 if (!NT_STATUS_IS_OK(status)) {
1397                         return_value = smbd_smb2_request_error(req, status);
1398                         break;
1399                 }
1400
1401                 {
1402                         START_PROFILE(smb2_getinfo);
1403                         return_value = smbd_smb2_request_process_getinfo(req);
1404                         END_PROFILE(smb2_getinfo);
1405                 }
1406                 break;
1407
1408         case SMB2_OP_SETINFO:
1409                 if (!NT_STATUS_IS_OK(session_status)) {
1410                         return_value = smbd_smb2_request_error(req, session_status);
1411                         break;
1412                 }
1413                 status = smbd_smb2_request_check_tcon(req);
1414                 if (!NT_STATUS_IS_OK(status)) {
1415                         return_value = smbd_smb2_request_error(req, status);
1416                         break;
1417                 }
1418
1419                 {
1420                         START_PROFILE(smb2_setinfo);
1421                         return_value = smbd_smb2_request_process_setinfo(req);
1422                         END_PROFILE(smb2_setinfo);
1423                 }
1424                 break;
1425
1426         case SMB2_OP_BREAK:
1427                 if (!NT_STATUS_IS_OK(session_status)) {
1428                         return_value = smbd_smb2_request_error(req, session_status);
1429                         break;
1430                 }
1431                 status = smbd_smb2_request_check_tcon(req);
1432                 if (!NT_STATUS_IS_OK(status)) {
1433                         return_value = smbd_smb2_request_error(req, status);
1434                         break;
1435                 }
1436
1437                 {
1438                         START_PROFILE(smb2_break);
1439                         return_value = smbd_smb2_request_process_break(req);
1440                         END_PROFILE(smb2_break);
1441                 }
1442                 break;
1443
1444         default:
1445                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1446                 break;
1447         }
1448         return return_value;
1449 }
1450
1451 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1452 {
1453         struct tevent_req *subreq;
1454         int i = req->current_idx;
1455
1456         req->subreq = NULL;
1457
1458         req->current_idx += 3;
1459
1460         if (req->current_idx < req->out.vector_count) {
1461                 /*
1462                  * We must process the remaining compound
1463                  * SMB2 requests before any new incoming SMB2
1464                  * requests. This is because incoming SMB2
1465                  * requests may include a cancel for a
1466                  * compound request we haven't processed
1467                  * yet.
1468                  */
1469                 struct tevent_immediate *im = tevent_create_immediate(req);
1470                 if (!im) {
1471                         return NT_STATUS_NO_MEMORY;
1472                 }
1473                 tevent_schedule_immediate(im,
1474                                         req->sconn->smb2.event_ctx,
1475                                         smbd_smb2_request_dispatch_immediate,
1476                                         req);
1477                 return NT_STATUS_OK;
1478         }
1479
1480         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1481
1482         /* Set credit for this operation (zero credits if this
1483            is a final reply for an async operation). */
1484         smb2_set_operation_credit(req->sconn,
1485                         req->async ? NULL : &req->in.vector[i],
1486                         &req->out.vector[i]);
1487
1488         if (req->do_signing) {
1489                 NTSTATUS status;
1490                 status = smb2_signing_sign_pdu(req->session->session_key,
1491                                                &req->out.vector[i], 3);
1492                 if (!NT_STATUS_IS_OK(status)) {
1493                         return status;
1494                 }
1495         }
1496
1497         if (DEBUGLEVEL >= 10) {
1498                 dbgtext("smbd_smb2_request_reply: sending...\n");
1499                 print_req_vectors(req);
1500         }
1501
1502         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1503         if (req->out.vector_count == 4 &&
1504                         req->out.vector[3].iov_base == NULL &&
1505                         req->out.vector[3].iov_len != 0) {
1506                 /* Dynamic part is NULL. Chop it off,
1507                    We're going to send it via sendfile. */
1508                 req->out.vector_count -= 1;
1509         }
1510
1511         subreq = tstream_writev_queue_send(req,
1512                                            req->sconn->smb2.event_ctx,
1513                                            req->sconn->smb2.stream,
1514                                            req->sconn->smb2.send_queue,
1515                                            req->out.vector,
1516                                            req->out.vector_count);
1517         if (subreq == NULL) {
1518                 return NT_STATUS_NO_MEMORY;
1519         }
1520         tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1521         /*
1522          * We're done with this request -
1523          * move it off the "being processed" queue.
1524          */
1525         DLIST_REMOVE(req->sconn->smb2.requests, req);
1526
1527         return NT_STATUS_OK;
1528 }
1529
1530 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1531                                         struct tevent_immediate *im,
1532                                         void *private_data)
1533 {
1534         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1535                                         struct smbd_smb2_request);
1536         struct smbd_server_connection *sconn = req->sconn;
1537         NTSTATUS status;
1538
1539         TALLOC_FREE(im);
1540
1541         if (DEBUGLEVEL >= 10) {
1542                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1543                         req->current_idx, req->in.vector_count));
1544                 print_req_vectors(req);
1545         }
1546
1547         status = smbd_smb2_request_dispatch(req);
1548         if (!NT_STATUS_IS_OK(status)) {
1549                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1550                 return;
1551         }
1552 }
1553
1554 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1555 {
1556         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1557                                         struct smbd_smb2_request);
1558         struct smbd_server_connection *sconn = req->sconn;
1559         int ret;
1560         int sys_errno;
1561
1562         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1563         TALLOC_FREE(subreq);
1564         TALLOC_FREE(req);
1565         if (ret == -1) {
1566                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1567                 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1568                         nt_errstr(status)));
1569                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1570                 return;
1571         }
1572 }
1573
1574 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1575                                    NTSTATUS status,
1576                                    DATA_BLOB body, DATA_BLOB *dyn,
1577                                    const char *location)
1578 {
1579         uint8_t *outhdr;
1580         int i = req->current_idx;
1581         uint32_t next_command_ofs;
1582
1583         DEBUG(10,("smbd_smb2_request_done_ex: "
1584                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1585                   i, nt_errstr(status), (unsigned int)body.length,
1586                   dyn ? "yes": "no",
1587                   (unsigned int)(dyn ? dyn->length : 0),
1588                   location));
1589
1590         if (body.length < 2) {
1591                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1592         }
1593
1594         if ((body.length % 2) != 0) {
1595                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1596         }
1597
1598         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1599
1600         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1601         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1602
1603         req->out.vector[i+1].iov_base = (void *)body.data;
1604         req->out.vector[i+1].iov_len = body.length;
1605
1606         if (dyn) {
1607                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
1608                 req->out.vector[i+2].iov_len    = dyn->length;
1609         } else {
1610                 req->out.vector[i+2].iov_base = NULL;
1611                 req->out.vector[i+2].iov_len = 0;
1612         }
1613
1614         /* see if we need to recalculate the offset to the next response */
1615         if (next_command_ofs > 0) {
1616                 next_command_ofs  = SMB2_HDR_BODY;
1617                 next_command_ofs += req->out.vector[i+1].iov_len;
1618                 next_command_ofs += req->out.vector[i+2].iov_len;
1619         }
1620
1621         if ((next_command_ofs % 8) != 0) {
1622                 size_t pad_size = 8 - (next_command_ofs % 8);
1623                 if (req->out.vector[i+2].iov_len == 0) {
1624                         /*
1625                          * if the dyn buffer is empty
1626                          * we can use it to add padding
1627                          */
1628                         uint8_t *pad;
1629
1630                         pad = talloc_zero_array(req->out.vector,
1631                                                 uint8_t, pad_size);
1632                         if (pad == NULL) {
1633                                 return smbd_smb2_request_error(req,
1634                                                 NT_STATUS_NO_MEMORY);
1635                         }
1636
1637                         req->out.vector[i+2].iov_base = (void *)pad;
1638                         req->out.vector[i+2].iov_len = pad_size;
1639                 } else {
1640                         /*
1641                          * For now we copy the dynamic buffer
1642                          * and add the padding to the new buffer
1643                          */
1644                         size_t old_size;
1645                         uint8_t *old_dyn;
1646                         size_t new_size;
1647                         uint8_t *new_dyn;
1648
1649                         old_size = req->out.vector[i+2].iov_len;
1650                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
1651
1652                         new_size = old_size + pad_size;
1653                         new_dyn = talloc_zero_array(req->out.vector,
1654                                                uint8_t, new_size);
1655                         if (new_dyn == NULL) {
1656                                 return smbd_smb2_request_error(req,
1657                                                 NT_STATUS_NO_MEMORY);
1658                         }
1659
1660                         memcpy(new_dyn, old_dyn, old_size);
1661                         memset(new_dyn + old_size, 0, pad_size);
1662
1663                         req->out.vector[i+2].iov_base = (void *)new_dyn;
1664                         req->out.vector[i+2].iov_len = new_size;
1665                 }
1666                 next_command_ofs += pad_size;
1667         }
1668
1669         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1670
1671         return smbd_smb2_request_reply(req);
1672 }
1673
1674 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
1675                                     NTSTATUS status,
1676                                     DATA_BLOB *info,
1677                                     const char *location)
1678 {
1679         DATA_BLOB body;
1680         int i = req->current_idx;
1681         uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
1682
1683         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
1684                   i, nt_errstr(status), info ? " +info" : "",
1685                   location));
1686
1687         body.data = outhdr + SMB2_HDR_BODY;
1688         body.length = 8;
1689         SSVAL(body.data, 0, 9);
1690
1691         if (info) {
1692                 SIVAL(body.data, 0x04, info->length);
1693         } else {
1694                 /* Allocated size of req->out.vector[i].iov_base
1695                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
1696                  * 1 byte without having to do an alloc.
1697                  */
1698                 info = talloc_zero_array(req->out.vector,
1699                                         DATA_BLOB,
1700                                         1);
1701                 if (!info) {
1702                         return NT_STATUS_NO_MEMORY;
1703                 }
1704                 info->data = ((uint8_t *)outhdr) +
1705                         OUTVEC_ALLOC_SIZE - 1;
1706                 info->length = 1;
1707                 SCVAL(info->data, 0, 0);
1708         }
1709
1710         /*
1711          * if a request fails, all other remaining
1712          * compounded requests should fail too
1713          */
1714         req->next_status = NT_STATUS_INVALID_PARAMETER;
1715
1716         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
1717 }
1718
1719
1720 struct smbd_smb2_send_oplock_break_state {
1721         struct smbd_server_connection *sconn;
1722         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
1723         struct iovec vector;
1724 };
1725
1726 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
1727
1728 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
1729                                      uint64_t file_id_persistent,
1730                                      uint64_t file_id_volatile,
1731                                      uint8_t oplock_level)
1732 {
1733         struct smbd_smb2_send_oplock_break_state *state;
1734         struct tevent_req *subreq;
1735         uint8_t *hdr;
1736         uint8_t *body;
1737
1738         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
1739         if (state == NULL) {
1740                 return NT_STATUS_NO_MEMORY;
1741         }
1742         state->sconn = sconn;
1743
1744         state->vector.iov_base = (void *)state->buf;
1745         state->vector.iov_len = sizeof(state->buf);
1746
1747         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
1748         hdr = state->buf + 4;
1749         body = hdr + SMB2_HDR_BODY;
1750
1751         SIVAL(hdr, 0,                           SMB2_MAGIC);
1752         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
1753         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
1754         SIVAL(hdr, SMB2_HDR_STATUS,             0);
1755         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
1756         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
1757         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
1758         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
1759         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
1760         SIVAL(hdr, SMB2_HDR_PID,                0);
1761         SIVAL(hdr, SMB2_HDR_TID,                0);
1762         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
1763         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
1764
1765         SSVAL(body, 0x00, 0x18);
1766
1767         SCVAL(body, 0x02, oplock_level);
1768         SCVAL(body, 0x03, 0);           /* reserved */
1769         SIVAL(body, 0x04, 0);           /* reserved */
1770         SBVAL(body, 0x08, file_id_persistent);
1771         SBVAL(body, 0x10, file_id_volatile);
1772
1773         subreq = tstream_writev_queue_send(state,
1774                                            sconn->smb2.event_ctx,
1775                                            sconn->smb2.stream,
1776                                            sconn->smb2.send_queue,
1777                                            &state->vector, 1);
1778         if (subreq == NULL) {
1779                 return NT_STATUS_NO_MEMORY;
1780         }
1781         tevent_req_set_callback(subreq,
1782                                 smbd_smb2_oplock_break_writev_done,
1783                                 state);
1784
1785         return NT_STATUS_OK;
1786 }
1787
1788 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
1789 {
1790         struct smbd_smb2_send_oplock_break_state *state =
1791                 tevent_req_callback_data(subreq,
1792                 struct smbd_smb2_send_oplock_break_state);
1793         struct smbd_server_connection *sconn = state->sconn;
1794         int ret;
1795         int sys_errno;
1796
1797         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1798         TALLOC_FREE(subreq);
1799         if (ret == -1) {
1800                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1801                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1802                 return;
1803         }
1804
1805         TALLOC_FREE(state);
1806 }
1807
1808 struct smbd_smb2_request_read_state {
1809         size_t missing;
1810         bool asked_for_header;
1811         struct smbd_smb2_request *smb2_req;
1812 };
1813
1814 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1815                                          void *private_data,
1816                                          TALLOC_CTX *mem_ctx,
1817                                          struct iovec **_vector,
1818                                          size_t *_count);
1819 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
1820
1821 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
1822                                         struct tevent_context *ev,
1823                                         struct smbd_server_connection *sconn)
1824 {
1825         struct tevent_req *req;
1826         struct smbd_smb2_request_read_state *state;
1827         struct tevent_req *subreq;
1828
1829         req = tevent_req_create(mem_ctx, &state,
1830                                 struct smbd_smb2_request_read_state);
1831         if (req == NULL) {
1832                 return NULL;
1833         }
1834         state->missing = 0;
1835         state->asked_for_header = false;
1836
1837         state->smb2_req = smbd_smb2_request_allocate(state);
1838         if (tevent_req_nomem(state->smb2_req, req)) {
1839                 return tevent_req_post(req, ev);
1840         }
1841         state->smb2_req->sconn = sconn;
1842
1843         subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
1844                                               sconn->smb2.recv_queue,
1845                                               smbd_smb2_request_next_vector,
1846                                               state);
1847         if (tevent_req_nomem(subreq, req)) {
1848                 return tevent_req_post(req, ev);
1849         }
1850         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
1851
1852         return req;
1853 }
1854
1855 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
1856                                          void *private_data,
1857                                          TALLOC_CTX *mem_ctx,
1858                                          struct iovec **_vector,
1859                                          size_t *_count)
1860 {
1861         struct smbd_smb2_request_read_state *state =
1862                 talloc_get_type_abort(private_data,
1863                 struct smbd_smb2_request_read_state);
1864         struct smbd_smb2_request *req = state->smb2_req;
1865         struct iovec *vector;
1866         int idx = req->in.vector_count;
1867         size_t len = 0;
1868         uint8_t *buf = NULL;
1869
1870         if (req->in.vector_count == 0) {
1871                 /*
1872                  * first we need to get the NBT header
1873                  */
1874                 req->in.vector = talloc_array(req, struct iovec,
1875                                               req->in.vector_count + 1);
1876                 if (req->in.vector == NULL) {
1877                         return -1;
1878                 }
1879                 req->in.vector_count += 1;
1880
1881                 req->in.vector[idx].iov_base    = (void *)req->in.nbt_hdr;
1882                 req->in.vector[idx].iov_len     = 4;
1883
1884                 vector = talloc_array(mem_ctx, struct iovec, 1);
1885                 if (vector == NULL) {
1886                         return -1;
1887                 }
1888
1889                 vector[0] = req->in.vector[idx];
1890
1891                 *_vector = vector;
1892                 *_count = 1;
1893                 return 0;
1894         }
1895
1896         if (req->in.vector_count == 1) {
1897                 /*
1898                  * Now we analyze the NBT header
1899                  */
1900                 state->missing = smb2_len(req->in.vector[0].iov_base);
1901
1902                 if (state->missing == 0) {
1903                         /* if there're no remaining bytes, we're done */
1904                         *_vector = NULL;
1905                         *_count = 0;
1906                         return 0;
1907                 }
1908
1909                 req->in.vector = talloc_realloc(req, req->in.vector,
1910                                                 struct iovec,
1911                                                 req->in.vector_count + 1);
1912                 if (req->in.vector == NULL) {
1913                         return -1;
1914                 }
1915                 req->in.vector_count += 1;
1916
1917                 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
1918                         /*
1919                          * it's a special NBT message,
1920                          * so get all remaining bytes
1921                          */
1922                         len = state->missing;
1923                 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
1924                         /*
1925                          * it's an invalid message, just read what we can get
1926                          * and let the caller handle the error
1927                          */
1928                         len = state->missing;
1929                 } else {
1930                         /*
1931                          * We assume it's a SMB2 request,
1932                          * and we first get the header and the
1933                          * first 2 bytes (the struct size) of the body
1934                          */
1935                         len = SMB2_HDR_BODY + 2;
1936
1937                         state->asked_for_header = true;
1938                 }
1939
1940                 state->missing -= len;
1941
1942                 buf = talloc_array(req->in.vector, uint8_t, len);
1943                 if (buf == NULL) {
1944                         return -1;
1945                 }
1946
1947                 req->in.vector[idx].iov_base    = (void *)buf;
1948                 req->in.vector[idx].iov_len     = len;
1949
1950                 vector = talloc_array(mem_ctx, struct iovec, 1);
1951                 if (vector == NULL) {
1952                         return -1;
1953                 }
1954
1955                 vector[0] = req->in.vector[idx];
1956
1957                 *_vector = vector;
1958                 *_count = 1;
1959                 return 0;
1960         }
1961
1962         if (state->missing == 0) {
1963                 /* if there're no remaining bytes, we're done */
1964                 *_vector = NULL;
1965                 *_count = 0;
1966                 return 0;
1967         }
1968
1969         if (state->asked_for_header) {
1970                 const uint8_t *hdr;
1971                 size_t full_size;
1972                 size_t next_command_ofs;
1973                 size_t body_size;
1974                 uint8_t *body;
1975                 size_t dyn_size;
1976                 uint8_t *dyn;
1977                 bool invalid = false;
1978
1979                 state->asked_for_header = false;
1980
1981                 /*
1982                  * We got the SMB2 header and the first 2 bytes
1983                  * of the body. We fix the size to just the header
1984                  * and manually copy the 2 first bytes to the body section
1985                  */
1986                 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
1987                 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
1988
1989                 /* allocate vectors for body and dynamic areas */
1990                 req->in.vector = talloc_realloc(req, req->in.vector,
1991                                                 struct iovec,
1992                                                 req->in.vector_count + 2);
1993                 if (req->in.vector == NULL) {
1994                         return -1;
1995                 }
1996                 req->in.vector_count += 2;
1997
1998                 full_size = state->missing + SMB2_HDR_BODY + 2;
1999                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2000                 body_size = SVAL(hdr, SMB2_HDR_BODY);
2001
2002                 if (next_command_ofs != 0) {
2003                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2004                                 /*
2005                                  * this is invalid, just return a zero
2006                                  * body and let the caller deal with the error
2007                                  */
2008                                 invalid = true;
2009                         } else if (next_command_ofs > full_size) {
2010                                 /*
2011                                  * this is invalid, just return a zero
2012                                  * body and let the caller deal with the error
2013                                  */
2014                                 invalid = true;
2015                         } else {
2016                                 full_size = next_command_ofs;
2017                         }
2018                 }
2019
2020                 if (!invalid) {
2021                         if (body_size < 2) {
2022                                 /*
2023                                  * this is invalid, just return a zero
2024                                  * body and let the caller deal with the error
2025                                  */
2026                                 invalid = true;
2027                         }
2028
2029                         /*
2030                          * Mask out the lowest bit, the "dynamic" part
2031                          * of body_size.
2032                          */
2033                         body_size &= ~1;
2034
2035                         if (body_size > (full_size - SMB2_HDR_BODY)) {
2036                                 /*
2037                                  * this is invalid, just return a zero
2038                                  * body and let the caller deal with the error
2039                                  */
2040                                 invalid = true;
2041                         }
2042                 }
2043
2044                 if (invalid) {
2045                         /* the caller should check this */
2046                         body_size = 2;
2047                 }
2048
2049                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2050
2051                 state->missing -= (body_size - 2) + dyn_size;
2052
2053                 body = talloc_array(req->in.vector, uint8_t, body_size);
2054                 if (body == NULL) {
2055                         return -1;
2056                 }
2057
2058                 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2059                 if (dyn == NULL) {
2060                         return -1;
2061                 }
2062
2063                 req->in.vector[idx].iov_base    = (void *)body;
2064                 req->in.vector[idx].iov_len     = body_size;
2065                 req->in.vector[idx+1].iov_base  = (void *)dyn;
2066                 req->in.vector[idx+1].iov_len   = dyn_size;
2067
2068                 vector = talloc_array(mem_ctx, struct iovec, 2);
2069                 if (vector == NULL) {
2070                         return -1;
2071                 }
2072
2073                 /*
2074                  * the first 2 bytes of the body were already fetched
2075                  * together with the header
2076                  */
2077                 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2078                 vector[0].iov_base = body + 2;
2079                 vector[0].iov_len = body_size - 2;
2080
2081                 vector[1] = req->in.vector[idx+1];
2082
2083                 *_vector = vector;
2084                 *_count = 2;
2085                 return 0;
2086         }
2087
2088         /*
2089          * when we endup here, we're looking for a new SMB2 request
2090          * next. And we ask for its header and the first 2 bytes of
2091          * the body (like we did for the first SMB2 request).
2092          */
2093
2094         req->in.vector = talloc_realloc(req, req->in.vector,
2095                                         struct iovec,
2096                                         req->in.vector_count + 1);
2097         if (req->in.vector == NULL) {
2098                 return -1;
2099         }
2100         req->in.vector_count += 1;
2101
2102         /*
2103          * We assume it's a SMB2 request,
2104          * and we first get the header and the
2105          * first 2 bytes (the struct size) of the body
2106          */
2107         len = SMB2_HDR_BODY + 2;
2108
2109         if (len > state->missing) {
2110                 /* let the caller handle the error */
2111                 len = state->missing;
2112         }
2113
2114         state->missing -= len;
2115         state->asked_for_header = true;
2116
2117         buf = talloc_array(req->in.vector, uint8_t, len);
2118         if (buf == NULL) {
2119                 return -1;
2120         }
2121
2122         req->in.vector[idx].iov_base    = (void *)buf;
2123         req->in.vector[idx].iov_len     = len;
2124
2125         vector = talloc_array(mem_ctx, struct iovec, 1);
2126         if (vector == NULL) {
2127                 return -1;
2128         }
2129
2130         vector[0] = req->in.vector[idx];
2131
2132         *_vector = vector;
2133         *_count = 1;
2134         return 0;
2135 }
2136
2137 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2138 {
2139         struct tevent_req *req =
2140                 tevent_req_callback_data(subreq,
2141                 struct tevent_req);
2142         int ret;
2143         int sys_errno;
2144         NTSTATUS status;
2145
2146         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2147         if (ret == -1) {
2148                 status = map_nt_error_from_unix(sys_errno);
2149                 tevent_req_nterror(req, status);
2150                 return;
2151         }
2152
2153         tevent_req_done(req);
2154 }
2155
2156 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2157                                             TALLOC_CTX *mem_ctx,
2158                                             struct smbd_smb2_request **_smb2_req)
2159 {
2160         struct smbd_smb2_request_read_state *state =
2161                 tevent_req_data(req,
2162                 struct smbd_smb2_request_read_state);
2163         NTSTATUS status;
2164
2165         if (tevent_req_is_nterror(req, &status)) {
2166                 tevent_req_received(req);
2167                 return status;
2168         }
2169
2170         talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2171         *_smb2_req = state->smb2_req;
2172         tevent_req_received(req);
2173         return NT_STATUS_OK;
2174 }
2175
2176 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2177
2178 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2179                              const uint8_t *inbuf, size_t size)
2180 {
2181         NTSTATUS status;
2182         struct smbd_smb2_request *req = NULL;
2183         struct tevent_req *subreq;
2184
2185         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2186                  (unsigned int)size));
2187
2188         status = smbd_initialize_smb2(sconn);
2189         if (!NT_STATUS_IS_OK(status)) {
2190                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2191                 return;
2192         }
2193
2194         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2195         if (!NT_STATUS_IS_OK(status)) {
2196                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2197                 return;
2198         }
2199
2200         status = smbd_smb2_request_setup_out(req);
2201         if (!NT_STATUS_IS_OK(status)) {
2202                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2203                 return;
2204         }
2205
2206         status = smbd_smb2_request_dispatch(req);
2207         if (!NT_STATUS_IS_OK(status)) {
2208                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2209                 return;
2210         }
2211
2212         /* ask for the next request */
2213         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2214         if (subreq == NULL) {
2215                 smbd_server_connection_terminate(sconn, "no memory for reading");
2216                 return;
2217         }
2218         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2219 }
2220
2221 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2222 {
2223         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2224                                                struct smbd_server_connection);
2225         NTSTATUS status;
2226         struct smbd_smb2_request *req = NULL;
2227
2228         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2229         TALLOC_FREE(subreq);
2230         if (!NT_STATUS_IS_OK(status)) {
2231                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2232                         nt_errstr(status)));
2233                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2234                 return;
2235         }
2236
2237         if (req->in.nbt_hdr[0] != 0x00) {
2238                 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2239                          req->in.nbt_hdr[0]));
2240                 TALLOC_FREE(req);
2241                 goto next;
2242         }
2243
2244         req->current_idx = 1;
2245
2246         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2247                  req->current_idx, req->in.vector_count));
2248
2249         status = smbd_smb2_request_validate(req);
2250         if (!NT_STATUS_IS_OK(status)) {
2251                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2252                 return;
2253         }
2254
2255         status = smbd_smb2_request_setup_out(req);
2256         if (!NT_STATUS_IS_OK(status)) {
2257                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2258                 return;
2259         }
2260
2261         status = smbd_smb2_request_dispatch(req);
2262         if (!NT_STATUS_IS_OK(status)) {
2263                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2264                 return;
2265         }
2266
2267 next:
2268         /* ask for the next request (this constructs the main loop) */
2269         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2270         if (subreq == NULL) {
2271                 smbd_server_connection_terminate(sconn, "no memory for reading");
2272                 return;
2273         }
2274         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2275 }