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