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