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