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