s3:smb2_server: remove unused outhdr variables
[metze/samba/wip.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         newreq->async = false;
715         newreq->cancelled = false;
716         /* Note we are leaving:
717                 ->tcon
718                 ->smb1req
719                 ->compat_chain_fsp
720            uninitialized as NULL here as
721            they're not used in the interim
722            response code. JRA. */
723
724         outvec = talloc_zero_array(newreq, struct iovec, count);
725         if (!outvec) {
726                 TALLOC_FREE(newreq);
727                 return NULL;
728         }
729         newreq->out.vector = outvec;
730         newreq->out.vector_count = count;
731
732         /* Setup the outvec's identically to req. */
733         outvec[0].iov_base = newreq->out.nbt_hdr;
734         outvec[0].iov_len = 4;
735         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
736
737         /* Setup the vectors identically to the ones in req. */
738         for (i = 1; i < count; i += 3) {
739                 if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
740                         break;
741                 }
742         }
743
744         if (i < count) {
745                 /* Alloc failed. */
746                 TALLOC_FREE(newreq);
747                 return NULL;
748         }
749
750         smb2_setup_nbt_length(newreq->out.vector,
751                 newreq->out.vector_count);
752
753         return newreq;
754 }
755
756 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
757
758 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
759 {
760         int i = 0;
761         uint8_t *outhdr = NULL;
762         struct smbd_smb2_request *nreq = NULL;
763
764         /* Create a new smb2 request we'll use
765            for the interim return. */
766         nreq = dup_smb2_req(req);
767         if (!nreq) {
768                 return NT_STATUS_NO_MEMORY;
769         }
770
771         /* Lose the last 3 out vectors. They're the
772            ones we'll be using for the async reply. */
773         nreq->out.vector_count -= 3;
774
775         smb2_setup_nbt_length(nreq->out.vector,
776                 nreq->out.vector_count);
777
778         /* Step back to the previous reply. */
779         i = nreq->current_idx - 3;
780         outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
781         /* And end the chain. */
782         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
783
784         /* Calculate outgoing credits */
785         smb2_calculate_credits(req, nreq);
786
787         /* Re-sign if needed. */
788         if (nreq->do_signing) {
789                 NTSTATUS status;
790                 status = smb2_signing_sign_pdu(nreq->session->session_key,
791                                         &nreq->out.vector[i], 3);
792                 if (!NT_STATUS_IS_OK(status)) {
793                         return status;
794                 }
795         }
796         if (DEBUGLEVEL >= 10) {
797                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
798                         (unsigned int)nreq->current_idx );
799                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
800                         (unsigned int)nreq->out.vector_count );
801                 print_req_vectors(nreq);
802         }
803         nreq->subreq = tstream_writev_queue_send(nreq,
804                                         nreq->sconn->smb2.event_ctx,
805                                         nreq->sconn->smb2.stream,
806                                         nreq->sconn->smb2.send_queue,
807                                         nreq->out.vector,
808                                         nreq->out.vector_count);
809
810         if (nreq->subreq == NULL) {
811                 return NT_STATUS_NO_MEMORY;
812         }
813
814         tevent_req_set_callback(nreq->subreq,
815                         smbd_smb2_request_writev_done,
816                         nreq);
817
818         return NT_STATUS_OK;
819 }
820
821 struct smbd_smb2_request_pending_state {
822         struct smbd_server_connection *sconn;
823         uint8_t buf[4 + SMB2_HDR_BODY + 0x08 + 1];
824         struct iovec vector[3];
825 };
826
827 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
828 {
829         struct smbd_smb2_request_pending_state *state =
830                 tevent_req_callback_data(subreq,
831                         struct smbd_smb2_request_pending_state);
832         struct smbd_server_connection *sconn = state->sconn;
833         int ret;
834         int sys_errno;
835
836         ret = tstream_writev_queue_recv(subreq, &sys_errno);
837         TALLOC_FREE(subreq);
838         if (ret == -1) {
839                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
840                 smbd_server_connection_terminate(sconn, nt_errstr(status));
841                 return;
842         }
843
844         TALLOC_FREE(state);
845 }
846
847 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
848                                          struct tevent_req *subreq)
849 {
850         NTSTATUS status;
851         struct smbd_smb2_request_pending_state *state = NULL;
852         int i = req->current_idx;
853         uint8_t *reqhdr = NULL;
854         uint8_t *hdr = NULL;
855         uint8_t *body = NULL;
856         uint32_t flags = 0;
857         uint64_t message_id = 0;
858         uint64_t async_id = 0;
859         struct iovec *outvec = NULL;
860
861         if (!tevent_req_is_in_progress(subreq)) {
862                 return NT_STATUS_OK;
863         }
864
865         req->subreq = subreq;
866         subreq = NULL;
867
868         if (req->async) {
869                 /* We're already async. */
870                 return NT_STATUS_OK;
871         }
872
873         if (req->in.vector_count > i + 3) {
874                 /*
875                  * We're trying to go async in a compound
876                  * request chain. This is not allowed.
877                  * Cancel the outstanding request.
878                  */
879                 tevent_req_cancel(req->subreq);
880                 return smbd_smb2_request_error(req,
881                         NT_STATUS_INSUFFICIENT_RESOURCES);
882         }
883
884         if (DEBUGLEVEL >= 10) {
885                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
886                         (unsigned int)req->current_idx );
887                 print_req_vectors(req);
888         }
889
890         if (req->out.vector_count > 4) {
891                 /* This is a compound reply. We
892                  * must do an interim response
893                  * followed by the async response
894                  * to match W2K8R2.
895                  */
896                 status = smb2_send_async_interim_response(req);
897                 if (!NT_STATUS_IS_OK(status)) {
898                         return status;
899                 }
900
901                 /*
902                  * We're splitting off the last SMB2
903                  * request in a compound set, and the
904                  * smb2_send_async_interim_response()
905                  * call above just sent all the replies
906                  * for the previous SMB2 requests in
907                  * this compound set. So we're no longer
908                  * in the "compound_related_in_progress"
909                  * state, and this is no longer a compound
910                  * request.
911                  */
912                 req->compound_related = false;
913                 req->sconn->smb2.compound_related_in_progress = false;
914         }
915
916         /* Don't return an intermediate packet on a pipe read/write. */
917         if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) {
918                 goto ipc_out;
919         }
920
921         reqhdr = (uint8_t *)req->out.vector[i].iov_base;
922         flags = (IVAL(reqhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
923         message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
924         async_id = message_id; /* keep it simple for now... */
925
926         /*
927          * What we send is identical to a smbd_smb2_request_error
928          * packet with an error status of STATUS_PENDING. Make use
929          * of this fact sometime when refactoring. JRA.
930          */
931
932         state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
933         if (state == NULL) {
934                 return NT_STATUS_NO_MEMORY;
935         }
936         state->sconn = req->sconn;
937
938         state->vector[0].iov_base = (void *)state->buf;
939         state->vector[0].iov_len = 4;
940
941         state->vector[1].iov_base = state->buf + 4;
942         state->vector[1].iov_len = SMB2_HDR_BODY;
943
944         state->vector[2].iov_base = state->buf + 4 + SMB2_HDR_BODY;
945         state->vector[2].iov_len = 9;
946
947         smb2_setup_nbt_length(state->vector, 3);
948
949         hdr = (uint8_t *)state->vector[1].iov_base;
950         body = (uint8_t *)state->vector[2].iov_base;
951
952         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
953         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
954         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
955         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
956         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(reqhdr, SMB2_HDR_OPCODE));
957
958         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
959         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
960         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
961         SBVAL(hdr, SMB2_HDR_PID, async_id);
962         SBVAL(hdr, SMB2_HDR_SESSION_ID,
963                 BVAL(reqhdr, SMB2_HDR_SESSION_ID));
964         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
965
966         SSVAL(body, 0x00, 0x08 + 1);
967
968         SCVAL(body, 0x02, 0);
969         SCVAL(body, 0x03, 0);
970         SIVAL(body, 0x04, 0);
971         /* Match W2K8R2... */
972         SCVAL(body, 0x08, 0x21);
973
974         /* Ensure we correctly go through crediting. Grant
975            the credits now, and zero credits on the final
976            response. */
977         smb2_set_operation_credit(req->sconn,
978                         &req->in.vector[i],
979                         &state->vector[1]);
980
981         if (req->do_signing) {
982                 status = smb2_signing_sign_pdu(req->session->session_key,
983                                         &state->vector[1], 2);
984                 if (!NT_STATUS_IS_OK(status)) {
985                         return status;
986                 }
987         }
988
989         subreq = tstream_writev_queue_send(state,
990                                         req->sconn->smb2.event_ctx,
991                                         req->sconn->smb2.stream,
992                                         req->sconn->smb2.send_queue,
993                                         state->vector,
994                                         3);
995
996         if (subreq == NULL) {
997                 return NT_STATUS_NO_MEMORY;
998         }
999
1000         tevent_req_set_callback(subreq,
1001                         smbd_smb2_request_pending_writev_done,
1002                         state);
1003
1004         /* Note we're going async with this request. */
1005         req->async = true;
1006
1007   ipc_out:
1008
1009         /*
1010          * Now manipulate req so that the outstanding async request
1011          * is the only one left in the struct smbd_smb2_request.
1012          */
1013
1014         if (req->current_idx == 1) {
1015                 /* There was only one. */
1016                 goto out;
1017         }
1018
1019         /* Re-arrange the in.vectors. */
1020         req->in.vector[1] = req->in.vector[i];
1021         req->in.vector[2] = req->in.vector[i+1];
1022         req->in.vector[3] = req->in.vector[i+2];
1023         req->in.vector_count = 4;
1024         /* Reset the new in size. */
1025         smb2_setup_nbt_length(req->in.vector, 4);
1026
1027         /* Now recreate the out.vectors. */
1028         outvec = talloc_zero_array(req, struct iovec, 4);
1029         if (!outvec) {
1030                 return NT_STATUS_NO_MEMORY;
1031         }
1032
1033         /* 0 is always boilerplate and must
1034          * be of size 4 for the length field. */
1035
1036         outvec[0].iov_base = req->out.nbt_hdr;
1037         outvec[0].iov_len = 4;
1038         SIVAL(req->out.nbt_hdr, 0, 0);
1039
1040         if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
1041                 return NT_STATUS_NO_MEMORY;
1042         }
1043
1044         TALLOC_FREE(req->out.vector);
1045
1046         req->out.vector = outvec;
1047
1048         req->current_idx = 1;
1049         req->out.vector_count = 4;
1050
1051   out:
1052
1053         smb2_setup_nbt_length(req->out.vector,
1054                 req->out.vector_count);
1055
1056         if (req->async) {
1057                 /* Ensure our final reply matches the interim one. */
1058                 reqhdr = (uint8_t *)req->out.vector[1].iov_base;
1059                 SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1060                 SBVAL(reqhdr, SMB2_HDR_PID, async_id);
1061
1062                 {
1063                         const uint8_t *inhdr =
1064                                 (const uint8_t *)req->in.vector[1].iov_base;
1065                         DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1066                                 "going async\n",
1067                                 smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1068                                 (unsigned long long)async_id ));
1069                 }
1070         }
1071
1072         return NT_STATUS_OK;
1073 }
1074
1075 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1076 {
1077         struct smbd_server_connection *sconn = req->sconn;
1078         struct smbd_smb2_request *cur;
1079         const uint8_t *inhdr;
1080         int i = req->current_idx;
1081         uint32_t flags;
1082         uint64_t search_message_id;
1083         uint64_t search_async_id;
1084         uint64_t found_id;
1085
1086         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1087
1088         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1089         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1090         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1091
1092         /*
1093          * we don't need the request anymore
1094          * cancel requests never have a response
1095          */
1096         DLIST_REMOVE(req->sconn->smb2.requests, req);
1097         TALLOC_FREE(req);
1098
1099         for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1100                 const uint8_t *outhdr;
1101                 uint64_t message_id;
1102                 uint64_t async_id;
1103
1104                 i = cur->current_idx;
1105
1106                 outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
1107
1108                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1109                 async_id = BVAL(outhdr, SMB2_HDR_PID);
1110
1111                 if (flags & SMB2_HDR_FLAG_ASYNC) {
1112                         if (search_async_id == async_id) {
1113                                 found_id = async_id;
1114                                 break;
1115                         }
1116                 } else {
1117                         if (search_message_id == message_id) {
1118                                 found_id = message_id;
1119                                 break;
1120                         }
1121                 }
1122         }
1123
1124         if (cur && cur->subreq) {
1125                 inhdr = (const uint8_t *)cur->in.vector[i].iov_base;
1126                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1127                         "cancel opcode[%s] mid %llu\n",
1128                         smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
1129                         (unsigned long long)found_id ));
1130                 tevent_req_cancel(cur->subreq);
1131         }
1132
1133         return NT_STATUS_OK;
1134 }
1135
1136 /*************************************************************
1137  Ensure an incoming tid is a valid one for us to access.
1138  Change to the associated uid credentials and chdir to the
1139  valid tid directory.
1140 *************************************************************/
1141
1142 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1143 {
1144         const uint8_t *inhdr;
1145         int i = req->current_idx;
1146         uint32_t in_flags;
1147         uint32_t in_tid;
1148         void *p;
1149         struct smbd_smb2_tcon *tcon;
1150
1151         req->tcon = NULL;
1152
1153         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1154
1155         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1156         in_tid = IVAL(inhdr, SMB2_HDR_TID);
1157
1158         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1159                 in_tid = req->last_tid;
1160         }
1161
1162         /* lookup an existing session */
1163         p = idr_find(req->session->tcons.idtree, in_tid);
1164         if (p == NULL) {
1165                 return NT_STATUS_NETWORK_NAME_DELETED;
1166         }
1167         tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
1168
1169         if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
1170                 return NT_STATUS_ACCESS_DENIED;
1171         }
1172
1173         /* should we pass FLAG_CASELESS_PATHNAMES here? */
1174         if (!set_current_service(tcon->compat_conn, 0, true)) {
1175                 return NT_STATUS_ACCESS_DENIED;
1176         }
1177
1178         req->tcon = tcon;
1179         req->last_tid = in_tid;
1180
1181         return NT_STATUS_OK;
1182 }
1183
1184 /*************************************************************
1185  Ensure an incoming session_id is a valid one for us to access.
1186 *************************************************************/
1187
1188 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1189 {
1190         const uint8_t *inhdr;
1191         int i = req->current_idx;
1192         uint32_t in_flags;
1193         uint64_t in_session_id;
1194         void *p;
1195         struct smbd_smb2_session *session;
1196
1197         req->session = NULL;
1198         req->tcon = NULL;
1199
1200         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1201
1202         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1203         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1204
1205         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1206                 in_session_id = req->last_session_id;
1207         }
1208
1209         /* lookup an existing session */
1210         p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1211         if (p == NULL) {
1212                 return NT_STATUS_USER_SESSION_DELETED;
1213         }
1214         session = talloc_get_type_abort(p, struct smbd_smb2_session);
1215
1216         if (!NT_STATUS_IS_OK(session->status)) {
1217                 return NT_STATUS_ACCESS_DENIED;
1218         }
1219
1220         set_current_user_info(session->session_info->unix_info->sanitized_username,
1221                               session->session_info->unix_info->unix_name,
1222                               session->session_info->info->domain_name);
1223
1224         req->session = session;
1225         req->last_session_id = in_session_id;
1226
1227         return NT_STATUS_OK;
1228 }
1229
1230 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1231                                         size_t expected_body_size)
1232 {
1233         const uint8_t *inhdr;
1234         uint16_t opcode;
1235         const uint8_t *inbody;
1236         int i = req->current_idx;
1237         size_t body_size;
1238         size_t min_dyn_size = expected_body_size & 0x00000001;
1239
1240         /*
1241          * The following should be checked already.
1242          */
1243         if ((i+2) > req->in.vector_count) {
1244                 return NT_STATUS_INTERNAL_ERROR;
1245         }
1246         if (req->in.vector[i+0].iov_len != SMB2_HDR_BODY) {
1247                 return NT_STATUS_INTERNAL_ERROR;
1248         }
1249         if (req->in.vector[i+1].iov_len < 2) {
1250                 return NT_STATUS_INTERNAL_ERROR;
1251         }
1252
1253         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
1254         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1255
1256         switch (opcode) {
1257         case SMB2_OP_IOCTL:
1258         case SMB2_OP_GETINFO:
1259                 min_dyn_size = 0;
1260                 break;
1261         }
1262
1263         /*
1264          * Now check the expected body size,
1265          * where the last byte might be in the
1266          * dynnamic section..
1267          */
1268         if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1269                 return NT_STATUS_INVALID_PARAMETER;
1270         }
1271         if (req->in.vector[i+2].iov_len < min_dyn_size) {
1272                 return NT_STATUS_INVALID_PARAMETER;
1273         }
1274
1275         inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1276
1277         body_size = SVAL(inbody, 0x00);
1278         if (body_size != expected_body_size) {
1279                 return NT_STATUS_INVALID_PARAMETER;
1280         }
1281
1282         return NT_STATUS_OK;
1283 }
1284
1285 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1286 {
1287         const uint8_t *inhdr;
1288         int i = req->current_idx;
1289         uint16_t opcode;
1290         uint32_t flags;
1291         uint64_t mid;
1292         NTSTATUS status;
1293         NTSTATUS session_status;
1294         uint32_t allowed_flags;
1295         NTSTATUS return_value;
1296
1297         inhdr = (const uint8_t *)req->in.vector[i].iov_base;
1298
1299         /* TODO: verify more things */
1300
1301         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1302         opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
1303         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1304         DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1305                 smb2_opcode_name(opcode),
1306                 (unsigned long long)mid));
1307
1308         if (get_Protocol() >= PROTOCOL_SMB2_02) {
1309                 /*
1310                  * once the protocol is negotiated
1311                  * SMB2_OP_NEGPROT is not allowed anymore
1312                  */
1313                 if (opcode == SMB2_OP_NEGPROT) {
1314                         /* drop the connection */
1315                         return NT_STATUS_INVALID_PARAMETER;
1316                 }
1317         } else {
1318                 /*
1319                  * if the protocol is not negotiated yet
1320                  * only SMB2_OP_NEGPROT is allowed.
1321                  */
1322                 if (opcode != SMB2_OP_NEGPROT) {
1323                         /* drop the connection */
1324                         return NT_STATUS_INVALID_PARAMETER;
1325                 }
1326         }
1327
1328         allowed_flags = SMB2_HDR_FLAG_CHAINED |
1329                         SMB2_HDR_FLAG_SIGNED |
1330                         SMB2_HDR_FLAG_DFS;
1331         if (opcode == SMB2_OP_CANCEL) {
1332                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1333         }
1334         if ((flags & ~allowed_flags) != 0) {
1335                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1336         }
1337
1338         /*
1339          * Check if the client provided a valid session id,
1340          * if so smbd_smb2_request_check_session() calls
1341          * set_current_user_info().
1342          *
1343          * As some command don't require a valid session id
1344          * we defer the check of the session_status
1345          */
1346         session_status = smbd_smb2_request_check_session(req);
1347
1348         req->do_signing = false;
1349         if (flags & SMB2_HDR_FLAG_SIGNED) {
1350                 if (!NT_STATUS_IS_OK(session_status)) {
1351                         return smbd_smb2_request_error(req, session_status);
1352                 }
1353
1354                 req->do_signing = true;
1355                 status = smb2_signing_check_pdu(req->session->session_key,
1356                                                 &req->in.vector[i], 3);
1357                 if (!NT_STATUS_IS_OK(status)) {
1358                         return smbd_smb2_request_error(req, status);
1359                 }
1360         } else if (opcode == SMB2_OP_CANCEL) {
1361                 /* Cancel requests are allowed to skip the signing */
1362         } else if (req->session && req->session->do_signing) {
1363                 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
1364         }
1365
1366         if (flags & SMB2_HDR_FLAG_CHAINED) {
1367                 /*
1368                  * This check is mostly for giving the correct error code
1369                  * for compounded requests.
1370                  *
1371                  * TODO: we may need to move this after the session
1372                  *       and tcon checks.
1373                  */
1374                 if (!NT_STATUS_IS_OK(req->next_status)) {
1375                         return smbd_smb2_request_error(req, req->next_status);
1376                 }
1377         } else {
1378                 req->compat_chain_fsp = NULL;
1379         }
1380
1381         if (req->compound_related) {
1382                 req->sconn->smb2.compound_related_in_progress = true;
1383         }
1384
1385         switch (opcode) {
1386         case SMB2_OP_NEGPROT:
1387                 /* This call needs to be run as root */
1388                 change_to_root_user();
1389
1390                 {
1391                         START_PROFILE(smb2_negprot);
1392                         return_value = smbd_smb2_request_process_negprot(req);
1393                         END_PROFILE(smb2_negprot);
1394                 }
1395                 break;
1396
1397         case SMB2_OP_SESSSETUP:
1398                 /* This call needs to be run as root */
1399                 change_to_root_user();
1400
1401                 {
1402                         START_PROFILE(smb2_sesssetup);
1403                         return_value = smbd_smb2_request_process_sesssetup(req);
1404                         END_PROFILE(smb2_sesssetup);
1405                 }
1406                 break;
1407
1408         case SMB2_OP_LOGOFF:
1409                 if (!NT_STATUS_IS_OK(session_status)) {
1410                         return_value = smbd_smb2_request_error(req, session_status);
1411                         break;
1412                 }
1413
1414                 /* This call needs to be run as root */
1415                 change_to_root_user();
1416
1417                 {
1418                         START_PROFILE(smb2_logoff);
1419                         return_value = smbd_smb2_request_process_logoff(req);
1420                         END_PROFILE(smb2_logoff);
1421                 }
1422                 break;
1423
1424         case SMB2_OP_TCON:
1425                 if (!NT_STATUS_IS_OK(session_status)) {
1426                         return_value = smbd_smb2_request_error(req, session_status);
1427                         break;
1428                 }
1429
1430                 /*
1431                  * This call needs to be run as root.
1432                  *
1433                  * smbd_smb2_request_process_tcon()
1434                  * calls make_connection_snum(), which will call
1435                  * change_to_user(), when needed.
1436                  */
1437                 change_to_root_user();
1438
1439                 {
1440                         START_PROFILE(smb2_tcon);
1441                         return_value = smbd_smb2_request_process_tcon(req);
1442                         END_PROFILE(smb2_tcon);
1443                 }
1444                 break;
1445
1446         case SMB2_OP_TDIS:
1447                 if (!NT_STATUS_IS_OK(session_status)) {
1448                         return_value = smbd_smb2_request_error(req, session_status);
1449                         break;
1450                 }
1451                 /*
1452                  * This call needs to be run as user.
1453                  *
1454                  * smbd_smb2_request_check_tcon()
1455                  * calls change_to_user() on success.
1456                  */
1457                 status = smbd_smb2_request_check_tcon(req);
1458                 if (!NT_STATUS_IS_OK(status)) {
1459                         return_value = smbd_smb2_request_error(req, status);
1460                         break;
1461                 }
1462                 /* This call needs to be run as root */
1463                 change_to_root_user();
1464
1465
1466                 {
1467                         START_PROFILE(smb2_tdis);
1468                         return_value = smbd_smb2_request_process_tdis(req);
1469                         END_PROFILE(smb2_tdis);
1470                 }
1471                 break;
1472
1473         case SMB2_OP_CREATE:
1474                 if (!NT_STATUS_IS_OK(session_status)) {
1475                         return_value = smbd_smb2_request_error(req, session_status);
1476                         break;
1477                 }
1478                 /*
1479                  * This call needs to be run as user.
1480                  *
1481                  * smbd_smb2_request_check_tcon()
1482                  * calls change_to_user() on success.
1483                  */
1484                 status = smbd_smb2_request_check_tcon(req);
1485                 if (!NT_STATUS_IS_OK(status)) {
1486                         return_value = smbd_smb2_request_error(req, status);
1487                         break;
1488                 }
1489
1490                 {
1491                         START_PROFILE(smb2_create);
1492                         return_value = smbd_smb2_request_process_create(req);
1493                         END_PROFILE(smb2_create);
1494                 }
1495                 break;
1496
1497         case SMB2_OP_CLOSE:
1498                 if (!NT_STATUS_IS_OK(session_status)) {
1499                         return_value = smbd_smb2_request_error(req, session_status);
1500                         break;
1501                 }
1502                 /*
1503                  * This call needs to be run as user.
1504                  *
1505                  * smbd_smb2_request_check_tcon()
1506                  * calls change_to_user() on success.
1507                  */
1508                 status = smbd_smb2_request_check_tcon(req);
1509                 if (!NT_STATUS_IS_OK(status)) {
1510                         return_value = smbd_smb2_request_error(req, status);
1511                         break;
1512                 }
1513
1514                 {
1515                         START_PROFILE(smb2_close);
1516                         return_value = smbd_smb2_request_process_close(req);
1517                         END_PROFILE(smb2_close);
1518                 }
1519                 break;
1520
1521         case SMB2_OP_FLUSH:
1522                 if (!NT_STATUS_IS_OK(session_status)) {
1523                         return_value = smbd_smb2_request_error(req, session_status);
1524                         break;
1525                 }
1526                 /*
1527                  * This call needs to be run as user.
1528                  *
1529                  * smbd_smb2_request_check_tcon()
1530                  * calls change_to_user() on success.
1531                  */
1532                 status = smbd_smb2_request_check_tcon(req);
1533                 if (!NT_STATUS_IS_OK(status)) {
1534                         return_value = smbd_smb2_request_error(req, status);
1535                         break;
1536                 }
1537
1538                 {
1539                         START_PROFILE(smb2_flush);
1540                         return_value = smbd_smb2_request_process_flush(req);
1541                         END_PROFILE(smb2_flush);
1542                 }
1543                 break;
1544
1545         case SMB2_OP_READ:
1546                 if (!NT_STATUS_IS_OK(session_status)) {
1547                         return_value = smbd_smb2_request_error(req, session_status);
1548                         break;
1549                 }
1550                 /*
1551                  * This call needs to be run as user.
1552                  *
1553                  * smbd_smb2_request_check_tcon()
1554                  * calls change_to_user() on success.
1555                  */
1556                 status = smbd_smb2_request_check_tcon(req);
1557                 if (!NT_STATUS_IS_OK(status)) {
1558                         return_value = smbd_smb2_request_error(req, status);
1559                         break;
1560                 }
1561
1562                 {
1563                         START_PROFILE(smb2_read);
1564                         return_value = smbd_smb2_request_process_read(req);
1565                         END_PROFILE(smb2_read);
1566                 }
1567                 break;
1568
1569         case SMB2_OP_WRITE:
1570                 if (!NT_STATUS_IS_OK(session_status)) {
1571                         return_value = smbd_smb2_request_error(req, session_status);
1572                         break;
1573                 }
1574                 /*
1575                  * This call needs to be run as user.
1576                  *
1577                  * smbd_smb2_request_check_tcon()
1578                  * calls change_to_user() on success.
1579                  */
1580                 status = smbd_smb2_request_check_tcon(req);
1581                 if (!NT_STATUS_IS_OK(status)) {
1582                         return_value = smbd_smb2_request_error(req, status);
1583                         break;
1584                 }
1585
1586                 {
1587                         START_PROFILE(smb2_write);
1588                         return_value = smbd_smb2_request_process_write(req);
1589                         END_PROFILE(smb2_write);
1590                 }
1591                 break;
1592
1593         case SMB2_OP_LOCK:
1594                 if (!NT_STATUS_IS_OK(session_status)) {
1595                         /* Too ugly to live ? JRA. */
1596                         if (NT_STATUS_EQUAL(session_status,NT_STATUS_USER_SESSION_DELETED)) {
1597                                 session_status = NT_STATUS_FILE_CLOSED;
1598                         }
1599                         return_value = smbd_smb2_request_error(req, session_status);
1600                         break;
1601                 }
1602                 /*
1603                  * This call needs to be run as user.
1604                  *
1605                  * smbd_smb2_request_check_tcon()
1606                  * calls change_to_user() on success.
1607                  */
1608                 status = smbd_smb2_request_check_tcon(req);
1609                 if (!NT_STATUS_IS_OK(status)) {
1610                         /* Too ugly to live ? JRA. */
1611                         if (NT_STATUS_EQUAL(status,NT_STATUS_NETWORK_NAME_DELETED)) {
1612                                 status = NT_STATUS_FILE_CLOSED;
1613                         }
1614                         return_value = smbd_smb2_request_error(req, status);
1615                         break;
1616                 }
1617
1618                 {
1619                         START_PROFILE(smb2_lock);
1620                         return_value = smbd_smb2_request_process_lock(req);
1621                         END_PROFILE(smb2_lock);
1622                 }
1623                 break;
1624
1625         case SMB2_OP_IOCTL:
1626                 if (!NT_STATUS_IS_OK(session_status)) {
1627                         return_value = smbd_smb2_request_error(req, session_status);
1628                         break;
1629                 }
1630                 /*
1631                  * This call needs to be run as user.
1632                  *
1633                  * smbd_smb2_request_check_tcon()
1634                  * calls change_to_user() on success.
1635                  */
1636                 status = smbd_smb2_request_check_tcon(req);
1637                 if (!NT_STATUS_IS_OK(status)) {
1638                         return_value = smbd_smb2_request_error(req, status);
1639                         break;
1640                 }
1641
1642                 {
1643                         START_PROFILE(smb2_ioctl);
1644                         return_value = smbd_smb2_request_process_ioctl(req);
1645                         END_PROFILE(smb2_ioctl);
1646                 }
1647                 break;
1648
1649         case SMB2_OP_CANCEL:
1650                 /*
1651                  * This call needs to be run as root
1652                  *
1653                  * That is what we also do in the SMB1 case.
1654                  */
1655                 change_to_root_user();
1656
1657                 {
1658                         START_PROFILE(smb2_cancel);
1659                         return_value = smbd_smb2_request_process_cancel(req);
1660                         END_PROFILE(smb2_cancel);
1661                 }
1662                 break;
1663
1664         case SMB2_OP_KEEPALIVE:
1665                 /* This call needs to be run as root */
1666                 change_to_root_user();
1667
1668                 {
1669                         START_PROFILE(smb2_keepalive);
1670                         return_value = smbd_smb2_request_process_keepalive(req);
1671                         END_PROFILE(smb2_keepalive);
1672                 }
1673                 break;
1674
1675         case SMB2_OP_FIND:
1676                 if (!NT_STATUS_IS_OK(session_status)) {
1677                         return_value = smbd_smb2_request_error(req, session_status);
1678                         break;
1679                 }
1680                 /*
1681                  * This call needs to be run as user.
1682                  *
1683                  * smbd_smb2_request_check_tcon()
1684                  * calls change_to_user() on success.
1685                  */
1686                 status = smbd_smb2_request_check_tcon(req);
1687                 if (!NT_STATUS_IS_OK(status)) {
1688                         return_value = smbd_smb2_request_error(req, status);
1689                         break;
1690                 }
1691
1692                 {
1693                         START_PROFILE(smb2_find);
1694                         return_value = smbd_smb2_request_process_find(req);
1695                         END_PROFILE(smb2_find);
1696                 }
1697                 break;
1698
1699         case SMB2_OP_NOTIFY:
1700                 if (!NT_STATUS_IS_OK(session_status)) {
1701                         return_value = smbd_smb2_request_error(req, session_status);
1702                         break;
1703                 }
1704                 /*
1705                  * This call needs to be run as user.
1706                  *
1707                  * smbd_smb2_request_check_tcon()
1708                  * calls change_to_user() on success.
1709                  */
1710                 status = smbd_smb2_request_check_tcon(req);
1711                 if (!NT_STATUS_IS_OK(status)) {
1712                         return_value = smbd_smb2_request_error(req, status);
1713                         break;
1714                 }
1715
1716                 {
1717                         START_PROFILE(smb2_notify);
1718                         return_value = smbd_smb2_request_process_notify(req);
1719                         END_PROFILE(smb2_notify);
1720                 }
1721                 break;
1722
1723         case SMB2_OP_GETINFO:
1724                 if (!NT_STATUS_IS_OK(session_status)) {
1725                         return_value = smbd_smb2_request_error(req, session_status);
1726                         break;
1727                 }
1728                 /*
1729                  * This call needs to be run as user.
1730                  *
1731                  * smbd_smb2_request_check_tcon()
1732                  * calls change_to_user() on success.
1733                  */
1734                 status = smbd_smb2_request_check_tcon(req);
1735                 if (!NT_STATUS_IS_OK(status)) {
1736                         return_value = smbd_smb2_request_error(req, status);
1737                         break;
1738                 }
1739
1740                 {
1741                         START_PROFILE(smb2_getinfo);
1742                         return_value = smbd_smb2_request_process_getinfo(req);
1743                         END_PROFILE(smb2_getinfo);
1744                 }
1745                 break;
1746
1747         case SMB2_OP_SETINFO:
1748                 if (!NT_STATUS_IS_OK(session_status)) {
1749                         return_value = smbd_smb2_request_error(req, session_status);
1750                         break;
1751                 }
1752                 /*
1753                  * This call needs to be run as user.
1754                  *
1755                  * smbd_smb2_request_check_tcon()
1756                  * calls change_to_user() on success.
1757                  */
1758                 status = smbd_smb2_request_check_tcon(req);
1759                 if (!NT_STATUS_IS_OK(status)) {
1760                         return_value = smbd_smb2_request_error(req, status);
1761                         break;
1762                 }
1763
1764                 {
1765                         START_PROFILE(smb2_setinfo);
1766                         return_value = smbd_smb2_request_process_setinfo(req);
1767                         END_PROFILE(smb2_setinfo);
1768                 }
1769                 break;
1770
1771         case SMB2_OP_BREAK:
1772                 if (!NT_STATUS_IS_OK(session_status)) {
1773                         return_value = smbd_smb2_request_error(req, session_status);
1774                         break;
1775                 }
1776                 /*
1777                  * This call needs to be run as user.
1778                  *
1779                  * smbd_smb2_request_check_tcon()
1780                  * calls change_to_user() on success.
1781                  */
1782                 status = smbd_smb2_request_check_tcon(req);
1783                 if (!NT_STATUS_IS_OK(status)) {
1784                         return_value = smbd_smb2_request_error(req, status);
1785                         break;
1786                 }
1787
1788                 {
1789                         START_PROFILE(smb2_break);
1790                         return_value = smbd_smb2_request_process_break(req);
1791                         END_PROFILE(smb2_break);
1792                 }
1793                 break;
1794
1795         default:
1796                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1797                 break;
1798         }
1799         return return_value;
1800 }
1801
1802 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
1803 {
1804         struct tevent_req *subreq;
1805         int i = req->current_idx;
1806
1807         req->subreq = NULL;
1808
1809         req->current_idx += 3;
1810
1811         if (req->current_idx < req->out.vector_count) {
1812                 /*
1813                  * We must process the remaining compound
1814                  * SMB2 requests before any new incoming SMB2
1815                  * requests. This is because incoming SMB2
1816                  * requests may include a cancel for a
1817                  * compound request we haven't processed
1818                  * yet.
1819                  */
1820                 struct tevent_immediate *im = tevent_create_immediate(req);
1821                 if (!im) {
1822                         return NT_STATUS_NO_MEMORY;
1823                 }
1824                 tevent_schedule_immediate(im,
1825                                         req->sconn->smb2.event_ctx,
1826                                         smbd_smb2_request_dispatch_immediate,
1827                                         req);
1828                 return NT_STATUS_OK;
1829         }
1830
1831         if (req->compound_related) {
1832                 req->sconn->smb2.compound_related_in_progress = false;
1833         }
1834
1835         smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1836
1837         /* Set credit for this operation (zero credits if this
1838            is a final reply for an async operation). */
1839         smb2_set_operation_credit(req->sconn,
1840                         &req->in.vector[i],
1841                         &req->out.vector[i]);
1842
1843         if (req->do_signing) {
1844                 NTSTATUS status;
1845                 status = smb2_signing_sign_pdu(req->session->session_key,
1846                                                &req->out.vector[i], 3);
1847                 if (!NT_STATUS_IS_OK(status)) {
1848                         return status;
1849                 }
1850         }
1851
1852         if (DEBUGLEVEL >= 10) {
1853                 dbgtext("smbd_smb2_request_reply: sending...\n");
1854                 print_req_vectors(req);
1855         }
1856
1857         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
1858         if (req->out.vector_count == 4 &&
1859                         req->out.vector[3].iov_base == NULL &&
1860                         req->out.vector[3].iov_len != 0) {
1861                 /* Dynamic part is NULL. Chop it off,
1862                    We're going to send it via sendfile. */
1863                 req->out.vector_count -= 1;
1864         }
1865
1866         subreq = tstream_writev_queue_send(req,
1867                                            req->sconn->smb2.event_ctx,
1868                                            req->sconn->smb2.stream,
1869                                            req->sconn->smb2.send_queue,
1870                                            req->out.vector,
1871                                            req->out.vector_count);
1872         if (subreq == NULL) {
1873                 return NT_STATUS_NO_MEMORY;
1874         }
1875         tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
1876         /*
1877          * We're done with this request -
1878          * move it off the "being processed" queue.
1879          */
1880         DLIST_REMOVE(req->sconn->smb2.requests, req);
1881
1882         return NT_STATUS_OK;
1883 }
1884
1885 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
1886
1887 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
1888                                         struct tevent_immediate *im,
1889                                         void *private_data)
1890 {
1891         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
1892                                         struct smbd_smb2_request);
1893         struct smbd_server_connection *sconn = req->sconn;
1894         NTSTATUS status;
1895
1896         TALLOC_FREE(im);
1897
1898         if (DEBUGLEVEL >= 10) {
1899                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
1900                         req->current_idx, req->in.vector_count));
1901                 print_req_vectors(req);
1902         }
1903
1904         status = smbd_smb2_request_dispatch(req);
1905         if (!NT_STATUS_IS_OK(status)) {
1906                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1907                 return;
1908         }
1909
1910         status = smbd_smb2_request_next_incoming(sconn);
1911         if (!NT_STATUS_IS_OK(status)) {
1912                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1913                 return;
1914         }
1915 }
1916
1917 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
1918 {
1919         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
1920                                         struct smbd_smb2_request);
1921         struct smbd_server_connection *sconn = req->sconn;
1922         int ret;
1923         int sys_errno;
1924         NTSTATUS status;
1925
1926         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1927         TALLOC_FREE(subreq);
1928         TALLOC_FREE(req);
1929         if (ret == -1) {
1930                 status = map_nt_error_from_unix(sys_errno);
1931                 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
1932                         nt_errstr(status)));
1933                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1934                 return;
1935         }
1936
1937         status = smbd_smb2_request_next_incoming(sconn);
1938         if (!NT_STATUS_IS_OK(status)) {
1939                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1940                 return;
1941         }
1942 }
1943
1944 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
1945                                    NTSTATUS status,
1946                                    DATA_BLOB body, DATA_BLOB *dyn,
1947                                    const char *location)
1948 {
1949         uint8_t *outhdr;
1950         int i = req->current_idx;
1951         uint32_t next_command_ofs;
1952
1953         DEBUG(10,("smbd_smb2_request_done_ex: "
1954                   "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
1955                   i, nt_errstr(status), (unsigned int)body.length,
1956                   dyn ? "yes": "no",
1957                   (unsigned int)(dyn ? dyn->length : 0),
1958                   location));
1959
1960         if (body.length < 2) {
1961                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1962         }
1963
1964         if ((body.length % 2) != 0) {
1965                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
1966         }
1967
1968         outhdr = (uint8_t *)req->out.vector[i].iov_base;
1969
1970         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
1971         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
1972
1973         req->out.vector[i+1].iov_base = (void *)body.data;
1974         req->out.vector[i+1].iov_len = body.length;
1975
1976         if (dyn) {
1977                 req->out.vector[i+2].iov_base   = (void *)dyn->data;
1978                 req->out.vector[i+2].iov_len    = dyn->length;
1979         } else {
1980                 req->out.vector[i+2].iov_base = NULL;
1981                 req->out.vector[i+2].iov_len = 0;
1982         }
1983
1984         /* see if we need to recalculate the offset to the next response */
1985         if (next_command_ofs > 0) {
1986                 next_command_ofs  = SMB2_HDR_BODY;
1987                 next_command_ofs += req->out.vector[i+1].iov_len;
1988                 next_command_ofs += req->out.vector[i+2].iov_len;
1989         }
1990
1991         if ((next_command_ofs % 8) != 0) {
1992                 size_t pad_size = 8 - (next_command_ofs % 8);
1993                 if (req->out.vector[i+2].iov_len == 0) {
1994                         /*
1995                          * if the dyn buffer is empty
1996                          * we can use it to add padding
1997                          */
1998                         uint8_t *pad;
1999
2000                         pad = talloc_zero_array(req->out.vector,
2001                                                 uint8_t, pad_size);
2002                         if (pad == NULL) {
2003                                 return smbd_smb2_request_error(req,
2004                                                 NT_STATUS_NO_MEMORY);
2005                         }
2006
2007                         req->out.vector[i+2].iov_base = (void *)pad;
2008                         req->out.vector[i+2].iov_len = pad_size;
2009                 } else {
2010                         /*
2011                          * For now we copy the dynamic buffer
2012                          * and add the padding to the new buffer
2013                          */
2014                         size_t old_size;
2015                         uint8_t *old_dyn;
2016                         size_t new_size;
2017                         uint8_t *new_dyn;
2018
2019                         old_size = req->out.vector[i+2].iov_len;
2020                         old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
2021
2022                         new_size = old_size + pad_size;
2023                         new_dyn = talloc_zero_array(req->out.vector,
2024                                                uint8_t, new_size);
2025                         if (new_dyn == NULL) {
2026                                 return smbd_smb2_request_error(req,
2027                                                 NT_STATUS_NO_MEMORY);
2028                         }
2029
2030                         memcpy(new_dyn, old_dyn, old_size);
2031                         memset(new_dyn + old_size, 0, pad_size);
2032
2033                         req->out.vector[i+2].iov_base = (void *)new_dyn;
2034                         req->out.vector[i+2].iov_len = new_size;
2035                 }
2036                 next_command_ofs += pad_size;
2037         }
2038
2039         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2040
2041         return smbd_smb2_request_reply(req);
2042 }
2043
2044 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2045                                     NTSTATUS status,
2046                                     DATA_BLOB *info,
2047                                     const char *location)
2048 {
2049         DATA_BLOB body;
2050         int i = req->current_idx;
2051         uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base;
2052
2053         DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2054                   i, nt_errstr(status), info ? " +info" : "",
2055                   location));
2056
2057         body.data = outhdr + SMB2_HDR_BODY;
2058         body.length = 8;
2059         SSVAL(body.data, 0, 9);
2060
2061         if (info) {
2062                 SIVAL(body.data, 0x04, info->length);
2063         } else {
2064                 /* Allocated size of req->out.vector[i].iov_base
2065                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2066                  * 1 byte without having to do an alloc.
2067                  */
2068                 info = talloc_zero_array(req->out.vector,
2069                                         DATA_BLOB,
2070                                         1);
2071                 if (!info) {
2072                         return NT_STATUS_NO_MEMORY;
2073                 }
2074                 info->data = ((uint8_t *)outhdr) +
2075                         OUTVEC_ALLOC_SIZE - 1;
2076                 info->length = 1;
2077                 SCVAL(info->data, 0, 0);
2078         }
2079
2080         /*
2081          * if a request fails, all other remaining
2082          * compounded requests should fail too
2083          */
2084         req->next_status = NT_STATUS_INVALID_PARAMETER;
2085
2086         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2087 }
2088
2089
2090 struct smbd_smb2_send_oplock_break_state {
2091         struct smbd_server_connection *sconn;
2092         uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
2093         struct iovec vector;
2094 };
2095
2096 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2097
2098 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2099                                      uint64_t file_id_persistent,
2100                                      uint64_t file_id_volatile,
2101                                      uint8_t oplock_level)
2102 {
2103         struct smbd_smb2_send_oplock_break_state *state;
2104         struct tevent_req *subreq;
2105         uint8_t *hdr;
2106         uint8_t *body;
2107
2108         state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2109         if (state == NULL) {
2110                 return NT_STATUS_NO_MEMORY;
2111         }
2112         state->sconn = sconn;
2113
2114         state->vector.iov_base = (void *)state->buf;
2115         state->vector.iov_len = sizeof(state->buf);
2116
2117         _smb2_setlen(state->buf, sizeof(state->buf) - 4);
2118         hdr = state->buf + 4;
2119         body = hdr + SMB2_HDR_BODY;
2120
2121         SIVAL(hdr, 0,                           SMB2_MAGIC);
2122         SSVAL(hdr, SMB2_HDR_LENGTH,             SMB2_HDR_BODY);
2123         SSVAL(hdr, SMB2_HDR_EPOCH,              0);
2124         SIVAL(hdr, SMB2_HDR_STATUS,             0);
2125         SSVAL(hdr, SMB2_HDR_OPCODE,             SMB2_OP_BREAK);
2126         SSVAL(hdr, SMB2_HDR_CREDIT,             0);
2127         SIVAL(hdr, SMB2_HDR_FLAGS,              SMB2_HDR_FLAG_REDIRECT);
2128         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND,       0);
2129         SBVAL(hdr, SMB2_HDR_MESSAGE_ID,         UINT64_MAX);
2130         SIVAL(hdr, SMB2_HDR_PID,                0);
2131         SIVAL(hdr, SMB2_HDR_TID,                0);
2132         SBVAL(hdr, SMB2_HDR_SESSION_ID,         0);
2133         memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2134
2135         SSVAL(body, 0x00, 0x18);
2136
2137         SCVAL(body, 0x02, oplock_level);
2138         SCVAL(body, 0x03, 0);           /* reserved */
2139         SIVAL(body, 0x04, 0);           /* reserved */
2140         SBVAL(body, 0x08, file_id_persistent);
2141         SBVAL(body, 0x10, file_id_volatile);
2142
2143         subreq = tstream_writev_queue_send(state,
2144                                            sconn->smb2.event_ctx,
2145                                            sconn->smb2.stream,
2146                                            sconn->smb2.send_queue,
2147                                            &state->vector, 1);
2148         if (subreq == NULL) {
2149                 return NT_STATUS_NO_MEMORY;
2150         }
2151         tevent_req_set_callback(subreq,
2152                                 smbd_smb2_oplock_break_writev_done,
2153                                 state);
2154
2155         return NT_STATUS_OK;
2156 }
2157
2158 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2159 {
2160         struct smbd_smb2_send_oplock_break_state *state =
2161                 tevent_req_callback_data(subreq,
2162                 struct smbd_smb2_send_oplock_break_state);
2163         struct smbd_server_connection *sconn = state->sconn;
2164         int ret;
2165         int sys_errno;
2166
2167         ret = tstream_writev_queue_recv(subreq, &sys_errno);
2168         TALLOC_FREE(subreq);
2169         if (ret == -1) {
2170                 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2171                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2172                 return;
2173         }
2174
2175         TALLOC_FREE(state);
2176 }
2177
2178 struct smbd_smb2_request_read_state {
2179         size_t missing;
2180         bool asked_for_header;
2181         struct smbd_smb2_request *smb2_req;
2182 };
2183
2184 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2185                                          void *private_data,
2186                                          TALLOC_CTX *mem_ctx,
2187                                          struct iovec **_vector,
2188                                          size_t *_count);
2189 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2190
2191 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2192                                         struct tevent_context *ev,
2193                                         struct smbd_server_connection *sconn)
2194 {
2195         struct tevent_req *req;
2196         struct smbd_smb2_request_read_state *state;
2197         struct tevent_req *subreq;
2198
2199         req = tevent_req_create(mem_ctx, &state,
2200                                 struct smbd_smb2_request_read_state);
2201         if (req == NULL) {
2202                 return NULL;
2203         }
2204         state->missing = 0;
2205         state->asked_for_header = false;
2206
2207         state->smb2_req = smbd_smb2_request_allocate(state);
2208         if (tevent_req_nomem(state->smb2_req, req)) {
2209                 return tevent_req_post(req, ev);
2210         }
2211         state->smb2_req->sconn = sconn;
2212
2213         subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
2214                                               sconn->smb2.recv_queue,
2215                                               smbd_smb2_request_next_vector,
2216                                               state);
2217         if (tevent_req_nomem(subreq, req)) {
2218                 return tevent_req_post(req, ev);
2219         }
2220         tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2221
2222         return req;
2223 }
2224
2225 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2226                                          void *private_data,
2227                                          TALLOC_CTX *mem_ctx,
2228                                          struct iovec **_vector,
2229                                          size_t *_count)
2230 {
2231         struct smbd_smb2_request_read_state *state =
2232                 talloc_get_type_abort(private_data,
2233                 struct smbd_smb2_request_read_state);
2234         struct smbd_smb2_request *req = state->smb2_req;
2235         struct iovec *vector;
2236         int idx = req->in.vector_count;
2237         size_t len = 0;
2238         uint8_t *buf = NULL;
2239
2240         if (req->in.vector_count == 0) {
2241                 /*
2242                  * first we need to get the NBT header
2243                  */
2244                 req->in.vector = talloc_array(req, struct iovec,
2245                                               req->in.vector_count + 1);
2246                 if (req->in.vector == NULL) {
2247                         return -1;
2248                 }
2249                 req->in.vector_count += 1;
2250
2251                 req->in.vector[idx].iov_base    = (void *)req->in.nbt_hdr;
2252                 req->in.vector[idx].iov_len     = 4;
2253
2254                 vector = talloc_array(mem_ctx, struct iovec, 1);
2255                 if (vector == NULL) {
2256                         return -1;
2257                 }
2258
2259                 vector[0] = req->in.vector[idx];
2260
2261                 *_vector = vector;
2262                 *_count = 1;
2263                 return 0;
2264         }
2265
2266         if (req->in.vector_count == 1) {
2267                 /*
2268                  * Now we analyze the NBT header
2269                  */
2270                 state->missing = smb2_len(req->in.vector[0].iov_base);
2271
2272                 if (state->missing == 0) {
2273                         /* if there're no remaining bytes, we're done */
2274                         *_vector = NULL;
2275                         *_count = 0;
2276                         return 0;
2277                 }
2278
2279                 req->in.vector = talloc_realloc(req, req->in.vector,
2280                                                 struct iovec,
2281                                                 req->in.vector_count + 1);
2282                 if (req->in.vector == NULL) {
2283                         return -1;
2284                 }
2285                 req->in.vector_count += 1;
2286
2287                 if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
2288                         /*
2289                          * it's a special NBT message,
2290                          * so get all remaining bytes
2291                          */
2292                         len = state->missing;
2293                 } else if (state->missing < (SMB2_HDR_BODY + 2)) {
2294                         /*
2295                          * it's an invalid message, just read what we can get
2296                          * and let the caller handle the error
2297                          */
2298                         len = state->missing;
2299                 } else {
2300                         /*
2301                          * We assume it's a SMB2 request,
2302                          * and we first get the header and the
2303                          * first 2 bytes (the struct size) of the body
2304                          */
2305                         len = SMB2_HDR_BODY + 2;
2306
2307                         state->asked_for_header = true;
2308                 }
2309
2310                 state->missing -= len;
2311
2312                 buf = talloc_array(req->in.vector, uint8_t, len);
2313                 if (buf == NULL) {
2314                         return -1;
2315                 }
2316
2317                 req->in.vector[idx].iov_base    = (void *)buf;
2318                 req->in.vector[idx].iov_len     = len;
2319
2320                 vector = talloc_array(mem_ctx, struct iovec, 1);
2321                 if (vector == NULL) {
2322                         return -1;
2323                 }
2324
2325                 vector[0] = req->in.vector[idx];
2326
2327                 *_vector = vector;
2328                 *_count = 1;
2329                 return 0;
2330         }
2331
2332         if (state->missing == 0) {
2333                 /* if there're no remaining bytes, we're done */
2334                 *_vector = NULL;
2335                 *_count = 0;
2336                 return 0;
2337         }
2338
2339         if (state->asked_for_header) {
2340                 const uint8_t *hdr;
2341                 size_t full_size;
2342                 size_t next_command_ofs;
2343                 size_t body_size;
2344                 uint8_t *body;
2345                 size_t dyn_size;
2346                 uint8_t *dyn;
2347                 bool invalid = false;
2348
2349                 state->asked_for_header = false;
2350
2351                 /*
2352                  * We got the SMB2 header and the first 2 bytes
2353                  * of the body. We fix the size to just the header
2354                  * and manually copy the 2 first bytes to the body section
2355                  */
2356                 req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
2357                 hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
2358
2359                 /* allocate vectors for body and dynamic areas */
2360                 req->in.vector = talloc_realloc(req, req->in.vector,
2361                                                 struct iovec,
2362                                                 req->in.vector_count + 2);
2363                 if (req->in.vector == NULL) {
2364                         return -1;
2365                 }
2366                 req->in.vector_count += 2;
2367
2368                 full_size = state->missing + SMB2_HDR_BODY + 2;
2369                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
2370                 body_size = SVAL(hdr, SMB2_HDR_BODY);
2371
2372                 if (next_command_ofs != 0) {
2373                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
2374                                 /*
2375                                  * this is invalid, just return a zero
2376                                  * body and let the caller deal with the error
2377                                  */
2378                                 invalid = true;
2379                         } else if (next_command_ofs > full_size) {
2380                                 /*
2381                                  * this is invalid, just return a zero
2382                                  * body and let the caller deal with the error
2383                                  */
2384                                 invalid = true;
2385                         } else {
2386                                 full_size = next_command_ofs;
2387                         }
2388                 }
2389
2390                 if (!invalid) {
2391                         if (body_size < 2) {
2392                                 /*
2393                                  * this is invalid, just return a zero
2394                                  * body and let the caller deal with the error
2395                                  */
2396                                 invalid = true;
2397                         }
2398
2399                         /*
2400                          * Mask out the lowest bit, the "dynamic" part
2401                          * of body_size.
2402                          */
2403                         body_size &= ~1;
2404
2405                         if (body_size > (full_size - SMB2_HDR_BODY)) {
2406                                 /*
2407                                  * this is invalid, just return a zero
2408                                  * body and let the caller deal with the error
2409                                  */
2410                                 invalid = true;
2411                         }
2412                 }
2413
2414                 if (invalid) {
2415                         /* the caller should check this */
2416                         body_size = 2;
2417                 }
2418
2419                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
2420
2421                 state->missing -= (body_size - 2) + dyn_size;
2422
2423                 body = talloc_array(req->in.vector, uint8_t, body_size);
2424                 if (body == NULL) {
2425                         return -1;
2426                 }
2427
2428                 dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
2429                 if (dyn == NULL) {
2430                         return -1;
2431                 }
2432
2433                 req->in.vector[idx].iov_base    = (void *)body;
2434                 req->in.vector[idx].iov_len     = body_size;
2435                 req->in.vector[idx+1].iov_base  = (void *)dyn;
2436                 req->in.vector[idx+1].iov_len   = dyn_size;
2437
2438                 vector = talloc_array(mem_ctx, struct iovec, 2);
2439                 if (vector == NULL) {
2440                         return -1;
2441                 }
2442
2443                 /*
2444                  * the first 2 bytes of the body were already fetched
2445                  * together with the header
2446                  */
2447                 memcpy(body, hdr + SMB2_HDR_BODY, 2);
2448                 vector[0].iov_base = body + 2;
2449                 vector[0].iov_len = body_size - 2;
2450
2451                 vector[1] = req->in.vector[idx+1];
2452
2453                 *_vector = vector;
2454                 *_count = 2;
2455                 return 0;
2456         }
2457
2458         /*
2459          * when we endup here, we're looking for a new SMB2 request
2460          * next. And we ask for its header and the first 2 bytes of
2461          * the body (like we did for the first SMB2 request).
2462          */
2463
2464         req->in.vector = talloc_realloc(req, req->in.vector,
2465                                         struct iovec,
2466                                         req->in.vector_count + 1);
2467         if (req->in.vector == NULL) {
2468                 return -1;
2469         }
2470         req->in.vector_count += 1;
2471
2472         /*
2473          * We assume it's a SMB2 request,
2474          * and we first get the header and the
2475          * first 2 bytes (the struct size) of the body
2476          */
2477         len = SMB2_HDR_BODY + 2;
2478
2479         if (len > state->missing) {
2480                 /* let the caller handle the error */
2481                 len = state->missing;
2482         }
2483
2484         state->missing -= len;
2485         state->asked_for_header = true;
2486
2487         buf = talloc_array(req->in.vector, uint8_t, len);
2488         if (buf == NULL) {
2489                 return -1;
2490         }
2491
2492         req->in.vector[idx].iov_base    = (void *)buf;
2493         req->in.vector[idx].iov_len     = len;
2494
2495         vector = talloc_array(mem_ctx, struct iovec, 1);
2496         if (vector == NULL) {
2497                 return -1;
2498         }
2499
2500         vector[0] = req->in.vector[idx];
2501
2502         *_vector = vector;
2503         *_count = 1;
2504         return 0;
2505 }
2506
2507 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
2508 {
2509         struct tevent_req *req =
2510                 tevent_req_callback_data(subreq,
2511                 struct tevent_req);
2512         int ret;
2513         int sys_errno;
2514         NTSTATUS status;
2515
2516         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
2517         if (ret == -1) {
2518                 status = map_nt_error_from_unix(sys_errno);
2519                 tevent_req_nterror(req, status);
2520                 return;
2521         }
2522
2523         tevent_req_done(req);
2524 }
2525
2526 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
2527                                             TALLOC_CTX *mem_ctx,
2528                                             struct smbd_smb2_request **_smb2_req)
2529 {
2530         struct smbd_smb2_request_read_state *state =
2531                 tevent_req_data(req,
2532                 struct smbd_smb2_request_read_state);
2533         NTSTATUS status;
2534
2535         if (tevent_req_is_nterror(req, &status)) {
2536                 tevent_req_received(req);
2537                 return status;
2538         }
2539
2540         talloc_steal(mem_ctx, state->smb2_req->mem_pool);
2541         *_smb2_req = state->smb2_req;
2542         tevent_req_received(req);
2543         return NT_STATUS_OK;
2544 }
2545
2546 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
2547
2548 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2549 {
2550         size_t max_send_queue_len;
2551         size_t cur_send_queue_len;
2552         struct tevent_req *subreq;
2553
2554         if (sconn->smb2.compound_related_in_progress) {
2555                 /*
2556                  * Can't read another until the related
2557                  * compound is done.
2558                  */
2559                 return NT_STATUS_OK;
2560         }
2561
2562         if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
2563                 /*
2564                  * if there is already a smbd_smb2_request_read
2565                  * pending, we are done.
2566                  */
2567                 return NT_STATUS_OK;
2568         }
2569
2570         max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2571         cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
2572
2573         if (cur_send_queue_len > max_send_queue_len) {
2574                 /*
2575                  * if we have a lot of requests to send,
2576                  * we wait until they are on the wire until we
2577                  * ask for the next request.
2578                  */
2579                 return NT_STATUS_OK;
2580         }
2581
2582         /* ask for the next request */
2583         subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
2584         if (subreq == NULL) {
2585                 return NT_STATUS_NO_MEMORY;
2586         }
2587         tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
2588
2589         return NT_STATUS_OK;
2590 }
2591
2592 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2593                              const uint8_t *inbuf, size_t size)
2594 {
2595         NTSTATUS status;
2596         struct smbd_smb2_request *req = NULL;
2597
2598         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2599                  (unsigned int)size));
2600
2601         status = smbd_initialize_smb2(sconn);
2602         if (!NT_STATUS_IS_OK(status)) {
2603                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2604                 return;
2605         }
2606
2607         status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2608         if (!NT_STATUS_IS_OK(status)) {
2609                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2610                 return;
2611         }
2612
2613         status = smbd_smb2_request_setup_out(req);
2614         if (!NT_STATUS_IS_OK(status)) {
2615                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2616                 return;
2617         }
2618
2619         status = smbd_smb2_request_dispatch(req);
2620         if (!NT_STATUS_IS_OK(status)) {
2621                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2622                 return;
2623         }
2624
2625         status = smbd_smb2_request_next_incoming(sconn);
2626         if (!NT_STATUS_IS_OK(status)) {
2627                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2628                 return;
2629         }
2630
2631         sconn->num_requests++;
2632 }
2633
2634 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
2635 {
2636         struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
2637                                                struct smbd_server_connection);
2638         NTSTATUS status;
2639         struct smbd_smb2_request *req = NULL;
2640
2641         status = smbd_smb2_request_read_recv(subreq, sconn, &req);
2642         TALLOC_FREE(subreq);
2643         if (!NT_STATUS_IS_OK(status)) {
2644                 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
2645                         nt_errstr(status)));
2646                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2647                 return;
2648         }
2649
2650         if (req->in.nbt_hdr[0] != 0x00) {
2651                 DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
2652                          req->in.nbt_hdr[0]));
2653                 TALLOC_FREE(req);
2654                 goto next;
2655         }
2656
2657         req->current_idx = 1;
2658
2659         DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
2660                  req->current_idx, req->in.vector_count));
2661
2662         status = smbd_smb2_request_validate(req);
2663         if (!NT_STATUS_IS_OK(status)) {
2664                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2665                 return;
2666         }
2667
2668         status = smbd_smb2_request_setup_out(req);
2669         if (!NT_STATUS_IS_OK(status)) {
2670                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2671                 return;
2672         }
2673
2674         status = smbd_smb2_request_dispatch(req);
2675         if (!NT_STATUS_IS_OK(status)) {
2676                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2677                 return;
2678         }
2679
2680 next:
2681         status = smbd_smb2_request_next_incoming(sconn);
2682         if (!NT_STATUS_IS_OK(status)) {
2683                 smbd_server_connection_terminate(sconn, nt_errstr(status));
2684                 return;
2685         }
2686
2687         sconn->num_requests++;
2688
2689         /* The timeout_processing function isn't run nearly
2690            often enough to implement 'max log size' without
2691            overrunning the size of the file by many megabytes.
2692            This is especially true if we are running at debug
2693            level 10.  Checking every 50 SMB2s is a nice
2694            tradeoff of performance vs log file size overrun. */
2695
2696         if ((sconn->num_requests % 50) == 0 &&
2697             need_to_check_log_size()) {
2698                 change_to_root_user();
2699                 check_log_size();
2700         }
2701 }