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