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