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