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