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