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