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