s3:smbd: disconnect the socket if we got an unexpected request
[kai/samba.git] / source3 / smbd / smb2_server.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #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         if (get_Protocol() >= PROTOCOL_SMB2_02) {
1337                 /*
1338                  * once the protocol is negotiated
1339                  * SMB2_OP_NEGPROT is not allowed anymore
1340                  */
1341                 if (opcode == SMB2_OP_NEGPROT) {
1342                         /* drop the connection */
1343                         return NT_STATUS_INVALID_PARAMETER;
1344                 }
1345         } else {
1346                 /*
1347                  * if the protocol is not negotiated yet
1348                  * only SMB2_OP_NEGPROT is allowed.
1349                  */
1350                 if (opcode != SMB2_OP_NEGPROT) {
1351                         /* drop the connection */
1352                         return NT_STATUS_INVALID_PARAMETER;
1353                 }
1354         }
1355
1356         allowed_flags = SMB2_HDR_FLAG_CHAINED |
1357                         SMB2_HDR_FLAG_SIGNED |
1358                         SMB2_HDR_FLAG_DFS;
1359         if (opcode == SMB2_OP_CANCEL) {
1360                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1361         }
1362         if ((flags & ~allowed_flags) != 0) {
1363                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1364         }
1365
1366         /*
1367          * Check if the client provided a valid session id,
1368          * if so smbd_smb2_request_check_session() calls
1369          * set_current_user_info().
1370          *
1371          * As some command don't require a valid session id
1372          * we defer the check of the session_status
1373          */
1374         session_status = smbd_smb2_request_check_session(req);
1375
1376         req->do_signing = false;
1377         if (flags & SMB2_HDR_FLAG_SIGNED) {
1378                 if (!NT_STATUS_IS_OK(session_status)) {
1379                         return smbd_smb2_request_error(req, session_status);
1380                 }
1381
1382                 req->do_signing = true;
1383                 status = smb2_signing_check_pdu(req->session->session_key,
1384                                                 &req->in.vector[i], 3);
1385                 if (!NT_STATUS_IS_OK(status)) {
1386                         return smbd_smb2_request_error(req, status);
1387                 }
1388         } else if (req->session && req->session->do_signing) {
1389                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1390         }
1391
1392         if (flags & SMB2_HDR_FLAG_CHAINED) {
1393                 /*
1394                  * This check is mostly for giving the correct error code
1395                  * for compounded requests.
1396                  *
1397                  * TODO: we may need to move this after the session
1398                  *       and tcon checks.
1399                  */
1400                 if (!NT_STATUS_IS_OK(req->next_status)) {
1401                         return smbd_smb2_request_error(req, req->next_status);
1402                 }
1403         } else {
1404                 req->compat_chain_fsp = NULL;
1405         }
1406
1407         if (req->compound_related) {
1408                 req->sconn->smb2.compound_related_in_progress = true;
1409         }
1410
1411         switch (opcode) {
1412         case SMB2_OP_NEGPROT:
1413                 /* This call needs to be run as root */
1414                 change_to_root_user();
1415
1416                 {
1417                         START_PROFILE(smb2_negprot);
1418                         return_value = smbd_smb2_request_process_negprot(req);
1419                         END_PROFILE(smb2_negprot);
1420                 }
1421                 break;
1422
1423         case SMB2_OP_SESSSETUP:
1424                 /* This call needs to be run as root */
1425                 change_to_root_user();
1426
1427                 {
1428                         START_PROFILE(smb2_sesssetup);
1429                         return_value = smbd_smb2_request_process_sesssetup(req);
1430                         END_PROFILE(smb2_sesssetup);
1431                 }
1432                 break;
1433
1434         case SMB2_OP_LOGOFF:
1435                 if (!NT_STATUS_IS_OK(session_status)) {
1436                         return_value = smbd_smb2_request_error(req, session_status);
1437                         break;
1438                 }
1439
1440                 /* This call needs to be run as root */
1441                 change_to_root_user();
1442
1443                 {
1444                         START_PROFILE(smb2_logoff);
1445                         return_value = smbd_smb2_request_process_logoff(req);
1446                         END_PROFILE(smb2_logoff);
1447                 }
1448                 break;
1449
1450         case SMB2_OP_TCON:
1451                 if (!NT_STATUS_IS_OK(session_status)) {
1452                         return_value = smbd_smb2_request_error(req, session_status);
1453                         break;
1454                 }
1455
1456                 /*
1457                  * This call needs to be run as root.
1458                  *
1459                  * smbd_smb2_request_process_tcon()
1460                  * calls make_connection_snum(), which will call
1461                  * change_to_user(), when needed.
1462                  */
1463                 change_to_root_user();
1464
1465                 {
1466                         START_PROFILE(smb2_tcon);
1467                         return_value = smbd_smb2_request_process_tcon(req);
1468                         END_PROFILE(smb2_tcon);
1469                 }
1470                 break;
1471
1472         case SMB2_OP_TDIS:
1473                 if (!NT_STATUS_IS_OK(session_status)) {
1474                         return_value = smbd_smb2_request_error(req, session_status);
1475                         break;
1476                 }
1477                 /*
1478                  * This call needs to be run as user.
1479                  *
1480                  * smbd_smb2_request_check_tcon()
1481                  * calls change_to_user() on success.
1482                  */
1483                 status = smbd_smb2_request_check_tcon(req);
1484                 if (!NT_STATUS_IS_OK(status)) {
1485                         return_value = smbd_smb2_request_error(req, status);
1486                         break;
1487                 }
1488                 /* This call needs to be run as root */
1489                 change_to_root_user();
1490
1491
1492                 {
1493                         START_PROFILE(smb2_tdis);
1494                         return_value = smbd_smb2_request_process_tdis(req);
1495                         END_PROFILE(smb2_tdis);
1496                 }
1497                 break;
1498
1499         case SMB2_OP_CREATE:
1500                 if (!NT_STATUS_IS_OK(session_status)) {
1501                         return_value = smbd_smb2_request_error(req, session_status);
1502                         break;
1503                 }
1504                 /*
1505                  * This call needs to be run as user.
1506                  *
1507                  * smbd_smb2_request_check_tcon()
1508                  * calls change_to_user() on success.
1509                  */
1510                 status = smbd_smb2_request_check_tcon(req);
1511                 if (!NT_STATUS_IS_OK(status)) {
1512                         return_value = smbd_smb2_request_error(req, status);
1513                         break;
1514                 }
1515
1516                 {
1517                         START_PROFILE(smb2_create);
1518                         return_value = smbd_smb2_request_process_create(req);
1519                         END_PROFILE(smb2_create);
1520                 }
1521                 break;
1522
1523         case SMB2_OP_CLOSE:
1524                 if (!NT_STATUS_IS_OK(session_status)) {
1525                         return_value = smbd_smb2_request_error(req, session_status);
1526                         break;
1527                 }
1528                 /*
1529                  * This call needs to be run as user.
1530                  *
1531                  * smbd_smb2_request_check_tcon()
1532                  * calls change_to_user() on success.
1533                  */
1534                 status = smbd_smb2_request_check_tcon(req);
1535                 if (!NT_STATUS_IS_OK(status)) {
1536                         return_value = smbd_smb2_request_error(req, status);
1537                         break;
1538                 }
1539
1540                 {
1541                         START_PROFILE(smb2_close);
1542                         return_value = smbd_smb2_request_process_close(req);
1543                         END_PROFILE(smb2_close);
1544                 }
1545                 break;
1546
1547         case SMB2_OP_FLUSH:
1548                 if (!NT_STATUS_IS_OK(session_status)) {
1549                         return_value = smbd_smb2_request_error(req, session_status);
1550                         break;
1551                 }
1552                 /*
1553                  * This call needs to be run as user.
1554                  *
1555                  * smbd_smb2_request_check_tcon()
1556                  * calls change_to_user() on success.
1557                  */
1558                 status = smbd_smb2_request_check_tcon(req);
1559                 if (!NT_STATUS_IS_OK(status)) {
1560                         return_value = smbd_smb2_request_error(req, status);
1561                         break;
1562                 }
1563
1564                 {
1565                         START_PROFILE(smb2_flush);
1566                         return_value = smbd_smb2_request_process_flush(req);
1567                         END_PROFILE(smb2_flush);
1568                 }
1569                 break;
1570
1571         case SMB2_OP_READ:
1572                 if (!NT_STATUS_IS_OK(session_status)) {
1573                         return_value = smbd_smb2_request_error(req, session_status);
1574                         break;
1575                 }
1576                 /*
1577                  * This call needs to be run as user.
1578                  *
1579                  * smbd_smb2_request_check_tcon()
1580                  * calls change_to_user() on success.
1581                  */
1582                 status = smbd_smb2_request_check_tcon(req);
1583                 if (!NT_STATUS_IS_OK(status)) {
1584                         return_value = smbd_smb2_request_error(req, status);
1585                         break;
1586                 }
1587
1588                 {
1589                         START_PROFILE(smb2_read);
1590                         return_value = smbd_smb2_request_process_read(req);
1591                         END_PROFILE(smb2_read);
1592                 }
1593                 break;
1594
1595         case SMB2_OP_WRITE:
1596                 if (!NT_STATUS_IS_OK(session_status)) {
1597                         return_value = smbd_smb2_request_error(req, session_status);
1598                         break;
1599                 }
1600                 /*
1601                  * This call needs to be run as user.
1602                  *
1603                  * smbd_smb2_request_check_tcon()
1604                  * calls change_to_user() on success.
1605                  */
1606                 status = smbd_smb2_request_check_tcon(req);
1607                 if (!NT_STATUS_IS_OK(status)) {
1608                         return_value = smbd_smb2_request_error(req, status);
1609                         break;
1610                 }
1611
1612                 {
1613                         START_PROFILE(smb2_write);
1614                         return_value = smbd_smb2_request_process_write(req);
1615                         END_PROFILE(smb2_write);
1616                 }
1617                 break;
1618
1619         case SMB2_OP_LOCK:
1620                 if (!NT_STATUS_IS_OK(session_status)) {
1621                         /* Too ugly to live ? JRA. */
1622                         if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1623                                 session_status = NT_STATUS_FILE_CLOSED;
1624                         }
1625                         return_value = smbd_smb2_request_error(req, session_status);
1626                         break;
1627                 }
1628                 /*
1629                  * This call needs to be run as user.
1630                  *
1631                  * smbd_smb2_request_check_tcon()
1632                  * calls change_to_user() on success.
1633                  */
1634                 status = smbd_smb2_request_check_tcon(req);
1635                 if (!NT_STATUS_IS_OK(status)) {
1636                         /* Too ugly to live ? JRA. */
1637                         if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1638                                 status = NT_STATUS_FILE_CLOSED;
1639                         }
1640                         return_value = smbd_smb2_request_error(req, status);
1641                         break;
1642                 }
1643
1644                 {
1645                         START_PROFILE(smb2_lock);
1646                         return_value = smbd_smb2_request_process_lock(req);
1647                         END_PROFILE(smb2_lock);
1648                 }
1649                 break;
1650
1651         case SMB2_OP_IOCTL:
1652                 if (!NT_STATUS_IS_OK(session_status)) {
1653                         return_value = smbd_smb2_request_error(req, session_status);
1654                         break;
1655                 }
1656                 /*
1657                  * This call needs to be run as user.
1658                  *
1659                  * smbd_smb2_request_check_tcon()
1660                  * calls change_to_user() on success.
1661                  */
1662                 status = smbd_smb2_request_check_tcon(req);
1663                 if (!NT_STATUS_IS_OK(status)) {
1664                         return_value = smbd_smb2_request_error(req, status);
1665                         break;
1666                 }
1667
1668                 {
1669                         START_PROFILE(smb2_ioctl);
1670                         return_value = smbd_smb2_request_process_ioctl(req);
1671                         END_PROFILE(smb2_ioctl);
1672                 }
1673                 break;
1674
1675         case SMB2_OP_CANCEL:
1676                 /*
1677                  * This call needs to be run as root
1678                  *
1679                  * That is what we also do in the SMB1 case.
1680                  */
1681                 change_to_root_user();
1682
1683                 {
1684                         START_PROFILE(smb2_cancel);
1685                         return_value = smbd_smb2_request_process_cancel(req);
1686                         END_PROFILE(smb2_cancel);
1687                 }
1688                 break;
1689
1690         case SMB2_OP_KEEPALIVE:
1691                 /* This call needs to be run as root */
1692                 change_to_root_user();
1693
1694                 {
1695                         START_PROFILE(smb2_keepalive);
1696                         return_value = smbd_smb2_request_process_keepalive(req);
1697                         END_PROFILE(smb2_keepalive);
1698                 }
1699                 break;
1700
1701         case SMB2_OP_FIND:
1702                 if (!NT_STATUS_IS_OK(session_status)) {
1703                         return_value = smbd_smb2_request_error(req, session_status);
1704                         break;
1705                 }
1706                 /*
1707                  * This call needs to be run as user.
1708                  *
1709                  * smbd_smb2_request_check_tcon()
1710                  * calls change_to_user() on success.
1711                  */
1712                 status = smbd_smb2_request_check_tcon(req);
1713                 if (!NT_STATUS_IS_OK(status)) {
1714                         return_value = smbd_smb2_request_error(req, status);
1715                         break;
1716                 }
1717
1718                 {
1719                         START_PROFILE(smb2_find);
1720                         return_value = smbd_smb2_request_process_find(req);
1721                         END_PROFILE(smb2_find);
1722                 }
1723                 break;
1724
1725         case SMB2_OP_NOTIFY:
1726                 if (!NT_STATUS_IS_OK(session_status)) {
1727                         return_value = smbd_smb2_request_error(req, session_status);
1728                         break;
1729                 }
1730                 /*
1731                  * This call needs to be run as user.
1732                  *
1733                  * smbd_smb2_request_check_tcon()
1734                  * calls change_to_user() on success.
1735                  */
1736                 status = smbd_smb2_request_check_tcon(req);
1737                 if (!NT_STATUS_IS_OK(status)) {
1738                         return_value = smbd_smb2_request_error(req, status);
1739                         break;
1740                 }
1741
1742                 {
1743                         START_PROFILE(smb2_notify);
1744                         return_value = smbd_smb2_request_process_notify(req);
1745                         END_PROFILE(smb2_notify);
1746                 }
1747                 break;
1748
1749         case SMB2_OP_GETINFO:
1750                 if (!NT_STATUS_IS_OK(session_status)) {
1751                         return_value = smbd_smb2_request_error(req, session_status);
1752                         break;
1753                 }
1754                 /*
1755                  * This call needs to be run as user.
1756                  *
1757                  * smbd_smb2_request_check_tcon()
1758                  * calls change_to_user() on success.
1759                  */
1760                 status = smbd_smb2_request_check_tcon(req);
1761                 if (!NT_STATUS_IS_OK(status)) {
1762                         return_value = smbd_smb2_request_error(req, status);
1763                         break;
1764                 }
1765
1766                 {
1767                         START_PROFILE(smb2_getinfo);
1768                         return_value = smbd_smb2_request_process_getinfo(req);
1769                         END_PROFILE(smb2_getinfo);
1770                 }
1771                 break;
1772
1773         case SMB2_OP_SETINFO:
1774                 if (!NT_STATUS_IS_OK(session_status)) {
1775                         return_value = smbd_smb2_request_error(req, session_status);
1776                         break;
1777                 }
1778                 /*
1779                  * This call needs to be run as user.
1780                  *
1781                  * smbd_smb2_request_check_tcon()
1782                  * calls change_to_user() on success.
1783                  */
1784                 status = smbd_smb2_request_check_tcon(req);
1785                 if (!NT_STATUS_IS_OK(status)) {
1786                         return_value = smbd_smb2_request_error(req, status);
1787                         break;
1788                 }
1789
1790                 {
1791                         START_PROFILE(smb2_setinfo);
1792                         return_value = smbd_smb2_request_process_setinfo(req);
1793                         END_PROFILE(smb2_setinfo);
1794                 }
1795                 break;
1796
1797         case SMB2_OP_BREAK:
1798                 if (!NT_STATUS_IS_OK(session_status)) {
1799                         return_value = smbd_smb2_request_error(req, session_status);
1800                         break;
1801                 }
1802                 /*
1803                  * This call needs to be run as user.
1804                  *
1805                  * smbd_smb2_request_check_tcon()
1806                  * calls change_to_user() on success.
1807                  */
1808                 status = smbd_smb2_request_check_tcon(req);
1809                 if (!NT_STATUS_IS_OK(status)) {
1810                         return_value = smbd_smb2_request_error(req, status);
1811                         break;
1812                 }
1813
1814                 {
1815                         START_PROFILE(smb2_break);
1816                         return_value = smbd_smb2_request_process_break(req);
1817                         END_PROFILE(smb2_break);
1818                 }
1819                 break;
1820
1821         default:
1822                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1823                 break;
1824         }
1825         return return_value;
1826 }
1827
1828 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1829 {
1830         struct tevent_req *subreq;
1831         int i = req->current_idx;
1832
1833         req->subreq = NULL;
1834
1835         req->current_idx += 3;
1836
1837         if (req->current_idx < req->out.vector_count) {
1838                 /*
1839                  * We must process the remaining compound
1840                  * SMB2 requests before any new incoming SMB2
1841                  * requests. This is because incoming SMB2
1842                  * requests may include a cancel for a
1843                  * compound request we haven't processed
1844                  * yet.
1845                  */
1846                 struct tevent_immediate *im = tevent_create_immediate(req);
1847                 if (!im) {
1848                         return NT_STATUS_NO_MEMORY;
1849                 }
1850                 tevent_schedule_immediate(im,
1851                                         req->sconn->smb2.event_ctx,
1852                                         smbd_smb2_request_dispatch_immediate,
1853                                         req);
1854                 return NT_STATUS_OK;
1855         }
1856
1857         if (req->compound_related) {
1858                 req->sconn->smb2.compound_related_in_progress = false;
1859         }
1860
1861         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1862
1863         /* Set credit for this operation (zero credits if this
1864            is a final reply for an async operation). */
1865         smb2_set_operation_credit(req->sconn,
1866                         &req->in.vector[i],
1867                         &req->out.vector[i]);
1868
1869         if (req->do_signing) {
1870                 NTSTATUS status;
1871                 status = smb2_signing_sign_pdu(req->session->session_key,
1872                                                &req->out.vector[i], 3);
1873                 if (!NT_STATUS_IS_OK(status)) {
1874                         return status;
1875                 }
1876         }
1877
1878         if (DEBUGLEVEL >= 10) {
1879                 dbgtext("smbd_smb2_request_reply: sending...\n");
1880                 print_req_vectors(req);
1881         }
1882
1883         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1884         if (req->out.vector_count == 4 &&
1885                         req->out.vector[3].iov_base == NULL &&
1886                         req->out.vector[3].iov_len != 0) {
1887                 /* Dynamic part is NULL. Chop it off,
1888                    We're going to send it via sendfile. */
1889                 req->out.vector_count -= 1;
1890         }
1891
1892         subreq = tstream_writev_queue_send(req,
1893                                            req->sconn->smb2.event_ctx,
1894                                            req->sconn->smb2.stream,
1895                                            req->sconn->smb2.send_queue,
1896                                            req->out.vector,
1897                                            req->out.vector_count);
1898         if (subreq == NULL) {
1899                 return NT_STATUS_NO_MEMORY;
1900         }
1901         tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1902         /*
1903          * We're done with this request -
1904          * move it off the "being processed" queue.
1905          */
1906         DLIST_REMOVE(req->sconn->smb2.requests, req);
1907
1908         return NT_STATUS_OK;
1909 }
1910
1911 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1912
1913 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1914                                         struct tevent_immediate *im,
1915                                         void *private_data)
1916 {
1917         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1918                                         struct smbd_smb2_request);
1919         struct smbd_server_connection *sconn = req->sconn;
1920         NTSTATUS status;
1921
1922         TALLOC_FREE(im);
1923
1924         if (DEBUGLEVEL >= 10) {
1925                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1926                         req->current_idx, req->in.vector_count));
1927                 print_req_vectors(req);
1928         }
1929
1930         status = smbd_smb2_request_dispatch(req);
1931         if (!NT_STATUS_IS_OK(status)) {
1932                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1933                 return;
1934         }
1935
1936         status = smbd_smb2_request_next_incoming(sconn);
1937         if (!NT_STATUS_IS_OK(status)) {
1938                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1939                 return;
1940         }
1941 }
1942
1943 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1944 {
1945         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1946                                         struct smbd_smb2_request);
1947         struct smbd_server_connection *sconn = req->sconn;
1948         int ret;
1949         int sys_errno;
1950         NTSTATUS status;
1951
1952         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1953         TALLOC_FREE(subreq);
1954         TALLOC_FREE(req);
1955         if (ret == -1) {
1956                 status = map_nt_error_from_unix(sys_errno);
1957                 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1958                         nt_errstr(status)));
1959                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1960                 return;
1961         }
1962
1963         status = smbd_smb2_request_next_incoming(sconn);
1964         if (!NT_STATUS_IS_OK(status)) {
1965                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1966                 return;
1967         }
1968 }
1969
1970 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1971                                    NTSTATUS status,
1972                                    DATA_BLOB body, DATA_BLOB *dyn,
1973                                    const char *location)
1974 {
1975         uint8_t *outhdr;
1976         int i = req->current_idx;
1977         uint32_t next_command_ofs;
1978
1979         DEBUG(10,("smbd_smb2_request_done_ex: "
1980                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1981                   i, nt_errstr(status), (unsigned int)body.length,
1982                   dyn ? "yes": "no",
1983                   (unsigned int)(dyn ? dyn->length : 0),
1984                   location));
1985
1986         if (body.length < 2) {
1987                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1988         }
1989
1990         if ((body.length % 2) != 0) {
1991                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1992         }
1993
1994         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1995
1996         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1997         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1998
1999         req->out.vector[i+1].iov_base = (void *)body.data;
2000         req->out.vector[i+1].iov_len = body.length;
2001
2002         if (dyn) {
2003                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
2004                 req->out.vector[i+2].iov_len    = dyn->length;
2005         } else {
2006                 req->out.vector[i+2].iov_base = NULL;
2007                 req->out.vector[i+2].iov_len = 0;
2008         }
2009
2010         /* see if we need to recalculate the offset to the next response */
2011         if (next_command_ofs > 0) {
2012                 next_command_ofs  = SMB2_HDR_BODY;
2013                 next_command_ofs += req->out.vector[i+1].iov_len;
2014                 next_command_ofs += req->out.vector[i+2].iov_len;
2015         }
2016
2017         if ((next_command_ofs % 8) != 0) {
2018                 size_t pad_size = 8 - (next_command_ofs % 8);
2019                 if (req->out.vector[i+2].iov_len == 0) {
2020                         /*
2021                          * if the dyn buffer is empty
2022                          * we can use it to add padding
2023                          */
2024                         uint8_t *pad;
2025
2026                         pad = talloc_zero_array(req->out.vector,
2027                                                 uint8_t, pad_size);
2028                         if (pad == NULL) {
2029                                 return smbd_smb2_request_error(req,
2030                                                 NT_STATUS_NO_MEMORY);
2031                         }
2032
2033                         req->out.vector[i+2].iov_base = (void *)pad;
2034                         req->out.vector[i+2].iov_len = pad_size;
2035                 } else {
2036                         /*
2037                          * For now we copy the dynamic buffer
2038                          * and add the padding to the new buffer
2039                          */
2040                         size_t old_size;
2041                         uint8_t *old_dyn;
2042                         size_t new_size;
2043                         uint8_t *new_dyn;
2044
2045                         old_size = req->out.vector[i+2].iov_len;
2046                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2047
2048                         new_size = old_size + pad_size;
2049                         new_dyn = talloc_zero_array(req->out.vector,
2050                                                uint8_t, new_size);
2051                         if (new_dyn == NULL) {
2052                                 return smbd_smb2_request_error(req,
2053                                                 NT_STATUS_NO_MEMORY);
2054                         }
2055
2056                         memcpy(new_dyn, old_dyn, old_size);
2057                         memset(new_dyn + old_size, 0, pad_size);
2058
2059                         req->out.vector[i+2].iov_base = (void *)new_dyn;
2060                         req->out.vector[i+2].iov_len = new_size;
2061                 }
2062                 next_command_ofs += pad_size;
2063         }
2064
2065         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2066
2067         return smbd_smb2_request_reply(req);
2068 }
2069
2070 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2071                                     NTSTATUS status,
2072                                     DATA_BLOB *info,
2073                                     const char *location)
2074 {
2075         DATA_BLOB body;
2076         int i = req->current_idx;
2077         uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2078
2079         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2080                   i, nt_errstr(status), info ? " +info" : "",
2081                   location));
2082
2083         body.data = outhdr + SMB2_HDR_BODY;
2084         body.length = 8;
2085         SSVAL(body.data, 0, 9);
2086
2087         if (info) {
2088                 SIVAL(body.data, 0x04, info->length);
2089         } else {
2090                 /* Allocated size of req->out.vector[i].iov_base
2091                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2092                  * 1 byte without having to do an alloc.
2093                  */
2094                 info = talloc_zero_array(req->out.vector,
2095                                         DATA_BLOB,
2096                                         1);
2097                 if (!info) {
2098                         return NT_STATUS_NO_MEMORY;
2099                 }
2100                 info->data = ((uint8_t *)outhdr) +
2101                         OUTVEC_ALLOC_SIZE - 1;
2102                 info->length = 1;
2103                 SCVAL(info->data, 0, 0);
2104         }
2105
2106         /*
2107          * if a request fails, all other remaining
2108          * compounded requests should fail too
2109          */
2110         req->next_status = NT_STATUS_INVALID_PARAMETER;
2111
2112         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2113 }
2114
2115
2116 struct smbd_smb2_send_oplock_break_state {
2117         struct smbd_server_connection *sconn;
2118         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2119         struct iovec vector;
2120 };
2121
2122 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2123
2124 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2125                                      uint64_t file_id_persistent,
2126                                      uint64_t file_id_volatile,
2127                                      uint8_t oplock_level)
2128 {
2129         struct smbd_smb2_send_oplock_break_state *state;
2130         struct tevent_req *subreq;
2131         uint8_t *hdr;
2132         uint8_t *body;
2133
2134         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2135         if (state == NULL) {
2136                 return NT_STATUS_NO_MEMORY;
2137         }
2138         state->sconn = sconn;
2139
2140         state->vector.iov_base = (void *)state->buf;
2141         state->vector.iov_len = sizeof(state->buf);
2142
2143         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2144         hdr = state->buf + 4;
2145         body = hdr + SMB2_HDR_BODY;
2146
2147         SIVAL(hdr, 0,                           SMB2_MAGIC);
2148         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
2149         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
2150         SIVAL(hdr, SMB2_HDR_STATUS,             0);
2151         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
2152         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
2153         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
2154         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
2155         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
2156         SIVAL(hdr, SMB2_HDR_PID,                0);
2157         SIVAL(hdr, SMB2_HDR_TID,                0);
2158         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
2159         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2160
2161         SSVAL(body, 0x00, 0x18);
2162
2163         SCVAL(body, 0x02, oplock_level);
2164         SCVAL(body, 0x03, 0);           /* reserved */
2165         SIVAL(body, 0x04, 0);           /* reserved */
2166         SBVAL(body, 0x08, file_id_persistent);
2167         SBVAL(body, 0x10, file_id_volatile);
2168
2169         subreq = tstream_writev_queue_send(state,
2170                                            sconn->smb2.event_ctx,
2171                                            sconn->smb2.stream,
2172                                            sconn->smb2.send_queue,
2173                                            &state->vector, 1);
2174         if (subreq == NULL) {
2175                 return NT_STATUS_NO_MEMORY;
2176         }
2177         tevent_req_set_callback(subreq,
2178                                 smbd_smb2_oplock_break_writev_done,
2179                                 state);
2180
2181         return NT_STATUS_OK;
2182 }
2183
2184 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2185 {
2186         struct smbd_smb2_send_oplock_break_state *state =
2187                 tevent_req_callback_data(subreq,
2188                 struct smbd_smb2_send_oplock_break_state);
2189         struct smbd_server_connection *sconn = state->sconn;
2190         int ret;
2191         int sys_errno;
2192
2193         ret = tstream_writev_queue_recv(subreq, &sys_errno);
2194         TALLOC_FREE(subreq);
2195         if (ret == -1) {
2196                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2197                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2198                 return;
2199         }
2200
2201         TALLOC_FREE(state);
2202 }
2203
2204 struct smbd_smb2_request_read_state {
2205         size_t missing;
2206         bool asked_for_header;
2207         struct smbd_smb2_request *smb2_req;
2208 };
2209
2210 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2211                                          void *private_data,
2212                                          TALLOC_CTX *mem_ctx,
2213                                          struct iovec **_vector,
2214                                          size_t *_count);
2215 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2216
2217 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2218                                         struct tevent_context *ev,
2219                                         struct smbd_server_connection *sconn)
2220 {
2221         struct tevent_req *req;
2222         struct smbd_smb2_request_read_state *state;
2223         struct tevent_req *subreq;
2224
2225         req = tevent_req_create(mem_ctx, &state,
2226                                 struct smbd_smb2_request_read_state);
2227         if (req == NULL) {
2228                 return NULL;
2229         }
2230         state->missing = 0;
2231         state->asked_for_header = false;
2232
2233         state->smb2_req = smbd_smb2_request_allocate(state);
2234         if (tevent_req_nomem(state->smb2_req, req)) {
2235                 return tevent_req_post(req, ev);
2236         }
2237         state->smb2_req->sconn = sconn;
2238
2239         subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2240                                               sconn->smb2.recv_queue,
2241                                               smbd_smb2_request_next_vector,
2242                                               state);
2243         if (tevent_req_nomem(subreq, req)) {
2244                 return tevent_req_post(req, ev);
2245         }
2246         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2247
2248         return req;
2249 }
2250
2251 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2252                                          void *private_data,
2253                                          TALLOC_CTX *mem_ctx,
2254                                          struct iovec **_vector,
2255                                          size_t *_count)
2256 {
2257         struct smbd_smb2_request_read_state *state =
2258                 talloc_get_type_abort(private_data,
2259                 struct smbd_smb2_request_read_state);
2260         struct smbd_smb2_request *req = state->smb2_req;
2261         struct iovec *vector;
2262         int idx = req->in.vector_count;
2263         size_t len = 0;
2264         uint8_t *buf = NULL;
2265
2266         if (req->in.vector_count == 0) {
2267                 /*
2268                  * first we need to get the NBT header
2269                  */
2270                 req->in.vector = talloc_array(req, struct iovec,
2271                                               req->in.vector_count + 1);
2272                 if (req->in.vector == NULL) {
2273                         return -1;
2274                 }
2275                 req->in.vector_count += 1;
2276
2277                 req->in.vector[idx].iov_base    = (void *)req->in.nbt_hdr;
2278                 req->in.vector[idx].iov_len     = 4;
2279
2280                 vector = talloc_array(mem_ctx, struct iovec, 1);
2281                 if (vector == NULL) {
2282                         return -1;
2283                 }
2284
2285                 vector[0] = req->in.vector[idx];
2286
2287                 *_vector = vector;
2288                 *_count = 1;
2289                 return 0;
2290         }
2291
2292         if (req->in.vector_count == 1) {
2293                 /*
2294                  * Now we analyze the NBT header
2295                  */
2296                 state->missing = smb2_len(req->in.vector[0].iov_base);
2297
2298                 if (state->missing == 0) {
2299                         /* if there're no remaining bytes, we're done */
2300                         *_vector = NULL;
2301                         *_count = 0;
2302                         return 0;
2303                 }
2304
2305                 req->in.vector = talloc_realloc(req, req->in.vector,
2306                                                 struct iovec,
2307                                                 req->in.vector_count + 1);
2308                 if (req->in.vector == NULL) {
2309                         return -1;
2310                 }
2311                 req->in.vector_count += 1;
2312
2313                 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2314                         /*
2315                          * it's a special NBT message,
2316                          * so get all remaining bytes
2317                          */
2318                         len = state->missing;
2319                 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2320                         /*
2321                          * it's an invalid message, just read what we can get
2322                          * and let the caller handle the error
2323                          */
2324                         len = state->missing;
2325                 } else {
2326                         /*
2327                          * We assume it's a SMB2 request,
2328                          * and we first get the header and the
2329                          * first 2 bytes (the struct size) of the body
2330                          */
2331                         len = SMB2_HDR_BODY + 2;
2332
2333                         state->asked_for_header = true;
2334                 }
2335
2336                 state->missing -= len;
2337
2338                 buf = talloc_array(req->in.vector, uint8_t, len);
2339                 if (buf == NULL) {
2340                         return -1;
2341                 }
2342
2343                 req->in.vector[idx].iov_base    = (void *)buf;
2344                 req->in.vector[idx].iov_len     = len;
2345
2346                 vector = talloc_array(mem_ctx, struct iovec, 1);
2347                 if (vector == NULL) {
2348                         return -1;
2349                 }
2350
2351                 vector[0] = req->in.vector[idx];
2352
2353                 *_vector = vector;
2354                 *_count = 1;
2355                 return 0;
2356         }
2357
2358         if (state->missing == 0) {
2359                 /* if there're no remaining bytes, we're done */
2360                 *_vector = NULL;
2361                 *_count = 0;
2362                 return 0;
2363         }
2364
2365         if (state->asked_for_header) {
2366                 const uint8_t *hdr;
2367                 size_t full_size;
2368                 size_t next_command_ofs;
2369                 size_t body_size;
2370                 uint8_t *body;
2371                 size_t dyn_size;
2372                 uint8_t *dyn;
2373                 bool invalid = false;
2374
2375                 state->asked_for_header = false;
2376
2377                 /*
2378                  * We got the SMB2 header and the first 2 bytes
2379                  * of the body. We fix the size to just the header
2380                  * and manually copy the 2 first bytes to the body section
2381                  */
2382                 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2383                 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2384
2385                 /* allocate vectors for body and dynamic areas */
2386                 req->in.vector = talloc_realloc(req, req->in.vector,
2387                                                 struct iovec,
2388                                                 req->in.vector_count + 2);
2389                 if (req->in.vector == NULL) {
2390                         return -1;
2391                 }
2392                 req->in.vector_count += 2;
2393
2394                 full_size = state->missing + SMB2_HDR_BODY + 2;
2395                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2396                 body_size = SVAL(hdr, SMB2_HDR_BODY);
2397
2398                 if (next_command_ofs != 0) {
2399                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2400                                 /*
2401                                  * this is invalid, just return a zero
2402                                  * body and let the caller deal with the error
2403                                  */
2404                                 invalid = true;
2405                         } else if (next_command_ofs > full_size) {
2406                                 /*
2407                                  * this is invalid, just return a zero
2408                                  * body and let the caller deal with the error
2409                                  */
2410                                 invalid = true;
2411                         } else {
2412                                 full_size = next_command_ofs;
2413                         }
2414                 }
2415
2416                 if (!invalid) {
2417                         if (body_size < 2) {
2418                                 /*
2419                                  * this is invalid, just return a zero
2420                                  * body and let the caller deal with the error
2421                                  */
2422                                 invalid = true;
2423                         }
2424
2425                         /*
2426                          * Mask out the lowest bit, the "dynamic" part
2427                          * of body_size.
2428                          */
2429                         body_size &= ~1;
2430
2431                         if (body_size > (full_size - SMB2_HDR_BODY)) {
2432                                 /*
2433                                  * this is invalid, just return a zero
2434                                  * body and let the caller deal with the error
2435                                  */
2436                                 invalid = true;
2437                         }
2438                 }
2439
2440                 if (invalid) {
2441                         /* the caller should check this */
2442                         body_size = 2;
2443                 }
2444
2445                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2446
2447                 state->missing -= (body_size - 2) + dyn_size;
2448
2449                 body = talloc_array(req->in.vector, uint8_t, body_size);
2450                 if (body == NULL) {
2451                         return -1;
2452                 }
2453
2454                 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2455                 if (dyn == NULL) {
2456                         return -1;
2457                 }
2458
2459                 req->in.vector[idx].iov_base    = (void *)body;
2460                 req->in.vector[idx].iov_len     = body_size;
2461                 req->in.vector[idx+1].iov_base  = (void *)dyn;
2462                 req->in.vector[idx+1].iov_len   = dyn_size;
2463
2464                 vector = talloc_array(mem_ctx, struct iovec, 2);
2465                 if (vector == NULL) {
2466                         return -1;
2467                 }
2468
2469                 /*
2470                  * the first 2 bytes of the body were already fetched
2471                  * together with the header
2472                  */
2473                 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2474                 vector[0].iov_base = body + 2;
2475                 vector[0].iov_len = body_size - 2;
2476
2477                 vector[1] = req->in.vector[idx+1];
2478
2479                 *_vector = vector;
2480                 *_count = 2;
2481                 return 0;
2482         }
2483
2484         /*
2485          * when we endup here, we're looking for a new SMB2 request
2486          * next. And we ask for its header and the first 2 bytes of
2487          * the body (like we did for the first SMB2 request).
2488          */
2489
2490         req->in.vector = talloc_realloc(req, req->in.vector,
2491                                         struct iovec,
2492                                         req->in.vector_count + 1);
2493         if (req->in.vector == NULL) {
2494                 return -1;
2495         }
2496         req->in.vector_count += 1;
2497
2498         /*
2499          * We assume it's a SMB2 request,
2500          * and we first get the header and the
2501          * first 2 bytes (the struct size) of the body
2502          */
2503         len = SMB2_HDR_BODY + 2;
2504
2505         if (len > state->missing) {
2506                 /* let the caller handle the error */
2507                 len = state->missing;
2508         }
2509
2510         state->missing -= len;
2511         state->asked_for_header = true;
2512
2513         buf = talloc_array(req->in.vector, uint8_t, len);
2514         if (buf == NULL) {
2515                 return -1;
2516         }
2517
2518         req->in.vector[idx].iov_base    = (void *)buf;
2519         req->in.vector[idx].iov_len     = len;
2520
2521         vector = talloc_array(mem_ctx, struct iovec, 1);
2522         if (vector == NULL) {
2523                 return -1;
2524         }
2525
2526         vector[0] = req->in.vector[idx];
2527
2528         *_vector = vector;
2529         *_count = 1;
2530         return 0;
2531 }
2532
2533 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2534 {
2535         struct tevent_req *req =
2536                 tevent_req_callback_data(subreq,
2537                 struct tevent_req);
2538         int ret;
2539         int sys_errno;
2540         NTSTATUS status;
2541
2542         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2543         if (ret == -1) {
2544                 status = map_nt_error_from_unix(sys_errno);
2545                 tevent_req_nterror(req, status);
2546                 return;
2547         }
2548
2549         tevent_req_done(req);
2550 }
2551
2552 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2553                                             TALLOC_CTX *mem_ctx,
2554                                             struct smbd_smb2_request **_smb2_req)
2555 {
2556         struct smbd_smb2_request_read_state *state =
2557                 tevent_req_data(req,
2558                 struct smbd_smb2_request_read_state);
2559         NTSTATUS status;
2560
2561         if (tevent_req_is_nterror(req, &status)) {
2562                 tevent_req_received(req);
2563                 return status;
2564         }
2565
2566         talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2567         *_smb2_req = state->smb2_req;
2568         tevent_req_received(req);
2569         return NT_STATUS_OK;
2570 }
2571
2572 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2573
2574 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2575 {
2576         size_t max_send_queue_len;
2577         size_t cur_send_queue_len;
2578         struct tevent_req *subreq;
2579
2580         if (sconn->smb2.compound_related_in_progress) {
2581                 /*
2582                  * Can't read another until the related
2583                  * compound is done.
2584                  */
2585                 return NT_STATUS_OK;
2586         }
2587
2588         if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2589                 /*
2590                  * if there is already a smbd_smb2_request_read
2591                  * pending, we are done.
2592                  */
2593                 return NT_STATUS_OK;
2594         }
2595
2596         max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2597         cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2598
2599         if (cur_send_queue_len > max_send_queue_len) {
2600                 /*
2601                  * if we have a lot of requests to send,
2602                  * we wait until they are on the wire until we
2603                  * ask for the next request.
2604                  */
2605                 return NT_STATUS_OK;
2606         }
2607
2608         /* ask for the next request */
2609         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2610         if (subreq == NULL) {
2611                 return NT_STATUS_NO_MEMORY;
2612         }
2613         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2614
2615         return NT_STATUS_OK;
2616 }
2617
2618 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2619                              const uint8_t *inbuf, size_t size)
2620 {
2621         NTSTATUS status;
2622         struct smbd_smb2_request *req = NULL;
2623
2624         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2625                  (unsigned int)size));
2626
2627         status = smbd_initialize_smb2(sconn);
2628         if (!NT_STATUS_IS_OK(status)) {
2629                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2630                 return;
2631         }
2632
2633         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2634         if (!NT_STATUS_IS_OK(status)) {
2635                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2636                 return;
2637         }
2638
2639         status = smbd_smb2_request_setup_out(req);
2640         if (!NT_STATUS_IS_OK(status)) {
2641                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2642                 return;
2643         }
2644
2645         status = smbd_smb2_request_dispatch(req);
2646         if (!NT_STATUS_IS_OK(status)) {
2647                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2648                 return;
2649         }
2650
2651         status = smbd_smb2_request_next_incoming(sconn);
2652         if (!NT_STATUS_IS_OK(status)) {
2653                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2654                 return;
2655         }
2656
2657         sconn->num_requests++;
2658 }
2659
2660 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2661 {
2662         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2663                                                struct smbd_server_connection);
2664         NTSTATUS status;
2665         struct smbd_smb2_request *req = NULL;
2666
2667         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2668         TALLOC_FREE(subreq);
2669         if (!NT_STATUS_IS_OK(status)) {
2670                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2671                         nt_errstr(status)));
2672                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2673                 return;
2674         }
2675
2676         if (req->in.nbt_hdr[0] != 0x00) {
2677                 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2678                          req->in.nbt_hdr[0]));
2679                 TALLOC_FREE(req);
2680                 goto next;
2681         }
2682
2683         req->current_idx = 1;
2684
2685         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2686                  req->current_idx, req->in.vector_count));
2687
2688         status = smbd_smb2_request_validate(req);
2689         if (!NT_STATUS_IS_OK(status)) {
2690                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2691                 return;
2692         }
2693
2694         status = smbd_smb2_request_setup_out(req);
2695         if (!NT_STATUS_IS_OK(status)) {
2696                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2697                 return;
2698         }
2699
2700         status = smbd_smb2_request_dispatch(req);
2701         if (!NT_STATUS_IS_OK(status)) {
2702                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2703                 return;
2704         }
2705
2706 next:
2707         status = smbd_smb2_request_next_incoming(sconn);
2708         if (!NT_STATUS_IS_OK(status)) {
2709                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2710                 return;
2711         }
2712
2713         sconn->num_requests++;
2714
2715         /* The timeout_processing function isn't run nearly
2716            often enough to implement 'max log size' without
2717            overrunning the size of the file by many megabytes.
2718            This is especially true if we are running at debug
2719            level 10.  Checking every 50 SMB2s is a nice
2720            tradeoff of performance vs log file size overrun. */
2721
2722         if ((sconn->num_requests % 50) == 0 &&
2723             need_to_check_log_size()) {
2724                 change_to_root_user();
2725                 check_log_size();
2726         }
2727 }