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