d4147a1f0f5f7e82b5db7fdc47480b6ae3ea8889
[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 = sconn->ev_ctx;
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         req->last_session_id = UINT64_MAX;
213         req->last_tid = UINT32_MAX;
214
215         talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
216         talloc_set_destructor(req, smbd_smb2_request_destructor);
217
218         return req;
219 }
220
221 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
222                                          const uint8_t *inbuf, size_t size,
223                                          struct smbd_smb2_request **_req)
224 {
225         struct smbd_smb2_request *req;
226         uint32_t protocol_version;
227         const uint8_t *inhdr = NULL;
228         off_t ofs = 0;
229         uint16_t cmd;
230         uint32_t next_command_ofs;
231
232         if (size < (4 + SMB2_HDR_BODY + 2)) {
233                 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
234                 return NT_STATUS_INVALID_PARAMETER;
235         }
236
237         inhdr = inbuf + 4;
238
239         protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
240         if (protocol_version != SMB2_MAGIC) {
241                 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
242                          protocol_version));
243                 return NT_STATUS_INVALID_PARAMETER;
244         }
245
246         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
247         if (cmd != SMB2_OP_NEGPROT) {
248                 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
249                          cmd));
250                 return NT_STATUS_INVALID_PARAMETER;
251         }
252
253         next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
254         if (next_command_ofs != 0) {
255                 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
256                          next_command_ofs));
257                 return NT_STATUS_INVALID_PARAMETER;
258         }
259
260         req = smbd_smb2_request_allocate(sconn);
261         if (req == NULL) {
262                 return NT_STATUS_NO_MEMORY;
263         }
264         req->sconn = sconn;
265
266         talloc_steal(req, inbuf);
267
268         req->in.vector = talloc_array(req, struct iovec, 4);
269         if (req->in.vector == NULL) {
270                 TALLOC_FREE(req);
271                 return NT_STATUS_NO_MEMORY;
272         }
273         req->in.vector_count = 4;
274
275         memcpy(req->in.nbt_hdr, inbuf, 4);
276
277         ofs = 0;
278         req->in.vector[0].iov_base      = discard_const_p(void, req->in.nbt_hdr);
279         req->in.vector[0].iov_len       = 4;
280         ofs += req->in.vector[0].iov_len;
281
282         req->in.vector[1].iov_base      = discard_const_p(void, (inbuf + ofs));
283         req->in.vector[1].iov_len       = SMB2_HDR_BODY;
284         ofs += req->in.vector[1].iov_len;
285
286         req->in.vector[2].iov_base      = discard_const_p(void, (inbuf + ofs));
287         req->in.vector[2].iov_len       = SVAL(inbuf, ofs) & 0xFFFE;
288         ofs += req->in.vector[2].iov_len;
289
290         if (ofs > size) {
291                 return NT_STATUS_INVALID_PARAMETER;
292         }
293
294         req->in.vector[3].iov_base      = discard_const_p(void, (inbuf + ofs));
295         req->in.vector[3].iov_len       = size - ofs;
296         ofs += req->in.vector[3].iov_len;
297
298         req->current_idx = 1;
299
300         *_req = req;
301         return NT_STATUS_OK;
302 }
303
304 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
305                                 const uint8_t *inhdr)
306 {
307         uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
308         struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
309         uint16_t opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
310         unsigned int bitmap_offset;
311
312         if (opcode == SMB2_OP_CANCEL) {
313                 /* SMB2_CANCEL requests by definition resend messageids. */
314                 return true;
315         }
316
317         if (message_id < sconn->smb2.seqnum_low ||
318                         message_id > (sconn->smb2.seqnum_low +
319                         (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR))) {
320                 DEBUG(0,("smb2_validate_message_id: bad message_id "
321                         "%llu (low = %llu, max = %lu)\n",
322                         (unsigned long long)message_id,
323                         (unsigned long long)sconn->smb2.seqnum_low,
324                         (unsigned long)sconn->smb2.max_credits ));
325                 return false;
326         }
327
328         if (sconn->smb2.credits_granted == 0) {
329                 DEBUG(0,("smb2_validate_message_id: client used more "
330                          "credits than granted message_id (%llu)\n",
331                          (unsigned long long)message_id));
332                 return false;
333         }
334
335         /* client just used a credit. */
336         sconn->smb2.credits_granted -= 1;
337
338         /* Mark the message_id as seen in the bitmap. */
339         bitmap_offset = (unsigned int)(message_id %
340                         (uint64_t)(sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR));
341         if (bitmap_query(credits_bm, bitmap_offset)) {
342                 DEBUG(0,("smb2_validate_message_id: duplicate message_id "
343                         "%llu (bm offset %u)\n",
344                         (unsigned long long)message_id,
345                         bitmap_offset));
346                 return false;
347         }
348         bitmap_set(credits_bm, bitmap_offset);
349
350         if (message_id == sconn->smb2.seqnum_low + 1) {
351                 /* Move the window forward by all the message_id's
352                    already seen. */
353                 while (bitmap_query(credits_bm, bitmap_offset)) {
354                         DEBUG(10,("smb2_validate_message_id: clearing "
355                                 "id %llu (position %u) from bitmap\n",
356                                 (unsigned long long)(sconn->smb2.seqnum_low + 1),
357                                 bitmap_offset ));
358                         bitmap_clear(credits_bm, bitmap_offset);
359                         sconn->smb2.seqnum_low += 1;
360                         bitmap_offset = (bitmap_offset + 1) %
361                                 (sconn->smb2.max_credits * DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR);
362                 }
363         }
364
365         return true;
366 }
367
368 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
369 {
370         int count;
371         int idx;
372
373         count = req->in.vector_count;
374
375         if (count < 4) {
376                 /* It's not a SMB2 request */
377                 return NT_STATUS_INVALID_PARAMETER;
378         }
379
380         for (idx=1; idx < count; idx += 3) {
381                 const uint8_t *inhdr = NULL;
382                 uint32_t flags;
383
384                 if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
385                         return NT_STATUS_INVALID_PARAMETER;
386                 }
387
388                 if (req->in.vector[idx+1].iov_len < 2) {
389                         return NT_STATUS_INVALID_PARAMETER;
390                 }
391
392                 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
393
394                 /* Check the SMB2 header */
395                 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
396                         return NT_STATUS_INVALID_PARAMETER;
397                 }
398
399                 if (!smb2_validate_message_id(req->sconn, inhdr)) {
400                         return NT_STATUS_INVALID_PARAMETER;
401                 }
402
403                 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
404                 if (idx == 1) {
405                         /*
406                          * the 1st request should never have the
407                          * SMB2_HDR_FLAG_CHAINED flag set
408                          */
409                         if (flags & SMB2_HDR_FLAG_CHAINED) {
410                                 req->next_status = NT_STATUS_INVALID_PARAMETER;
411                                 return NT_STATUS_OK;
412                         }
413                 } else if (idx == 4) {
414                         /*
415                          * the 2nd request triggers related vs. unrelated
416                          * compounded requests
417                          */
418                         if (flags & SMB2_HDR_FLAG_CHAINED) {
419                                 req->compound_related = true;
420                         }
421                 } else if (idx > 4) {
422 #if 0
423                         /*
424                          * It seems the this tests are wrong
425                          * see the SMB2-COMPOUND test
426                          */
427
428                         /*
429                          * all other requests should match the 2nd one
430                          */
431                         if (flags & SMB2_HDR_FLAG_CHAINED) {
432                                 if (!req->compound_related) {
433                                         req->next_status =
434                                                 NT_STATUS_INVALID_PARAMETER;
435                                         return NT_STATUS_OK;
436                                 }
437                         } else {
438                                 if (req->compound_related) {
439                                         req->next_status =
440                                                 NT_STATUS_INVALID_PARAMETER;
441                                         return NT_STATUS_OK;
442                                 }
443                         }
444 #endif
445                 }
446         }
447
448         return NT_STATUS_OK;
449 }
450
451 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
452                         const struct iovec *in_vector,
453                         struct iovec *out_vector)
454 {
455         const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
456         uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
457         uint16_t credits_requested;
458         uint32_t out_flags;
459         uint16_t credits_granted = 0;
460
461         credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
462         out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
463
464         SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
465
466         if (out_flags & SMB2_HDR_FLAG_ASYNC) {
467                 /*
468                  * In case we already send an async interim
469                  * response, we should not grant
470                  * credits on the final response.
471                  */
472                 credits_requested = 0;
473         }
474
475         if (credits_requested) {
476                 uint16_t modified_credits_requested;
477                 uint32_t multiplier;
478
479                 /*
480                  * Split up max_credits into 1/16ths, and then scale
481                  * the requested credits by how many 16ths have been
482                  * currently granted. Less than 1/16th == grant all
483                  * requested (100%), scale down as more have been
484                  * granted. Never ask for less than 1 as the client
485                  * asked for at least 1. JRA.
486                  */
487
488                 multiplier = 16 - (((sconn->smb2.credits_granted * 16) / sconn->smb2.max_credits) % 16);
489
490                 modified_credits_requested = (multiplier * credits_requested) / 16;
491                 if (modified_credits_requested == 0) {
492                         modified_credits_requested = 1;
493                 }
494
495                 /* Remember what we gave out. */
496                 credits_granted = MIN(modified_credits_requested,
497                                         (sconn->smb2.max_credits - sconn->smb2.credits_granted));
498         }
499
500         if (credits_granted == 0 && sconn->smb2.credits_granted == 0) {
501                 /* First negprot packet, or ensure the client credits can
502                    never drop to zero. */
503                 credits_granted = 1;
504         }
505
506         SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
507         sconn->smb2.credits_granted += credits_granted;
508
509         DEBUG(10,("smb2_set_operation_credit: requested %u, "
510                 "granted %u, total granted %u\n",
511                 (unsigned int)credits_requested,
512                 (unsigned int)credits_granted,
513                 (unsigned int)sconn->smb2.credits_granted ));
514 }
515
516 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
517                                 struct smbd_smb2_request *outreq)
518 {
519         int count, idx;
520         uint16_t total_credits = 0;
521
522         count = outreq->out.vector_count;
523
524         for (idx=1; idx < count; idx += 3) {
525                 uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
526                 smb2_set_operation_credit(outreq->sconn,
527                         &inreq->in.vector[idx],
528                         &outreq->out.vector[idx]);
529                 /* To match Windows, count up what we
530                    just granted. */
531                 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
532                 /* Set to zero in all but the last reply. */
533                 if (idx + 3 < count) {
534                         SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
535                 } else {
536                         SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
537                 }
538         }
539 }
540
541 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
542 {
543         struct iovec *vector;
544         int count;
545         int idx;
546
547         count = req->in.vector_count;
548         vector = talloc_zero_array(req, struct iovec, count);
549         if (vector == NULL) {
550                 return NT_STATUS_NO_MEMORY;
551         }
552
553         vector[0].iov_base      = req->out.nbt_hdr;
554         vector[0].iov_len       = 4;
555         SIVAL(req->out.nbt_hdr, 0, 0);
556
557         for (idx=1; idx < count; idx += 3) {
558                 const uint8_t *inhdr = NULL;
559                 uint32_t in_flags;
560                 uint8_t *outhdr = NULL;
561                 uint8_t *outbody = NULL;
562                 uint32_t next_command_ofs = 0;
563                 struct iovec *current = &vector[idx];
564
565                 if ((idx + 3) < count) {
566                         /* we have a next command -
567                          * setup for the error case. */
568                         next_command_ofs = SMB2_HDR_BODY + 9;
569                 }
570
571                 inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
572                 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
573
574                 outhdr = talloc_zero_array(vector, uint8_t,
575                                       OUTVEC_ALLOC_SIZE);
576                 if (outhdr == NULL) {
577                         return NT_STATUS_NO_MEMORY;
578                 }
579
580                 outbody = outhdr + SMB2_HDR_BODY;
581
582                 current[0].iov_base     = (void *)outhdr;
583                 current[0].iov_len      = SMB2_HDR_BODY;
584
585                 current[1].iov_base     = (void *)outbody;
586                 current[1].iov_len      = 8;
587
588                 current[2].iov_base     = NULL;
589                 current[2].iov_len      = 0;
590
591                 /* setup the SMB2 header */
592                 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
593                 SSVAL(outhdr, SMB2_HDR_LENGTH,          SMB2_HDR_BODY);
594                 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
595                       SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
596                 SIVAL(outhdr, SMB2_HDR_STATUS,
597                       NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
598                 SSVAL(outhdr, SMB2_HDR_OPCODE,
599                       SVAL(inhdr, SMB2_HDR_OPCODE));
600                 SIVAL(outhdr, SMB2_HDR_FLAGS,
601                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
602                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
603                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
604                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
605                 SIVAL(outhdr, SMB2_HDR_PID,
606                       IVAL(inhdr, SMB2_HDR_PID));
607                 SIVAL(outhdr, SMB2_HDR_TID,
608                       IVAL(inhdr, SMB2_HDR_TID));
609                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
610                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
611                 memcpy(outhdr + SMB2_HDR_SIGNATURE,
612                        inhdr + SMB2_HDR_SIGNATURE, 16);
613
614                 /* setup error body header */
615                 SSVAL(outbody, 0x00, 0x08 + 1);
616                 SSVAL(outbody, 0x02, 0);
617                 SIVAL(outbody, 0x04, 0);
618         }
619
620         req->out.vector = vector;
621         req->out.vector_count = count;
622
623         /* setup the length of the NBT packet */
624         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
625
626         DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
627
628         return NT_STATUS_OK;
629 }
630
631 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
632                                          const char *reason,
633                                          const char *location)
634 {
635         DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
636                   reason, location));
637         exit_server_cleanly(reason);
638 }
639
640 static bool dup_smb2_vec3(TALLOC_CTX *ctx,
641                         struct iovec *outvec,
642                         const struct iovec *srcvec)
643 {
644         /* vec[0] is always boilerplate and must
645          * be allocated with size OUTVEC_ALLOC_SIZE. */
646
647         outvec[0].iov_base = talloc_memdup(ctx,
648                                 srcvec[0].iov_base,
649                                 OUTVEC_ALLOC_SIZE);
650         if (!outvec[0].iov_base) {
651                 return false;
652         }
653         outvec[0].iov_len = SMB2_HDR_BODY;
654
655         /*
656          * If this is a "standard" vec[1] of length 8,
657          * pointing to srcvec[0].iov_base + SMB2_HDR_BODY,
658          * then duplicate this. Else use talloc_memdup().
659          */
660
661         if (srcvec[1].iov_len == 8 &&
662                         srcvec[1].iov_base ==
663                                 ((uint8_t *)srcvec[0].iov_base) +
664                                         SMB2_HDR_BODY) {
665                 outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) +
666                                         SMB2_HDR_BODY;
667                 outvec[1].iov_len = 8;
668         } else {
669                 outvec[1].iov_base = talloc_memdup(ctx,
670                                 srcvec[1].iov_base,
671                                 srcvec[1].iov_len);
672                 if (!outvec[1].iov_base) {
673                         return false;
674                 }
675                 outvec[1].iov_len = srcvec[1].iov_len;
676         }
677
678         /*
679          * If this is a "standard" vec[2] of length 1,
680          * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1)
681          * then duplicate this. Else use talloc_memdup().
682          */
683
684         if (srcvec[2].iov_base &&
685                         srcvec[2].iov_len) {
686                 if (srcvec[2].iov_base ==
687                                 ((uint8_t *)srcvec[0].iov_base) +
688                                         (OUTVEC_ALLOC_SIZE - 1) &&
689                                 srcvec[2].iov_len == 1) {
690                         /* Common SMB2 error packet case. */
691                         outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) +
692                                 (OUTVEC_ALLOC_SIZE - 1);
693                 } else {
694                         outvec[2].iov_base = talloc_memdup(ctx,
695                                         srcvec[2].iov_base,
696                                         srcvec[2].iov_len);
697                         if (!outvec[2].iov_base) {
698                                 return false;
699                         }
700                 }
701                 outvec[2].iov_len = srcvec[2].iov_len;
702         } else {
703                 outvec[2].iov_base = NULL;
704                 outvec[2].iov_len = 0;
705         }
706         return true;
707 }
708
709 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
710 {
711         struct smbd_smb2_request *newreq = NULL;
712         struct iovec *outvec = NULL;
713         int count = req->out.vector_count;
714         int i;
715
716         newreq = smbd_smb2_request_allocate(req->sconn);
717         if (!newreq) {
718                 return NULL;
719         }
720
721         newreq->sconn = req->sconn;
722         newreq->session = req->session;
723         newreq->do_signing = req->do_signing;
724         newreq->current_idx = req->current_idx;
725
726         outvec = talloc_zero_array(newreq, struct iovec, count);
727         if (!outvec) {
728                 TALLOC_FREE(newreq);
729                 return NULL;
730         }
731         newreq->out.vector = outvec;
732         newreq->out.vector_count = count;
733
734         /* Setup the outvec's identically to req. */
735         outvec[0].iov_base = newreq->out.nbt_hdr;
736         outvec[0].iov_len = 4;
737         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
738
739         /* Setup the vectors identically to the ones in req. */
740         for (i = 1; i < count; i += 3) {
741                 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
742                         break;
743                 }
744         }
745
746         if (i < count) {
747                 /* Alloc failed. */
748                 TALLOC_FREE(newreq);
749                 return NULL;
750         }
751
752         smb2_setup_nbt_length(newreq->out.vector,
753                 newreq->out.vector_count);
754
755         return newreq;
756 }
757
758 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
759
760 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
761 {
762         int i = 0;
763         uint8_t *outhdr = NULL;
764         struct smbd_smb2_request *nreq = NULL;
765
766         /* Create a new smb2 request we'll use
767            for the interim return. */
768         nreq = dup_smb2_req(req);
769         if (!nreq) {
770                 return NT_STATUS_NO_MEMORY;
771         }
772
773         /* Lose the last 3 out vectors. They're the
774            ones we'll be using for the async reply. */
775         nreq->out.vector_count -= 3;
776
777         smb2_setup_nbt_length(nreq->out.vector,
778                 nreq->out.vector_count);
779
780         /* Step back to the previous reply. */
781         i = nreq->current_idx - 3;
782         outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
783         /* And end the chain. */
784         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
785
786         /* Calculate outgoing credits */
787         smb2_calculate_credits(req, nreq);
788
789         /* Re-sign if needed. */
790         if (nreq->do_signing) {
791                 NTSTATUS status;
792                 status = smb2_signing_sign_pdu(nreq->session->session_key,
793                                         &nreq->out.vector[i], 3);
794                 if (!NT_STATUS_IS_OK(status)) {
795                         return status;
796                 }
797         }
798         if (DEBUGLEVEL >= 10) {
799                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
800                         (unsigned int)nreq->current_idx );
801                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
802                         (unsigned int)nreq->out.vector_count );
803                 print_req_vectors(nreq);
804         }
805         nreq->subreq = tstream_writev_queue_send(nreq,
806                                         nreq->sconn->smb2.event_ctx,
807                                         nreq->sconn->smb2.stream,
808                                         nreq->sconn->smb2.send_queue,
809                                         nreq->out.vector,
810                                         nreq->out.vector_count);
811
812         if (nreq->subreq == NULL) {
813                 return NT_STATUS_NO_MEMORY;
814         }
815
816         tevent_req_set_callback(nreq->subreq,
817                         smbd_smb2_request_writev_done,
818                         nreq);
819
820         return NT_STATUS_OK;
821 }
822
823 struct smbd_smb2_request_pending_state {
824         struct smbd_server_connection *sconn;
825         uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
826         struct iovec vector[3];
827 };
828
829 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
830 {
831         struct smbd_smb2_request_pending_state *state =
832                 tevent_req_callback_data(subreq,
833                         struct smbd_smb2_request_pending_state);
834         struct smbd_server_connection *sconn = state->sconn;
835         int ret;
836         int sys_errno;
837
838         ret = tstream_writev_queue_recv(subreq, &sys_errno);
839         TALLOC_FREE(subreq);
840         if (ret == -1) {
841                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
842                 smbd_server_connection_terminate(sconn, nt_errstr(status));
843                 return;
844         }
845
846         TALLOC_FREE(state);
847 }
848
849 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
850                                             struct tevent_timer *te,
851                                             struct timeval current_time,
852                                             void *private_data);
853
854 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
855                                          struct tevent_req *subreq,
856                                          uint32_t defer_time)
857 {
858         NTSTATUS status;
859         int i = req->current_idx;
860         struct timeval defer_endtime;
861         uint8_t *outhdr = NULL;
862         uint32_t flags;
863
864         if (!tevent_req_is_in_progress(subreq)) {
865                 return NT_STATUS_OK;
866         }
867
868         req->subreq = subreq;
869         subreq = NULL;
870
871         if (req->async_te) {
872                 /* We're already async. */
873                 return NT_STATUS_OK;
874         }
875
876         outhdr = (uint8_t *)req->out.vector[i].iov_base;
877         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
878         if (flags & SMB2_HDR_FLAG_ASYNC) {
879                 /* We're already async. */
880                 return NT_STATUS_OK;
881         }
882
883         if (req->in.vector_count > i + 3) {
884                 /*
885                  * We're trying to go async in a compound
886                  * request chain. This is not allowed.
887                  * Cancel the outstanding request.
888                  */
889                 tevent_req_cancel(req->subreq);
890                 return smbd_smb2_request_error(req,
891                         NT_STATUS_INSUFFICIENT_RESOURCES);
892         }
893
894         if (DEBUGLEVEL >= 10) {
895                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
896                         (unsigned int)req->current_idx );
897                 print_req_vectors(req);
898         }
899
900         if (req->out.vector_count > 4) {
901                 struct iovec *outvec = NULL;
902
903                 /* This is a compound reply. We
904                  * must do an interim response
905                  * followed by the async response
906                  * to match W2K8R2.
907                  */
908                 status = smb2_send_async_interim_response(req);
909                 if (!NT_STATUS_IS_OK(status)) {
910                         return status;
911                 }
912
913                 /*
914                  * We're splitting off the last SMB2
915                  * request in a compound set, and the
916                  * smb2_send_async_interim_response()
917                  * call above just sent all the replies
918                  * for the previous SMB2 requests in
919                  * this compound set. So we're no longer
920                  * in the "compound_related_in_progress"
921                  * state, and this is no longer a compound
922                  * request.
923                  */
924                 req->compound_related = false;
925                 req->sconn->smb2.compound_related_in_progress = false;
926
927                 /* Re-arrange the in.vectors. */
928                 req->in.vector[1] = req->in.vector[i];
929                 req->in.vector[2] = req->in.vector[i+1];
930                 req->in.vector[3] = req->in.vector[i+2];
931                 req->in.vector_count = 4;
932
933                 /* Reset the new in size. */
934                 smb2_setup_nbt_length(req->in.vector, 4);
935
936                 /* Now recreate the out.vectors. */
937                 outvec = talloc_zero_array(req, struct iovec, 4);
938                 if (!outvec) {
939                         return NT_STATUS_NO_MEMORY;
940                 }
941
942                 /* 0 is always boilerplate and must
943                  * be of size 4 for the length field. */
944
945                 outvec[0].iov_base = req->out.nbt_hdr;
946                 outvec[0].iov_len = 4;
947                 SIVAL(req->out.nbt_hdr, 0, 0);
948
949                 if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
950                         return NT_STATUS_NO_MEMORY;
951                 }
952
953                 TALLOC_FREE(req->out.vector);
954
955                 req->out.vector = outvec;
956
957                 req->current_idx = 1;
958                 req->out.vector_count = 4;
959
960                 outhdr = (uint8_t *)req->out.vector[1].iov_base;
961                 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
962                 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
963         }
964
965         defer_endtime = timeval_current_ofs_usec(defer_time);
966         req->async_te = tevent_add_timer(req->sconn->smb2.event_ctx,
967                                          req, defer_endtime,
968                                          smbd_smb2_request_pending_timer,
969                                          req);
970         if (req->async_te == NULL) {
971                 return NT_STATUS_NO_MEMORY;
972         }
973
974         return NT_STATUS_OK;
975 }
976
977 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
978                                             struct tevent_timer *te,
979                                             struct timeval current_time,
980                                             void *private_data)
981 {
982         struct smbd_smb2_request *req =
983                 talloc_get_type_abort(private_data,
984                 struct smbd_smb2_request);
985         struct smbd_smb2_request_pending_state *state = NULL;
986         int i = req->current_idx;
987         uint8_t *outhdr = NULL;
988         const uint8_t *inhdr = NULL;
989         uint8_t *hdr = NULL;
990         uint8_t *body = NULL;
991         uint32_t flags = 0;
992         uint64_t message_id = 0;
993         uint64_t async_id = 0;
994         struct tevent_req *subreq = NULL;
995
996         TALLOC_FREE(req->async_te);
997
998         /* Ensure our final reply matches the interim one. */
999         inhdr = (const uint8_t *)req->in.vector[1].iov_base;
1000         outhdr = (uint8_t *)req->out.vector[1].iov_base;
1001         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1002         message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1003
1004         async_id = message_id; /* keep it simple for now... */
1005
1006         SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1007         SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1008
1009         DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1010                 "going async\n",
1011                 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1012                 (unsigned long long)async_id ));
1013
1014         /*
1015          * What we send is identical to a smbd_smb2_request_error
1016          * packet with an error status of STATUS_PENDING. Make use
1017          * of this fact sometime when refactoring. JRA.
1018          */
1019
1020         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1021         if (state == NULL) {
1022                 smbd_server_connection_terminate(req->sconn,
1023                                                  nt_errstr(NT_STATUS_NO_MEMORY));
1024                 return;
1025         }
1026         state->sconn = req->sconn;
1027
1028         state->vector[0].iov_base = (void *)state->buf;
1029         state->vector[0].iov_len = 4;
1030
1031         state->vector[1].iov_base = state->buf + 4;
1032         state->vector[1].iov_len = SMB2_HDR_BODY;
1033
1034         state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
1035         state->vector[2].iov_len = 9;
1036
1037         smb2_setup_nbt_length(state->vector, 3);
1038
1039         hdr = (uint8_t *)state->vector[1].iov_base;
1040         body = (uint8_t *)state->vector[2].iov_base;
1041
1042         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1043         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1044         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1045         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1046         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1047
1048         SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1049         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1050         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1051         SBVAL(hdr, SMB2_HDR_PID, async_id);
1052         SBVAL(hdr, SMB2_HDR_SESSION_ID,
1053                 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1054         memcpy(hdr+SMB2_HDR_SIGNATURE,
1055                outhdr+SMB2_HDR_SIGNATURE, 16);
1056
1057         SSVAL(body, 0x00, 0x08 + 1);
1058
1059         SCVAL(body, 0x02, 0);
1060         SCVAL(body, 0x03, 0);
1061         SIVAL(body, 0x04, 0);
1062         /* Match W2K8R2... */
1063         SCVAL(body, 0x08, 0x21);
1064
1065         /* Ensure we correctly go through crediting. Grant
1066            the credits now, and zero credits on the final
1067            response. */
1068         smb2_set_operation_credit(req->sconn,
1069                         &req->in.vector[i],
1070                         &state->vector[1]);
1071
1072         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1073
1074         if (req->do_signing) {
1075                 NTSTATUS status;
1076
1077                 status = smb2_signing_sign_pdu(req->session->session_key,
1078                                         &state->vector[1], 2);
1079                 if (!NT_STATUS_IS_OK(status)) {
1080                         smbd_server_connection_terminate(req->sconn,
1081                                                 nt_errstr(status));
1082                         return;
1083                 }
1084         }
1085
1086         subreq = tstream_writev_queue_send(state,
1087                                         state->sconn->smb2.event_ctx,
1088                                         state->sconn->smb2.stream,
1089                                         state->sconn->smb2.send_queue,
1090                                         state->vector,
1091                                         3);
1092         if (subreq == NULL) {
1093                 smbd_server_connection_terminate(state->sconn,
1094                                                  nt_errstr(NT_STATUS_NO_MEMORY));
1095                 return;
1096         }
1097         tevent_req_set_callback(subreq,
1098                         smbd_smb2_request_pending_writev_done,
1099                         state);
1100 }
1101
1102 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1103 {
1104         struct smbd_server_connection *sconn = req->sconn;
1105         struct smbd_smb2_request *cur;
1106         const uint8_t *inhdr;
1107         int i = req->current_idx;
1108         uint32_t flags;
1109         uint64_t search_message_id;
1110         uint64_t search_async_id;
1111         uint64_t found_id;
1112
1113         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1114
1115         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1116         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1117         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1118
1119         /*
1120          * we don't need the request anymore
1121          * cancel requests never have a response
1122          */
1123         DLIST_REMOVE(req->sconn->smb2.requests, req);
1124         TALLOC_FREE(req);
1125
1126         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1127                 const uint8_t *outhdr;
1128                 uint64_t message_id;
1129                 uint64_t async_id;
1130
1131                 i = cur->current_idx;
1132
1133                 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1134
1135                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1136                 async_id = BVAL(outhdr, SMB2_HDR_PID);
1137
1138                 if (flags & SMB2_HDR_FLAG_ASYNC) {
1139                         if (search_async_id == async_id) {
1140                                 found_id = async_id;
1141                                 break;
1142                         }
1143                 } else {
1144                         if (search_message_id == message_id) {
1145                                 found_id = message_id;
1146                                 break;
1147                         }
1148                 }
1149         }
1150
1151         if (cur && cur->subreq) {
1152                 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1153                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1154                         "cancel opcode[%s] mid %llu\n",
1155                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1156                         (unsigned long long)found_id ));
1157                 tevent_req_cancel(cur->subreq);
1158         }
1159
1160         return NT_STATUS_OK;
1161 }
1162
1163 /*************************************************************
1164  Ensure an incoming tid is a valid one for us to access.
1165  Change to the associated uid credentials and chdir to the
1166  valid tid directory.
1167 *************************************************************/
1168
1169 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1170 {
1171         const uint8_t *inhdr;
1172         int i = req->current_idx;
1173         uint32_t in_flags;
1174         uint32_t in_tid;
1175         void *p;
1176         struct smbd_smb2_tcon *tcon;
1177
1178         req->tcon = NULL;
1179
1180         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1181
1182         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1183         in_tid = IVAL(inhdr, SMB2_HDR_TID);
1184
1185         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1186                 in_tid = req->last_tid;
1187         }
1188
1189         /* lookup an existing session */
1190         p = idr_find(req->session->tcons.idtree, in_tid);
1191         if (p == NULL) {
1192                 return NT_STATUS_NETWORK_NAME_DELETED;
1193         }
1194         tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1195
1196         if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1197                 return NT_STATUS_ACCESS_DENIED;
1198         }
1199
1200         /* should we pass FLAG_CASELESS_PATHNAMES here? */
1201         if (!set_current_service(tcon->compat_conn, 0, true)) {
1202                 return NT_STATUS_ACCESS_DENIED;
1203         }
1204
1205         req->tcon = tcon;
1206         req->last_tid = in_tid;
1207
1208         return NT_STATUS_OK;
1209 }
1210
1211 /*************************************************************
1212  Ensure an incoming session_id is a valid one for us to access.
1213 *************************************************************/
1214
1215 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1216 {
1217         const uint8_t *inhdr;
1218         int i = req->current_idx;
1219         uint32_t in_flags;
1220         uint64_t in_session_id;
1221         void *p;
1222         struct smbd_smb2_session *session;
1223
1224         req->session = NULL;
1225         req->tcon = NULL;
1226
1227         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1228
1229         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1230         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1231
1232         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1233                 in_session_id = req->last_session_id;
1234         }
1235
1236         /* lookup an existing session */
1237         p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1238         if (p == NULL) {
1239                 return NT_STATUS_USER_SESSION_DELETED;
1240         }
1241         session = talloc_get_type_abort(p, struct smbd_smb2_session);
1242
1243         if (!NT_STATUS_IS_OK(session->status)) {
1244                 return NT_STATUS_ACCESS_DENIED;
1245         }
1246
1247         set_current_user_info(session->session_info->unix_info->sanitized_username,
1248                               session->session_info->unix_info->unix_name,
1249                               session->session_info->info->domain_name);
1250
1251         req->session = session;
1252         req->last_session_id = in_session_id;
1253
1254         return NT_STATUS_OK;
1255 }
1256
1257 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1258                                         size_t expected_body_size)
1259 {
1260         const uint8_t *inhdr;
1261         uint16_t opcode;
1262         const uint8_t *inbody;
1263         int i = req->current_idx;
1264         size_t body_size;
1265         size_t min_dyn_size = expected_body_size & 0x00000001;
1266
1267         /*
1268          * The following should be checked already.
1269          */
1270         if ((i+2) > req->in.vector_count) {
1271                 return NT_STATUS_INTERNAL_ERROR;
1272         }
1273         if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1274                 return NT_STATUS_INTERNAL_ERROR;
1275         }
1276         if (req->in.vector[i+1].iov_len < 2) {
1277                 return NT_STATUS_INTERNAL_ERROR;
1278         }
1279
1280         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1281         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1282
1283         switch (opcode) {
1284         case SMB2_OP_IOCTL:
1285         case SMB2_OP_GETINFO:
1286                 min_dyn_size = 0;
1287                 break;
1288         }
1289
1290         /*
1291          * Now check the expected body size,
1292          * where the last byte might be in the
1293          * dynnamic section..
1294          */
1295         if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1296                 return NT_STATUS_INVALID_PARAMETER;
1297         }
1298         if (req->in.vector[i+2].iov_len < min_dyn_size) {
1299                 return NT_STATUS_INVALID_PARAMETER;
1300         }
1301
1302         inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1303
1304         body_size = SVAL(inbody, 0x00);
1305         if (body_size != expected_body_size) {
1306                 return NT_STATUS_INVALID_PARAMETER;
1307         }
1308
1309         return NT_STATUS_OK;
1310 }
1311
1312 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1313 {
1314         const uint8_t *inhdr;
1315         int i = req->current_idx;
1316         uint16_t opcode;
1317         uint32_t flags;
1318         uint64_t mid;
1319         NTSTATUS status;
1320         NTSTATUS session_status;
1321         uint32_t allowed_flags;
1322         NTSTATUS return_value;
1323
1324         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1325
1326         /* TODO: verify more things */
1327
1328         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1329         opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1330         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1331         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1332                 smb2_opcode_name(opcode),
1333                 (unsigned long long)mid));
1334
1335         if (get_Protocol() >= PROTOCOL_SMB2_02) {
1336                 /*
1337                  * once the protocol is negotiated
1338                  * SMB2_OP_NEGPROT is not allowed anymore
1339                  */
1340                 if (opcode == SMB2_OP_NEGPROT) {
1341                         /* drop the connection */
1342                         return NT_STATUS_INVALID_PARAMETER;
1343                 }
1344         } else {
1345                 /*
1346                  * if the protocol is not negotiated yet
1347                  * only SMB2_OP_NEGPROT is allowed.
1348                  */
1349                 if (opcode != SMB2_OP_NEGPROT) {
1350                         /* drop the connection */
1351                         return NT_STATUS_INVALID_PARAMETER;
1352                 }
1353         }
1354
1355         allowed_flags = SMB2_HDR_FLAG_CHAINED |
1356                         SMB2_HDR_FLAG_SIGNED |
1357                         SMB2_HDR_FLAG_DFS;
1358         if (opcode == SMB2_OP_CANCEL) {
1359                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1360         }
1361         if ((flags & ~allowed_flags) != 0) {
1362                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1363         }
1364
1365         /*
1366          * Check if the client provided a valid session id,
1367          * if so smbd_smb2_request_check_session() calls
1368          * set_current_user_info().
1369          *
1370          * As some command don't require a valid session id
1371          * we defer the check of the session_status
1372          */
1373         session_status = smbd_smb2_request_check_session(req);
1374
1375         req->do_signing = false;
1376         if (flags & SMB2_HDR_FLAG_SIGNED) {
1377                 if (!NT_STATUS_IS_OK(session_status)) {
1378                         return smbd_smb2_request_error(req, session_status);
1379                 }
1380
1381                 req->do_signing = true;
1382                 status = smb2_signing_check_pdu(req->session->session_key,
1383                                                 &req->in.vector[i], 3);
1384                 if (!NT_STATUS_IS_OK(status)) {
1385                         return smbd_smb2_request_error(req, status);
1386                 }
1387         } else if (opcode == SMB2_OP_CANCEL) {
1388                 /* Cancel requests are allowed to skip the signing */
1389         } else if (req->session && req->session->do_signing) {
1390                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1391         }
1392
1393         if (flags & SMB2_HDR_FLAG_CHAINED) {
1394                 /*
1395                  * This check is mostly for giving the correct error code
1396                  * for compounded requests.
1397                  *
1398                  * TODO: we may need to move this after the session
1399                  *       and tcon checks.
1400                  */
1401                 if (!NT_STATUS_IS_OK(req->next_status)) {
1402                         return smbd_smb2_request_error(req, req->next_status);
1403                 }
1404         } else {
1405                 req->compat_chain_fsp = NULL;
1406         }
1407
1408         if (req->compound_related) {
1409                 req->sconn->smb2.compound_related_in_progress = true;
1410         }
1411
1412         switch (opcode) {
1413         case SMB2_OP_NEGPROT:
1414                 /* This call needs to be run as root */
1415                 change_to_root_user();
1416
1417                 {
1418                         START_PROFILE(smb2_negprot);
1419                         return_value = smbd_smb2_request_process_negprot(req);
1420                         END_PROFILE(smb2_negprot);
1421                 }
1422                 break;
1423
1424         case SMB2_OP_SESSSETUP:
1425                 /* This call needs to be run as root */
1426                 change_to_root_user();
1427
1428                 {
1429                         START_PROFILE(smb2_sesssetup);
1430                         return_value = smbd_smb2_request_process_sesssetup(req);
1431                         END_PROFILE(smb2_sesssetup);
1432                 }
1433                 break;
1434
1435         case SMB2_OP_LOGOFF:
1436                 if (!NT_STATUS_IS_OK(session_status)) {
1437                         return_value = smbd_smb2_request_error(req, session_status);
1438                         break;
1439                 }
1440
1441                 /* This call needs to be run as root */
1442                 change_to_root_user();
1443
1444                 {
1445                         START_PROFILE(smb2_logoff);
1446                         return_value = smbd_smb2_request_process_logoff(req);
1447                         END_PROFILE(smb2_logoff);
1448                 }
1449                 break;
1450
1451         case SMB2_OP_TCON:
1452                 if (!NT_STATUS_IS_OK(session_status)) {
1453                         return_value = smbd_smb2_request_error(req, session_status);
1454                         break;
1455                 }
1456
1457                 /*
1458                  * This call needs to be run as root.
1459                  *
1460                  * smbd_smb2_request_process_tcon()
1461                  * calls make_connection_snum(), which will call
1462                  * change_to_user(), when needed.
1463                  */
1464                 change_to_root_user();
1465
1466                 {
1467                         START_PROFILE(smb2_tcon);
1468                         return_value = smbd_smb2_request_process_tcon(req);
1469                         END_PROFILE(smb2_tcon);
1470                 }
1471                 break;
1472
1473         case SMB2_OP_TDIS:
1474                 if (!NT_STATUS_IS_OK(session_status)) {
1475                         return_value = smbd_smb2_request_error(req, session_status);
1476                         break;
1477                 }
1478                 /*
1479                  * This call needs to be run as user.
1480                  *
1481                  * smbd_smb2_request_check_tcon()
1482                  * calls change_to_user() on success.
1483                  */
1484                 status = smbd_smb2_request_check_tcon(req);
1485                 if (!NT_STATUS_IS_OK(status)) {
1486                         return_value = smbd_smb2_request_error(req, status);
1487                         break;
1488                 }
1489                 /* This call needs to be run as root */
1490                 change_to_root_user();
1491
1492
1493                 {
1494                         START_PROFILE(smb2_tdis);
1495                         return_value = smbd_smb2_request_process_tdis(req);
1496                         END_PROFILE(smb2_tdis);
1497                 }
1498                 break;
1499
1500         case SMB2_OP_CREATE:
1501                 if (!NT_STATUS_IS_OK(session_status)) {
1502                         return_value = smbd_smb2_request_error(req, session_status);
1503                         break;
1504                 }
1505                 /*
1506                  * This call needs to be run as user.
1507                  *
1508                  * smbd_smb2_request_check_tcon()
1509                  * calls change_to_user() on success.
1510                  */
1511                 status = smbd_smb2_request_check_tcon(req);
1512                 if (!NT_STATUS_IS_OK(status)) {
1513                         return_value = smbd_smb2_request_error(req, status);
1514                         break;
1515                 }
1516
1517                 {
1518                         START_PROFILE(smb2_create);
1519                         return_value = smbd_smb2_request_process_create(req);
1520                         END_PROFILE(smb2_create);
1521                 }
1522                 break;
1523
1524         case SMB2_OP_CLOSE:
1525                 if (!NT_STATUS_IS_OK(session_status)) {
1526                         return_value = smbd_smb2_request_error(req, session_status);
1527                         break;
1528                 }
1529                 /*
1530                  * This call needs to be run as user.
1531                  *
1532                  * smbd_smb2_request_check_tcon()
1533                  * calls change_to_user() on success.
1534                  */
1535                 status = smbd_smb2_request_check_tcon(req);
1536                 if (!NT_STATUS_IS_OK(status)) {
1537                         return_value = smbd_smb2_request_error(req, status);
1538                         break;
1539                 }
1540
1541                 {
1542                         START_PROFILE(smb2_close);
1543                         return_value = smbd_smb2_request_process_close(req);
1544                         END_PROFILE(smb2_close);
1545                 }
1546                 break;
1547
1548         case SMB2_OP_FLUSH:
1549                 if (!NT_STATUS_IS_OK(session_status)) {
1550                         return_value = smbd_smb2_request_error(req, session_status);
1551                         break;
1552                 }
1553                 /*
1554                  * This call needs to be run as user.
1555                  *
1556                  * smbd_smb2_request_check_tcon()
1557                  * calls change_to_user() on success.
1558                  */
1559                 status = smbd_smb2_request_check_tcon(req);
1560                 if (!NT_STATUS_IS_OK(status)) {
1561                         return_value = smbd_smb2_request_error(req, status);
1562                         break;
1563                 }
1564
1565                 {
1566                         START_PROFILE(smb2_flush);
1567                         return_value = smbd_smb2_request_process_flush(req);
1568                         END_PROFILE(smb2_flush);
1569                 }
1570                 break;
1571
1572         case SMB2_OP_READ:
1573                 if (!NT_STATUS_IS_OK(session_status)) {
1574                         return_value = smbd_smb2_request_error(req, session_status);
1575                         break;
1576                 }
1577                 /*
1578                  * This call needs to be run as user.
1579                  *
1580                  * smbd_smb2_request_check_tcon()
1581                  * calls change_to_user() on success.
1582                  */
1583                 status = smbd_smb2_request_check_tcon(req);
1584                 if (!NT_STATUS_IS_OK(status)) {
1585                         return_value = smbd_smb2_request_error(req, status);
1586                         break;
1587                 }
1588
1589                 {
1590                         START_PROFILE(smb2_read);
1591                         return_value = smbd_smb2_request_process_read(req);
1592                         END_PROFILE(smb2_read);
1593                 }
1594                 break;
1595
1596         case SMB2_OP_WRITE:
1597                 if (!NT_STATUS_IS_OK(session_status)) {
1598                         return_value = smbd_smb2_request_error(req, session_status);
1599                         break;
1600                 }
1601                 /*
1602                  * This call needs to be run as user.
1603                  *
1604                  * smbd_smb2_request_check_tcon()
1605                  * calls change_to_user() on success.
1606                  */
1607                 status = smbd_smb2_request_check_tcon(req);
1608                 if (!NT_STATUS_IS_OK(status)) {
1609                         return_value = smbd_smb2_request_error(req, status);
1610                         break;
1611                 }
1612
1613                 {
1614                         START_PROFILE(smb2_write);
1615                         return_value = smbd_smb2_request_process_write(req);
1616                         END_PROFILE(smb2_write);
1617                 }
1618                 break;
1619
1620         case SMB2_OP_LOCK:
1621                 if (!NT_STATUS_IS_OK(session_status)) {
1622                         /* Too ugly to live ? JRA. */
1623                         if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1624                                 session_status = NT_STATUS_FILE_CLOSED;
1625                         }
1626                         return_value = smbd_smb2_request_error(req, session_status);
1627                         break;
1628                 }
1629                 /*
1630                  * This call needs to be run as user.
1631                  *
1632                  * smbd_smb2_request_check_tcon()
1633                  * calls change_to_user() on success.
1634                  */
1635                 status = smbd_smb2_request_check_tcon(req);
1636                 if (!NT_STATUS_IS_OK(status)) {
1637                         /* Too ugly to live ? JRA. */
1638                         if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1639                                 status = NT_STATUS_FILE_CLOSED;
1640                         }
1641                         return_value = smbd_smb2_request_error(req, status);
1642                         break;
1643                 }
1644
1645                 {
1646                         START_PROFILE(smb2_lock);
1647                         return_value = smbd_smb2_request_process_lock(req);
1648                         END_PROFILE(smb2_lock);
1649                 }
1650                 break;
1651
1652         case SMB2_OP_IOCTL:
1653                 if (!NT_STATUS_IS_OK(session_status)) {
1654                         return_value = smbd_smb2_request_error(req, session_status);
1655                         break;
1656                 }
1657                 /*
1658                  * This call needs to be run as user.
1659                  *
1660                  * smbd_smb2_request_check_tcon()
1661                  * calls change_to_user() on success.
1662                  */
1663                 status = smbd_smb2_request_check_tcon(req);
1664                 if (!NT_STATUS_IS_OK(status)) {
1665                         return_value = smbd_smb2_request_error(req, status);
1666                         break;
1667                 }
1668
1669                 {
1670                         START_PROFILE(smb2_ioctl);
1671                         return_value = smbd_smb2_request_process_ioctl(req);
1672                         END_PROFILE(smb2_ioctl);
1673                 }
1674                 break;
1675
1676         case SMB2_OP_CANCEL:
1677                 /*
1678                  * This call needs to be run as root
1679                  *
1680                  * That is what we also do in the SMB1 case.
1681                  */
1682                 change_to_root_user();
1683
1684                 {
1685                         START_PROFILE(smb2_cancel);
1686                         return_value = smbd_smb2_request_process_cancel(req);
1687                         END_PROFILE(smb2_cancel);
1688                 }
1689                 break;
1690
1691         case SMB2_OP_KEEPALIVE:
1692                 /* This call needs to be run as root */
1693                 change_to_root_user();
1694
1695                 {
1696                         START_PROFILE(smb2_keepalive);
1697                         return_value = smbd_smb2_request_process_keepalive(req);
1698                         END_PROFILE(smb2_keepalive);
1699                 }
1700                 break;
1701
1702         case SMB2_OP_FIND:
1703                 if (!NT_STATUS_IS_OK(session_status)) {
1704                         return_value = smbd_smb2_request_error(req, session_status);
1705                         break;
1706                 }
1707                 /*
1708                  * This call needs to be run as user.
1709                  *
1710                  * smbd_smb2_request_check_tcon()
1711                  * calls change_to_user() on success.
1712                  */
1713                 status = smbd_smb2_request_check_tcon(req);
1714                 if (!NT_STATUS_IS_OK(status)) {
1715                         return_value = smbd_smb2_request_error(req, status);
1716                         break;
1717                 }
1718
1719                 {
1720                         START_PROFILE(smb2_find);
1721                         return_value = smbd_smb2_request_process_find(req);
1722                         END_PROFILE(smb2_find);
1723                 }
1724                 break;
1725
1726         case SMB2_OP_NOTIFY:
1727                 if (!NT_STATUS_IS_OK(session_status)) {
1728                         return_value = smbd_smb2_request_error(req, session_status);
1729                         break;
1730                 }
1731                 /*
1732                  * This call needs to be run as user.
1733                  *
1734                  * smbd_smb2_request_check_tcon()
1735                  * calls change_to_user() on success.
1736                  */
1737                 status = smbd_smb2_request_check_tcon(req);
1738                 if (!NT_STATUS_IS_OK(status)) {
1739                         return_value = smbd_smb2_request_error(req, status);
1740                         break;
1741                 }
1742
1743                 {
1744                         START_PROFILE(smb2_notify);
1745                         return_value = smbd_smb2_request_process_notify(req);
1746                         END_PROFILE(smb2_notify);
1747                 }
1748                 break;
1749
1750         case SMB2_OP_GETINFO:
1751                 if (!NT_STATUS_IS_OK(session_status)) {
1752                         return_value = smbd_smb2_request_error(req, session_status);
1753                         break;
1754                 }
1755                 /*
1756                  * This call needs to be run as user.
1757                  *
1758                  * smbd_smb2_request_check_tcon()
1759                  * calls change_to_user() on success.
1760                  */
1761                 status = smbd_smb2_request_check_tcon(req);
1762                 if (!NT_STATUS_IS_OK(status)) {
1763                         return_value = smbd_smb2_request_error(req, status);
1764                         break;
1765                 }
1766
1767                 {
1768                         START_PROFILE(smb2_getinfo);
1769                         return_value = smbd_smb2_request_process_getinfo(req);
1770                         END_PROFILE(smb2_getinfo);
1771                 }
1772                 break;
1773
1774         case SMB2_OP_SETINFO:
1775                 if (!NT_STATUS_IS_OK(session_status)) {
1776                         return_value = smbd_smb2_request_error(req, session_status);
1777                         break;
1778                 }
1779                 /*
1780                  * This call needs to be run as user.
1781                  *
1782                  * smbd_smb2_request_check_tcon()
1783                  * calls change_to_user() on success.
1784                  */
1785                 status = smbd_smb2_request_check_tcon(req);
1786                 if (!NT_STATUS_IS_OK(status)) {
1787                         return_value = smbd_smb2_request_error(req, status);
1788                         break;
1789                 }
1790
1791                 {
1792                         START_PROFILE(smb2_setinfo);
1793                         return_value = smbd_smb2_request_process_setinfo(req);
1794                         END_PROFILE(smb2_setinfo);
1795                 }
1796                 break;
1797
1798         case SMB2_OP_BREAK:
1799                 if (!NT_STATUS_IS_OK(session_status)) {
1800                         return_value = smbd_smb2_request_error(req, session_status);
1801                         break;
1802                 }
1803                 /*
1804                  * This call needs to be run as user.
1805                  *
1806                  * smbd_smb2_request_check_tcon()
1807                  * calls change_to_user() on success.
1808                  */
1809                 status = smbd_smb2_request_check_tcon(req);
1810                 if (!NT_STATUS_IS_OK(status)) {
1811                         return_value = smbd_smb2_request_error(req, status);
1812                         break;
1813                 }
1814
1815                 {
1816                         START_PROFILE(smb2_break);
1817                         return_value = smbd_smb2_request_process_break(req);
1818                         END_PROFILE(smb2_break);
1819                 }
1820                 break;
1821
1822         default:
1823                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1824                 break;
1825         }
1826         return return_value;
1827 }
1828
1829 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1830 {
1831         struct tevent_req *subreq;
1832         int i = req->current_idx;
1833
1834         req->subreq = NULL;
1835         TALLOC_FREE(req->async_te);
1836
1837         req->current_idx += 3;
1838
1839         if (req->current_idx < req->out.vector_count) {
1840                 /*
1841                  * We must process the remaining compound
1842                  * SMB2 requests before any new incoming SMB2
1843                  * requests. This is because incoming SMB2
1844                  * requests may include a cancel for a
1845                  * compound request we haven't processed
1846                  * yet.
1847                  */
1848                 struct tevent_immediate *im = tevent_create_immediate(req);
1849                 if (!im) {
1850                         return NT_STATUS_NO_MEMORY;
1851                 }
1852                 tevent_schedule_immediate(im,
1853                                         req->sconn->smb2.event_ctx,
1854                                         smbd_smb2_request_dispatch_immediate,
1855                                         req);
1856                 return NT_STATUS_OK;
1857         }
1858
1859         if (req->compound_related) {
1860                 req->sconn->smb2.compound_related_in_progress = false;
1861         }
1862
1863         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1864
1865         /* Set credit for these operations (zero credits if this
1866            is a final reply for an async operation). */
1867         smb2_calculate_credits(req, req);
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 }