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