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