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